diff options
579 files changed, 25873 insertions, 18469 deletions
@@ -2055,6 +2055,7 @@ asmcomp/asmgen.cmo : \ asmcomp/printlinear.cmi \ asmcomp/printcmm.cmi \ typing/primitive.cmi \ + asmcomp/polling.cmi \ utils/misc.cmi \ asmcomp/mach.cmi \ parsing/location.cmi \ @@ -2095,6 +2096,7 @@ asmcomp/asmgen.cmx : \ asmcomp/printlinear.cmx \ asmcomp/printcmm.cmx \ typing/primitive.cmx \ + asmcomp/polling.cmx \ utils/misc.cmx \ asmcomp/mach.cmx \ parsing/location.cmx \ @@ -2466,6 +2468,7 @@ asmcomp/emit.cmo : \ lambda/lambda.cmi \ asmcomp/emitaux.cmi \ utils/domainstate.cmi \ + lambda/debuginfo.cmi \ utils/config.cmi \ middle_end/compilenv.cmi \ asmcomp/cmm.cmi \ @@ -2488,6 +2491,7 @@ asmcomp/emit.cmx : \ lambda/lambda.cmx \ asmcomp/emitaux.cmx \ utils/domainstate.cmx \ + lambda/debuginfo.cmx \ utils/config.cmx \ middle_end/compilenv.cmx \ asmcomp/cmm.cmx \ @@ -2643,6 +2647,20 @@ asmcomp/mach.cmi : \ asmcomp/cmm.cmi \ middle_end/backend_var.cmi \ asmcomp/arch.cmo +asmcomp/polling.cmo : \ + asmcomp/reg.cmi \ + asmcomp/mach.cmi \ + lambda/debuginfo.cmi \ + asmcomp/cmm.cmi \ + asmcomp/polling.cmi +asmcomp/polling.cmx : \ + asmcomp/reg.cmx \ + asmcomp/mach.cmx \ + lambda/debuginfo.cmx \ + asmcomp/cmm.cmx \ + asmcomp/polling.cmi +asmcomp/polling.cmi : \ + asmcomp/mach.cmi asmcomp/printcmm.cmo : \ utils/targetint.cmi \ lambda/lambda.cmi \ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000000..2b1a968c28 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,31 @@ +name: main + +on: [push, pull_request] + +jobs: + build: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - name: linux-debug + os: ubuntu-latest + env: OCAMLRUNPARAM=v=0,V=1 USE_RUNTIME=d + - name: linux + os: ubuntu-latest + - name: macos + os: macos-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: configure tree + run: | + MAKE_ARG=-j XARCH=x64 bash -xe tools/ci/actions/runner.sh configure + - name: Build + run: | + MAKE_ARG=-j bash -xe tools/ci/actions/runner.sh build + - name: Run the testsuite + run: | + ${{ matrix.env }} bash -xe tools/ci/actions/runner.sh test diff --git a/.gitignore b/.gitignore index afac70dab9..21192ae276 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ *.out.dSYM *.swp _ocamltest +.vscode _ocamltestd *.odoc .merlin @@ -212,6 +213,7 @@ _build /testsuite/failure.stamp /testsuite/_retries +/testsuite/disabled-dirs /testsuite/tools/codegen diff --git a/.gitmodules b/.gitmodules index dca1e0d28f..e69de29bb2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "flexdll"] - path = flexdll - url = https://github.com/alainfrisch/flexdll.git diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0e5145065a..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,71 +0,0 @@ -#************************************************************************** -#* * -#* OCaml * -#* * -#* Anil Madhavapeddy, OCaml Labs * -#* * -#* Copyright 2014 Institut National de Recherche en Informatique et * -#* en Automatique. * -#* * -#* All rights reserved. This file is distributed under the terms of * -#* the GNU Lesser General Public License version 2.1, with the * -#* special exception on linking described in the file LICENSE. * -#* * -#************************************************************************** - -dist: bionic -language: c -git: - submodules: false -script: tools/ci/travis/travis-ci.sh -matrix: - include: - - env: >- - CI_KIND=build - XARCH=x64 - CONFIG_ARG=--enable-flambda - OCAMLRUNPARAM=b,v=0 - - env: >- - CI_KIND=build - XARCH=i386 - CONFIG_ARG=--disable-stdlib-manpages - addons: - apt: - packages: - - gcc-multilib - - env: >- - CI_KIND=build - XARCH=x64 - addons: - apt: - packages: - - texlive-latex-extra - - texlive-fonts-recommended - - env: >- - CI_KIND=build - XARCH=x64 - CONFIG_ARG=--disable-shared - - env: >- - CI_KIND=build - XARCH=x64 - MIN_BUILD=1 - - env: >- - CI_KIND=build - XARCH=x64 - CONFIG_ARG=--enable-dependency-generation - MAKE_ARG=-j - - env: CI_KIND=check-depend - - env: CI_KIND=changes - - env: CI_KIND=manual - - env: CI_KIND=check-typo -# - env: CI_KIND=tests -# allow_failures: -# - env: CI_KIND=tests -addons: - apt: - packages: - - binutils-dev - -notifications: - email: - - ocaml-ci-notifications@inria.fr diff --git a/Makefile.config.in b/Makefile.config.in index 35fd7aedda..fe546da534 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -227,6 +227,7 @@ WITH_SPACETIME=@spacetime@ ENABLE_CALL_COUNTS=@call_counts@ WITH_PROFINFO=@profinfo@ PROFINFO_WIDTH=@profinfo_width@ +COLLECT_STATS=@collect_stats@ LIBUNWIND_AVAILABLE=@libunwind_available@ LIBUNWIND_INCLUDE_FLAGS=@libunwind_include_flags@ LIBUNWIND_LINK_FLAGS=@libunwind_link_flags@ diff --git a/README.md b/README.md new file mode 100644 index 0000000000..864a9d0cae --- /dev/null +++ b/README.md @@ -0,0 +1,43 @@ +# Multicore OCaml + +A concurrent and shared-memory parallel extension of the OCaml compiler. + +Multicore OCaml cleanly separates abstractions for concurrency (overlapped +execution) from parallelism (simultaneous execution). Concurrency is expressed +through [effect handlers](http://kcsrk.info/papers/system_effects_feb_18.pdf) +and parallelism through +[domains](https://github.com/ocaml-multicore/ocaml-multicore/blob/master/stdlib/domain.mli). +Much of the work in supporting shared memory parallelism is the development of a +mostly-concurrent, generational, mark-and-sweep collector that strikes a balance +between single-threaded performance and feature backwards compatibility, and +multicore scalability. + +See the +[wiki](https://github.com/ocaml-multicore/ocaml-multicore/wiki) for more +resources. + +## Variants + +* **Parallel Minor GC (default)** -- A variant that performs stop-the-world parallel + minor collection. The branch is + [`parallel_minor_gc`](https://github.com/ocaml-multicore/ocaml-multicore/tree/parallel_minor_gc). +* **Concurrent Minor GC** -- A variant that garbage collects each domain's minor + heap concurrently. The branch is [`master`](https://github.com/ocaml-multicore/ocaml-multicore/tree/master). +* **Parallel Minor GC + No effect syntax** -- This branch does not have syntax + extension for effects (but includes the compiler and runtime system changes). + The branch is + [`no-effect-syntax`](https://github.com/ocaml-multicore/ocaml-multicore/tree/no-effect-syntax). + This branch is useful to install ppx libraries. + +## Installation + +If you want to try out Multicore OCaml, the easiest way is to install the compiler using [OPAM](https://github.com/ocaml-multicore/multicore-opam#install-multicore-ocaml). + +Parallel programming examples are available in the [domainslib](https://github.com/ocaml-multicore/domainslib/tree/master/test) library. + +Effect handler (concurrent programming) examples are available in [effects-examples](https://github.com/kayceesrk/effects-examples) repo. + +## Notes + +The original README.adoc file has been moved to +[README.stock.adoc](README.stock.adoc). diff --git a/README.adoc b/README.stock.adoc index 1af0b70462..1af0b70462 100644 --- a/README.adoc +++ b/README.stock.adoc @@ -1,4 +1,4 @@ -4.12.0+dev0-2020-04-22 +4.12.0+multicore+dev0-2020-04-22 # The version string is the first line of this file. # It must be in the format described in stdlib/sys.mli diff --git a/asmcomp/CSEgen.ml b/asmcomp/CSEgen.ml index d71198adda..b57822c699 100644 --- a/asmcomp/CSEgen.ml +++ b/asmcomp/CSEgen.ml @@ -236,6 +236,9 @@ method class_of_operation op = | Ifloatofint | Iintoffloat -> Op_pure | Ispecific _ -> Op_other | Iname_for_debugger _ -> Op_pure + | Ipoll -> Op_checkbound + | Inop -> Op_store true (* not correct, but enough to force CSE from leaving + nops alone *) (* Operations that are so cheap that it isn't worth factoring them. *) diff --git a/asmcomp/afl_instrument.ml b/asmcomp/afl_instrument.ml index c89fcf1ed7..9c21154e5d 100644 --- a/asmcomp/afl_instrument.ml +++ b/asmcomp/afl_instrument.ml @@ -42,13 +42,13 @@ let rec with_afl_logging b dbg = let afl_area = V.create_local "shared_mem" in let op oper args = Cop (oper, args, dbg) in Clet(VP.create afl_area, - op (Cload (Word_int, Asttypes.Mutable)) [afl_area_ptr dbg], - Clet(VP.create cur_pos, op Cxor [op (Cload (Word_int, Asttypes.Mutable)) + op (Cload ({memory_chunk=Word_int; mutability=Asttypes.Mutable; is_atomic=false})) [afl_area_ptr dbg], + Clet(VP.create cur_pos, op Cxor [op (Cload {memory_chunk=Word_int; mutability=Asttypes.Mutable; is_atomic=false}) [afl_prev_loc dbg]; Cconst_int (cur_location, dbg)], Csequence( op (Cstore(Byte_unsigned, Assignment)) [op Cadda [Cvar afl_area; Cvar cur_pos]; - op Cadda [op (Cload (Byte_unsigned, Asttypes.Mutable)) + op Cadda [op (Cload {memory_chunk=Byte_unsigned; mutability=Asttypes.Mutable; is_atomic=false}) [op Cadda [Cvar afl_area; Cvar cur_pos]]; Cconst_int (1, dbg)]], op (Cstore(Word_int, Assignment)) diff --git a/asmcomp/amd64/emit.mlp b/asmcomp/amd64/emit.mlp index d9c5eb6e68..a2c6d23f68 100644 --- a/asmcomp/amd64/emit.mlp +++ b/asmcomp/amd64/emit.mlp @@ -62,6 +62,15 @@ let cfi_endproc () = let cfi_adjust_cfa_offset n = if Config.asm_cfi_supported then D.cfi_adjust_cfa_offset n +let cfi_remember_state () = + if Config.asm_cfi_supported then D.cfi_remember_state () + +let cfi_restore_state () = + if Config.asm_cfi_supported then D.cfi_restore_state () + +let cfi_def_cfa_register reg = + if Config.asm_cfi_supported then D.cfi_def_cfa_register reg + let emit_debug_info dbg = emit_debug_info_gen dbg D.file D.loc @@ -74,6 +83,8 @@ let fastcode_flag = ref true (* Layout of the stack frame *) let stack_offset = ref 0 +let stack_threshold_size = Config.stack_threshold * 8 (* bytes *) + let num_stack_slots = Array.make Proc.num_register_classes 0 let prologue_required = ref false @@ -292,24 +303,37 @@ let spacetime_before_uninstrumented_call ~node_ptr ~index = (* Record calls to the GC -- we've moved them out of the way *) type gc_call = - { gc_lbl: label; (* Entry label *) + { gc_size: int; (* Allocation size, in bytes *) + gc_lbl: label; (* Entry label *) gc_return_lbl: label; (* Where to branch after GC *) gc_frame: label; (* Label of frame descriptor *) gc_spacetime : (X86_ast.arg * int) option; (* Spacetime node hole pointer and index *) + is_poll : bool } let call_gc_sites = ref ([] : gc_call list) let emit_call_gc gc = def_label gc.gc_lbl; + (* TODO KC: begin match gc.gc_spacetime with | None -> assert (not Config.spacetime) | Some (node_ptr, index) -> assert Config.spacetime; spacetime_before_uninstrumented_call ~node_ptr ~index end; - emit_call "caml_call_gc"; + *) + if gc.is_poll then begin + emit_call "caml_call_poll" + end else begin + match gc.gc_size with + | 16 -> emit_call "caml_call_gc1" + | 24 -> emit_call "caml_call_gc2" + | 32 -> emit_call "caml_call_gc3" + | n -> I.add (int n) r15; + emit_call "caml_call_gc" + end; def_label gc.gc_frame; I.jmp (label gc.gc_return_lbl) @@ -335,11 +359,11 @@ let bound_error_label ?label dbg ~spacetime = bound_error_sites := { bd_lbl = lbl_bound_error; bd_frame = lbl_frame; bd_spacetime = spacetime; } :: !bound_error_sites; - lbl_bound_error - end else begin - if !bound_error_call = 0 then bound_error_call := new_label(); - !bound_error_call - end + lbl_bound_error + end else begin + if !bound_error_call = 0 then bound_error_call := new_label(); + !bound_error_call + end let emit_call_bound_error bd = def_label bd.bd_lbl; @@ -566,64 +590,95 @@ let emit_instr fallthrough i = I.mov (nat n) (res i 0) | Lop(Iconst_float f) -> begin match f with - | 0x0000_0000_0000_0000L -> (* +0.0 *) - I.xorpd (res i 0) (res i 0) - | _ -> - let lbl = add_float_constant f in - I.movsd (mem64_rip NONE (emit_label lbl)) (res i 0) + | 0x0000_0000_0000_0000L -> (* +0.0 *) + I.xorpd (res i 0) (res i 0) + | _ -> + let lbl = add_float_constant f in + I.movsd (mem64_rip NONE (emit_label lbl)) (res i 0) end | Lop(Iconst_symbol s) -> add_used_symbol s; load_symbol_addr s (res i 0) | Lop(Icall_ind { label_after; }) -> + if Config.stats then begin + I.inc (domain_field Domainstate.Domain_call_ind); + end; I.call (arg i 0); record_frame i.live (Dbg_other i.dbg) ~label:label_after | Lop(Icall_imm { func; label_after; }) -> + if Config.stats then begin + I.inc (domain_field Domainstate.Domain_call_imm); + end; add_used_symbol func; emit_call func; record_frame i.live (Dbg_other i.dbg) ~label:label_after - | Lop(Itailcall_ind { label_after; }) -> + | Lop(Itailcall_ind { label_after = _; }) -> output_epilogue begin fun () -> - I.jmp (arg i 0); - if Config.spacetime then begin - record_frame Reg.Set.empty (Dbg_other i.dbg) ~label:label_after - end + if Config.stats then begin + I.inc (domain_field Domainstate.Domain_tailcall_ind); + end; + I.jmp (arg i 0); + (* TODO KC: Spacetime + if Config.spacetime then begin + record_frame Reg.Set.empty (Dbg_other i.dbg) ~label:label_after + end + *) end - | Lop(Itailcall_imm { func; label_after; }) -> + | Lop(Itailcall_imm { func; }) -> begin - if func = !function_name then + if func = !function_name then begin + if Config.stats then begin + I.inc (domain_field Domainstate.Domain_tailcall_imm); + end; I.jmp (label !tailrec_entry_point) - else begin + end else begin output_epilogue begin fun () -> - add_used_symbol func; - emit_jump func + if Config.stats then begin + I.inc (domain_field Domainstate.Domain_tailcall_imm) + end; + add_used_symbol func; + emit_jump func + end end + end; + (* FIXME KC: + if Config.spacetime then begin + record_frame Reg.Set.empty (Dbg_other i.dbg) ~label:label_after end - end; - if Config.spacetime then begin - record_frame Reg.Set.empty (Dbg_other i.dbg) ~label:label_after - end - | Lop(Iextcall { func; alloc; label_after; }) -> + *) + | Lop(Iextcall {func; alloc; stack_ofs; label_after}) -> add_used_symbol func; - if alloc then begin + if stack_ofs > 0 then begin + I.lea (mem64 QWORD 0 RSP) r13; + I.lea (mem64 QWORD stack_ofs RSP) r12; + load_symbol_addr func rax; + emit_call "caml_c_call_stack_args"; + record_frame i.live (Dbg_other i.dbg) ~label:label_after; + if Config.stats then begin + I.inc (domain_field Domainstate.Domain_extcall_alloc_stackargs) + end; + end else if alloc then begin load_symbol_addr func rax; emit_call "caml_c_call"; record_frame i.live (Dbg_other i.dbg) ~label:label_after; - if system <> S_win64 then begin - (* TODO: investigate why such a diff. - This comes from: - http://caml.inria.fr/cgi-bin/viewvc.cgi?view=revision&revision=12664 - - If we do the same for Win64, we probably need to change - amd64nt.asm accordingly. - *) - I.mov (domain_field Domainstate.Domain_young_ptr) r15 - end + if Config.stats then begin + I.inc (domain_field Domainstate.Domain_extcall_alloc) + end; end else begin + I.mov rsp rbp; + if Config.stats then begin + I.inc (domain_field Domainstate.Domain_extcall_noalloc); + end; + cfi_remember_state (); + cfi_def_cfa_register "rbp"; + (* NB: gdb has asserts on contiguous stacks that mean it + will not unwind through this unless we were to tag this + calling frame with cfi_signal_frame in it's definition. *) + I.mov (domain_field Domainstate.Domain_c_stack) rsp; + emit_call func; - if Config.spacetime then begin - record_frame Reg.Set.empty (Dbg_other i.dbg) ~label:label_after - end + I.mov rbp rsp; + cfi_restore_state (); end | Lop(Istackoffset n) -> if n < 0 @@ -655,7 +710,10 @@ let emit_instr fallthrough i = | Double | Double_u -> I.movsd (addressing addr REAL8 i 0) dest end - | Lop(Istore(chunk, addr, _)) -> + | Lop(Istore(chunk, addr, is_assignment)) -> + if Config.stats && is_assignment then begin + I.inc (domain_field Domainstate.Domain_immutable_stores); + end; begin match chunk with | Word_int | Word_val -> I.mov (arg i 0) (addressing addr QWORD i 1) @@ -671,44 +729,56 @@ let emit_instr fallthrough i = | Double | Double_u -> I.movsd (arg i 0) (addressing addr REAL8 i 1) end - | Lop(Ialloc { bytes = n; label_after_call_gc; spacetime_index; dbginfo }) -> - assert (n <= (Config.max_young_wosize + 1) * Arch.size_addr); + | Lop(Ialloc { bytes = n; label_after_call_gc; spacetime_index; }) -> + (* TODO Spacetime *) if !fastcode_flag then begin + let lbl_redo = new_label() in + def_label lbl_redo; I.sub (int n) r15; + if Config.stats then begin + I.inc (domain_field Domainstate.Domain_allocations); + end; I.cmp (domain_field Domainstate.Domain_young_limit) r15; let lbl_call_gc = new_label() in + let dbg = + if not Config.spacetime then Debuginfo.none + else i.dbg + in let lbl_frame = - record_frame_label ?label:label_after_call_gc i.live (Dbg_alloc dbginfo) + record_frame_label ?label:label_after_call_gc i.live (Dbg_other dbg) in I.jb (label lbl_call_gc); - let lbl_after_alloc = new_label() in - def_label lbl_after_alloc; I.lea (mem64 NONE 8 R15) (res i 0); let gc_spacetime = if not Config.spacetime then None else Some (arg i 0, spacetime_index) in call_gc_sites := - { gc_lbl = lbl_call_gc; - gc_return_lbl = lbl_after_alloc; + { gc_size = n; + gc_lbl = lbl_call_gc; + gc_return_lbl = lbl_redo; gc_frame = lbl_frame; - gc_spacetime; } :: !call_gc_sites + gc_spacetime; + is_poll = false } :: !call_gc_sites end else begin + if Config.stats then begin + I.inc (domain_field Domainstate.Domain_allocations); + end; if Config.spacetime then begin - spacetime_before_uninstrumented_call ~node_ptr:(arg i 0) - ~index:spacetime_index; + (* spacetime_before_uninstrumented_call ~node_ptr:(arg i 0) + ~index:spacetime_index; *) + () end; begin match n with | 16 -> emit_call "caml_alloc1" | 24 -> emit_call "caml_alloc2" | 32 -> emit_call "caml_alloc3" | _ -> - I.sub (int n) r15; - emit_call "caml_allocN" + I.mov (int n) rax; + emit_call "caml_allocN" end; let label = - record_frame_label ?label:label_after_call_gc i.live - (Dbg_alloc dbginfo) + record_frame_label ?label:label_after_call_gc i.live (Dbg_other i.dbg) in def_label label; I.lea (mem64 NONE 8 R15) (res i 0) @@ -797,6 +867,24 @@ let emit_instr fallthrough i = | Lop(Ispecific(Izextend32)) -> I.mov (arg32 i 0) (res32 i 0) | Lop (Iname_for_debugger _) -> () + | Lop (Inop) -> I.nop () + | Lop (Ipoll) -> + I.cmp (domain_field Domainstate.Domain_young_limit) r15; + let gc_call_label = new_label () in + let label_after_gc = new_label () in + let lbl_frame = + record_frame_label ?label:None i.live (Dbg_other i.dbg) + in + I.jb (label gc_call_label); + call_gc_sites := + { gc_size = 0; + gc_lbl = gc_call_label; + gc_return_lbl = label_after_gc; + gc_frame = lbl_frame; + gc_spacetime = None ; + is_poll = true } :: !call_gc_sites; + def_label label_after_gc; + () | Lreloadretaddr -> () | Lreturn -> @@ -860,7 +948,6 @@ let emit_instr fallthrough i = if i.arg.(0).loc = Reg 0 (* rax *) then (phys_reg 4 (*rdx*), phys_reg 0 (*rax*)) else (phys_reg 0 (*rax*), phys_reg 4 (*rdx*)) in - I.lea (mem64_rip NONE lbl) (reg tmp1); I.movsxd (mem64 DWORD 0 (arg64 i 0) ~scale:4 ~base:(reg64 tmp1)) (reg tmp2); @@ -894,14 +981,14 @@ let emit_instr fallthrough i = I.mov (sym (emit_label s)) arg in load_label_addr lbl_handler r11; - I.push r11; cfi_adjust_cfa_offset 8; - I.push (domain_field Domainstate.Domain_exception_pointer); + I.push r11; cfi_adjust_cfa_offset 8; - I.mov rsp (domain_field Domainstate.Domain_exception_pointer); - stack_offset := !stack_offset + 16; + I.push (domain_field Domainstate.Domain_exn_handler); + I.mov rsp (domain_field Domainstate.Domain_exn_handler); + stack_offset := !stack_offset + 16 | Lpoptrap -> - I.pop (domain_field Domainstate.Domain_exception_pointer); + I.pop (domain_field Domainstate.Domain_exn_handler); cfi_adjust_cfa_offset (-8); I.add (int 8) rsp; cfi_adjust_cfa_offset (-8); @@ -912,15 +999,14 @@ let emit_instr fallthrough i = trie is [caml_stash_backtrace], and it does not. *) begin match k with | Lambda.Raise_regular -> - I.mov (int 0) (domain_field Domainstate.Domain_backtrace_pos); emit_call "caml_raise_exn"; record_frame Reg.Set.empty (Dbg_raise i.dbg) | Lambda.Raise_reraise -> - emit_call "caml_raise_exn"; + emit_call "caml_reraise_exn"; record_frame Reg.Set.empty (Dbg_raise i.dbg) | Lambda.Raise_notrace -> - I.mov (domain_field Domainstate.Domain_exception_pointer) rsp; - I.pop (domain_field Domainstate.Domain_exception_pointer); + I.mov (domain_field Domainstate.Domain_exn_handler) rsp; + I.pop (domain_field Domainstate.Domain_exn_handler); I.pop r11; I.jmp r11 end @@ -932,8 +1018,53 @@ let rec emit_all fallthrough i = emit_instr fallthrough i; emit_all (Linear.has_fallthrough i.desc) i.next + let all_functions = ref [] + +type preproc_fun_result = + {max_stack_size : int; + contains_nontail_calls : bool; + contains_external_calls : bool} + +let preproc_fun fun_body _fun_name = + let rec proc_instr r a i = + if i.desc = Lend then r else + let upd_size r delta = + {r with max_stack_size = max r.max_stack_size (a+delta)} + in + let (r',a') = match i.desc with + | Lop (Istackoffset n) -> (upd_size r n, a+n) + | Lpushtrap _ -> (upd_size r 16, a+16) + | Lpoptrap -> (r, a-16) + | Lop (Iextcall _ | Ialloc _ | Ipoll | Iintop (Icheckbound _) + | Iintop_imm (Icheckbound _, _)) -> + ({r with contains_external_calls = true; + (* +24 bytes for caml_context *) + max_stack_size = max r.max_stack_size (a+24)}, a) + | Lop (Icall_ind _ | Icall_imm _ ) -> + ({r with contains_nontail_calls = true}, a) + | _ -> (r, a) + in + proc_instr r' a' i.next + in + let fs = frame_size () in + let r = + {max_stack_size = fs; + contains_nontail_calls = false; + contains_external_calls = false} + in + proc_instr r fs fun_body + +let emit_block_header_for_closure () = + let not_markable = Nativeint.shift_left (Nativeint.of_int 3) 8 in + let header = + Nativeint.logor not_markable (Nativeint.of_int Obj.abstract_tag) + in + let open D in + qword (const_nat Nativeint.zero); + qword (const_nat header) + (* Emission of a function declaration *) let fundecl fundecl = @@ -953,6 +1084,7 @@ let fundecl fundecl = emit_named_text_section !function_name; D.align 16; add_def_symbol fundecl.fun_name; + emit_block_header_for_closure (); if system = S_macosx && not !Clflags.output_c_object && is_generic_function fundecl.fun_name @@ -963,9 +1095,36 @@ let fundecl fundecl = D.label (emit_symbol fundecl.fun_name); emit_debug_info fundecl.fun_dbg; cfi_startproc (); + if !Clflags.runtime_variant = "d" then + emit_call "caml_assert_stack_invariants"; + let { max_stack_size; contains_nontail_calls; contains_external_calls = _ } = + preproc_fun fundecl.fun_body fundecl.fun_name in + let handle_overflow = ref None in + if contains_nontail_calls || max_stack_size >= stack_threshold_size then begin + let (overflow,ret) = new_label(), new_label() in + let threshold_offset = Domainstate.stack_ctx_words * 8 + stack_threshold_size in + I.lea (mem64 NONE (-(max_stack_size + threshold_offset)) RSP) r10; + if Config.stats then begin + I.inc (domain_field Domainstate.Domain_stackoverflow_checks); + end; + I.cmp (domain_field Domainstate.Domain_current_stack) r10; + I.jb (label overflow); + def_label ret; + handle_overflow := Some (overflow, ret) + end; emit_all true fundecl.fun_body; List.iter emit_call_gc !call_gc_sites; emit_call_bound_errors (); + (match !handle_overflow with None -> () | Some (overflow,ret) -> begin + def_label overflow; + (* Pass the desired stack size on the stack, since all of the + argument-passing registers may be in use. + Also serves to align the stack properly before the call *) + I.push (int (Config.stack_threshold + max_stack_size / 8)); (* measured in words *) + emit_call "caml_call_realloc_stack"; + I.pop r10; (* ignored *) + I.jmp (label ret) + end); if !frame_required then begin let n = frame_size() - 8 - (if fp then 8 else 0) in if n <> 0 @@ -1016,6 +1175,9 @@ let begin_assembly() = used_labels := Int.Set.empty; if system = S_win64 then begin D.extrn "caml_call_gc" NEAR; + D.extrn "caml_call_gc1" NEAR; + D.extrn "caml_call_gc2" NEAR; + D.extrn "caml_call_gc3" NEAR; D.extrn "caml_c_call" NEAR; D.extrn "caml_allocN" NEAR; D.extrn "caml_alloc1" NEAR; @@ -1152,7 +1314,7 @@ let end_assembly() = if Config.spacetime then begin emit_spacetime_shapes () - end; + end; if system = S_linux then (* Mark stack as non-executable, PR#4564 *) diff --git a/asmcomp/amd64/proc.ml b/asmcomp/amd64/proc.ml index fe798e13f6..f82a7e41ac 100644 --- a/asmcomp/amd64/proc.ml +++ b/asmcomp/amd64/proc.ml @@ -288,37 +288,37 @@ let regs_are_volatile _rs = false (* Registers destroyed by operations *) let destroyed_at_c_call = + (* C calling conventions preserve rbp, but it is clobbered + by the code sequence used for C calls in emit.mlp, so it + is marked as destroyed. *) if win64 then - (* Win64: rbx, rbp, rsi, rdi, r12-r15, xmm6-xmm15 preserved *) + (* Win64: rbx, rsi, rdi, r12-r15, xmm6-xmm15 preserved *) Array.of_list(List.map phys_reg - [0;4;5;6;7;10;11; + [0;4;5;6;7;10;11;12; 100;101;102;103;104;105]) else - (* Unix: rbp, rbx, r12-r15 preserved *) + (* Unix: rbx, r12-r15 preserved *) Array.of_list(List.map phys_reg - [0;2;3;4;5;6;7;10;11; + [0;2;3;4;5;6;7;10;11;12; 100;101;102;103;104;105;106;107; 108;109;110;111;112;113;114;115]) -let destroyed_by_spacetime_at_alloc = - if Config.spacetime then - [| loc_spacetime_node_hole |] - else - [| |] - let destroyed_at_alloc = let regs = - if X86_proc.use_plt then - destroyed_by_plt_stub + if Config.spacetime then + [| rax; loc_spacetime_node_hole |] else - [| r11 |] + [| rax |] in - Array.concat [regs; destroyed_by_spacetime_at_alloc] + Array.concat [regs; destroyed_by_plt_stub] let destroyed_at_oper = function - Iop(Icall_ind _ | Icall_imm _ | Iextcall { alloc = true; }) -> - all_phys_regs - | Iop(Iextcall { alloc = false; }) -> destroyed_at_c_call + Iop(Icall_ind _ | Icall_imm _) -> + all_phys_regs + | Iop(Iextcall {alloc; stack_ofs; }) -> + assert (stack_ofs >= 0); + if alloc || stack_ofs > 0 then all_phys_regs + else destroyed_at_c_call | Iop(Iintop(Idiv | Imod)) | Iop(Iintop_imm((Idiv | Imod), _)) -> [| rax; rdx |] | Iop(Istore(Single, _, _)) -> [| rxmm15 |] @@ -372,7 +372,7 @@ let max_register_pressure = function let op_is_pure = function | Icall_ind _ | Icall_imm _ | Itailcall_ind _ | Itailcall_imm _ - | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _ + | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _ | Ipoll | Inop | Iintop(Icheckbound _) | Iintop_imm(Icheckbound _, _) -> false | Ispecific(Ilea _|Isextend32|Izextend32) -> true | Ispecific _ -> false diff --git a/asmcomp/amd64/selection.ml b/asmcomp/amd64/selection.ml index 3c0993f234..cbaeb72c78 100644 --- a/asmcomp/amd64/selection.ml +++ b/asmcomp/amd64/selection.ml @@ -199,7 +199,7 @@ method! select_operation op args dbg = self#select_floatarith false Idivf Ifloatdiv args | Cextcall("sqrt", _, _, false, _) -> begin match args with - [Cop(Cload ((Double|Double_u as chunk), _), [loc], _dbg)] -> + [Cop(Cload {memory_chunk=(Double|Double_u as chunk)}, [loc], _dbg)] -> let (addr, arg) = self#select_addressing chunk loc in (Ispecific(Ifloatsqrtf addr), [arg]) | [arg] -> @@ -250,11 +250,11 @@ method! select_operation op args dbg = method select_floatarith commutative regular_op mem_op args = match args with - [arg1; Cop(Cload ((Double|Double_u as chunk), _), [loc2], _)] -> + [arg1; Cop(Cload {memory_chunk=(Double|Double_u as chunk)}, [loc2], _)] -> let (addr, arg2) = self#select_addressing chunk loc2 in (Ispecific(Ifloatarithmem(mem_op, addr)), [arg1; arg2]) - | [Cop(Cload ((Double|Double_u as chunk), _), [loc1], _); arg2] + | [Cop(Cload {memory_chunk=(Double|Double_u as chunk)}, [loc1], _); arg2] when commutative -> let (addr, arg1) = self#select_addressing chunk loc1 in (Ispecific(Ifloatarithmem(mem_op, addr)), diff --git a/asmcomp/arm/selection.ml b/asmcomp/arm/selection.ml index d2ef29606b..7659ea87af 100644 --- a/asmcomp/arm/selection.ml +++ b/asmcomp/arm/selection.ml @@ -53,6 +53,7 @@ exception Use_default let r1 = phys_reg 1 let r6 = phys_reg 6 let r7 = phys_reg 7 +let r12 = phys_reg 8 let pseudoregs_for_operation op arg res = match op with @@ -265,9 +266,9 @@ method private select_operation_softfp op args dbg = [Cop(Cextcall(func, typ_int, [XFloat;XFloat], false, None), args, dbg)]) (* Add coercions around loads and stores of 32-bit floats *) - | (Cload (Single, mut), args) -> + | (Cload {memory_chunk=Single; mutability; is_atomic=false}, args) -> (self#iextcall "__aeabi_f2d" typ_float [XInt], - [Cop(Cload (Word_int, mut), args, dbg)]) + [Cop(Cload {memory_chunk=Word_int; mutability; is_atomic=false}, args, dbg)]) | (Cstore (Single, init), [arg1; arg2]) -> let arg2' = Cop(Cextcall("__aeabi_d2f", typ_int, [XFloat], false, None), diff --git a/asmcomp/arm64/emit.mlp b/asmcomp/arm64/emit.mlp index 96be20907c..bccb8872e0 100644 --- a/asmcomp/arm64/emit.mlp +++ b/asmcomp/arm64/emit.mlp @@ -33,12 +33,16 @@ let fastcode_flag = ref true (* Names for special regs *) -let reg_domain_state_ptr = phys_reg 22 -let reg_trap_ptr = phys_reg 23 -let reg_alloc_ptr = phys_reg 24 -let reg_alloc_limit = phys_reg 25 -let reg_tmp1 = phys_reg 26 -let reg_x15 = phys_reg 15 +let reg_trap_off = phys_reg 23 (* x26 *) +let reg_alloc_ptr = phys_reg 24 (* x27 *) +let reg_alloc_limit = phys_reg 25 (* x28 *) +let reg_tmp1 = phys_reg 26 (* x16 *) +let reg_tmp2 = phys_reg 27 (* x17 *) +let reg_x15 = phys_reg 15 (* x15*) +let reg_x19 = phys_reg 16 (* x19 *) +let reg_x20 = phys_reg 17 (* x20 *) +let reg_x0 = phys_reg 0 (* x19 *) +let reg_x1 = phys_reg 1 (* x20 *) (* Output a label *) @@ -70,6 +74,8 @@ let emit_wreg = function (* Layout of the stack frame *) +let stack_threshold_size = Config.stack_threshold * 8 (* bytes *) + let stack_offset = ref 0 let num_stack_slots = Array.make Proc.num_register_classes 0 @@ -126,7 +132,7 @@ let emit_addressing addr r = (* Record live pointers at call points *) -let record_frame_label ?label live dbg = +let record_frame_label ?label live raise_ dbg = let lbl = match label with | None -> new_label() @@ -144,23 +150,25 @@ let record_frame_label ?label live dbg = | _ -> ()) live; record_frame_descr ~label:lbl ~frame_size:(frame_size()) - ~live_offset:!live_offset dbg; + ~live_offset:!live_offset ~raise_frame:raise_ dbg; lbl -let record_frame ?label live dbg = - let lbl = record_frame_label ?label live dbg in `{emit_label lbl}:` +let record_frame ?label live raise_ dbg = + let lbl = record_frame_label ?label live raise_ dbg in `{emit_label lbl}:` (* Record calls to the GC -- we've moved them out of the way *) type gc_call = - { gc_lbl: label; (* Entry label *) + { gc_size: int; (* Allocation size, in bytes *) + gc_lbl: label; (* Entry label *) gc_return_lbl: label; (* Where to branch after GC *) gc_frame_lbl: label } (* Label of frame descriptor *) let call_gc_sites = ref ([] : gc_call list) let emit_call_gc gc = - `{emit_label gc.gc_lbl}: bl {emit_symbol "caml_call_gc"}\n`; + `{emit_label gc.gc_lbl}: add {emit_reg reg_alloc_ptr}, {emit_reg reg_alloc_ptr}, #{emit_int gc.gc_size}\n`; + ` bl {emit_symbol "caml_call_gc"}\n`; `{emit_label gc.gc_frame_lbl}: b {emit_label gc.gc_return_lbl}\n` (* Record calls to caml_ml_array_bound_error. @@ -176,7 +184,7 @@ let bound_error_sites = ref ([] : bound_error_call list) let bound_error_label ?label dbg = if !Clflags.debug || !bound_error_sites = [] then begin let lbl_bound_error = new_label() in - let lbl_frame = record_frame_label ?label Reg.Set.empty (Dbg_other dbg) in + let lbl_frame = record_frame_label ?label Reg.Set.empty false dbg in bound_error_sites := { bd_lbl = lbl_bound_error; bd_frame_lbl = lbl_frame } :: !bound_error_sites; @@ -189,6 +197,27 @@ let emit_call_bound_error bd = `{emit_label bd.bd_lbl}: bl {emit_symbol "caml_ml_array_bound_error"}\n`; `{emit_label bd.bd_frame_lbl}:\n` +(* read barrier calls *) + +type read_barrier_call = + { rb_base : Reg.t; (* Base register *) + rb_off : Reg.t; (* Offset register *) + rb_dest : Reg.t; (* Destination register *) + rb_lbl : label; (* Entry label *) + rb_return_lbl : label; (* Where to branch after read barrier *) + rb_frame : label } (* Label of frame descriptor *) + +let read_barrier_call_sites = ref ([] : read_barrier_call list) + +let emit_call_read_barrier rb = + `{emit_label rb.rb_lbl}:\n`; + ` mov {emit_reg reg_x0}, {emit_reg rb.rb_base}\n`; + ` mov {emit_reg reg_x1}, {emit_reg rb.rb_off}\n`; + ` bl {emit_symbol "caml_call_read_barrier"}\n`; + `{emit_label rb.rb_frame}:\n`; + ` mov {emit_reg rb.rb_dest}, {emit_reg reg_x0}\n`; + ` b {emit_label rb.rb_return_lbl}\n` + (* Names of various instructions *) let name_for_comparison = function @@ -446,8 +475,10 @@ module BR = Branch_relaxation.Make (struct | Lop (Itailcall_ind _) -> epilogue_size () | Lop (Itailcall_imm { func; _ }) -> if func = !function_name then 1 else epilogue_size () - | Lop (Iextcall { alloc = false; }) -> 1 - | Lop (Iextcall { alloc = true; }) -> 3 + | Lop (Iextcall { alloc ; stack_off; }) -> 1 + if stack_off > 0 then 5 + else if alloc then 3 + else 8 | Lop (Istackoffset _) -> 2 | Lop (Iload (size, addr)) | Lop (Istore (size, addr, _)) -> let based = match addr with Iindexed _ -> 0 | Ibased _ -> 1 in @@ -508,13 +539,12 @@ module BR = Branch_relaxation.Make (struct | Lpoptrap -> 1 | Lraise k -> begin match k with - | Lambda.Raise_regular -> 2 - | Lambda.Raise_reraise -> 1 - | Lambda.Raise_notrace -> 4 + | Cmm.Raise_withtrace -> 1 + | Cmm.Raise_notrace -> 5 end - let relax_allocation ~num_bytes ~label_after_call_gc ~dbginfo = - Lop (Ispecific (Ifar_alloc { bytes = num_bytes; label_after_call_gc; dbginfo })) + let relax_allocation ~num_bytes ~label_after_call_gc = + Lop (Ispecific (Ifar_alloc { bytes = num_bytes; label_after_call_gc; })) let relax_intop_checkbound ~label_after_error = Lop (Ispecific (Ifar_intop_checkbound { label_after_error; })) @@ -530,19 +560,22 @@ end) (* Output the assembly code for allocation. *) -let assembly_code_for_allocation ~label_after_call_gc i ~n ~far ~dbginfo = +let assembly_code_for_allocation ?label_after_call_gc i ~n ~far = let lbl_frame = - record_frame_label ?label:label_after_call_gc i.live (Dbg_alloc dbginfo) + record_frame_label ?label:label_after_call_gc i.live false i.dbg in if !fastcode_flag then begin - let lbl_after_alloc = new_label() in + let lbl_redo = new_label() in let lbl_call_gc = new_label() in - (* n is at most Max_young_whsize * 8, i.e. currently 0x808, - so it is reasonable to assume n < 0x1_000. This makes - the generated code simpler. *) - assert (16 <= n && n < 0x1_000 && n land 0x7 = 0); - ` sub {emit_reg reg_alloc_ptr}, {emit_reg reg_alloc_ptr}, #{emit_int n}\n`; + assert (n < 0x1_000_000); + let nl = n land 0xFFF and nh = n land 0xFFF_000 in + `{emit_label lbl_redo}:`; + if nh <> 0 then + ` sub {emit_reg reg_alloc_ptr}, {emit_reg reg_alloc_ptr}, #{emit_int nh}\n`; + if nl <> 0 then + ` sub {emit_reg reg_alloc_ptr}, {emit_reg reg_alloc_ptr}, #{emit_int nl}\n`; ` cmp {emit_reg reg_alloc_ptr}, {emit_reg reg_alloc_limit}\n`; + ` add {emit_reg i.res.(0)}, {emit_reg reg_alloc_ptr}, #8\n`; if not far then begin ` b.lo {emit_label lbl_call_gc}\n` end else begin @@ -551,11 +584,9 @@ let assembly_code_for_allocation ~label_after_call_gc i ~n ~far ~dbginfo = ` b {emit_label lbl_call_gc}\n`; `{emit_label lbl}:\n` end; - `{emit_label lbl_after_alloc}:`; - ` add {emit_reg i.res.(0)}, {emit_reg reg_alloc_ptr}, #8\n`; call_gc_sites := { gc_lbl = lbl_call_gc; - gc_return_lbl = lbl_after_alloc; + gc_return_lbl = lbl_redo; gc_frame_lbl = lbl_frame } :: !call_gc_sites end else begin begin match n with @@ -568,6 +599,13 @@ let assembly_code_for_allocation ~label_after_call_gc i ~n ~far ~dbginfo = `{emit_label lbl_frame}: add {emit_reg i.res.(0)}, {emit_reg reg_alloc_ptr}, #8\n` end +let load_domain_field f r = + let domain_field = Domainstate.idx_of_field f * 8 in + let bits = Domainstate.minor_heap_align_bits in + let dom_mask = Nativeint.(lognot (sub (shift_left one bits) one)) in + ` and {emit_reg r}, {emit_reg reg_alloc_ptr}, #{emit_nativeint dom_mask}\n`; + ` ldr {emit_reg r}, [{emit_reg r}, #{emit_int domain_field}]` + (* Output .text section directive, or named .text.caml.<name> if enabled. *) let emit_named_text_section func_name = @@ -636,23 +674,39 @@ let emit_instr i = emit_load_symbol_addr i.res.(0) s | Lop(Icall_ind { label_after; }) -> ` blr {emit_reg i.arg.(0)}\n`; - `{record_frame i.live (Dbg_other i.dbg) ~label:label_after}\n` + `{record_frame i.live false i.dbg ~label:label_after}\n` | Lop(Icall_imm { func; label_after; }) -> ` bl {emit_symbol func}\n`; - `{record_frame i.live (Dbg_other i.dbg) ~label:label_after}\n` + `{record_frame i.live false i.dbg ~label:label_after}\n` | Lop(Itailcall_ind { label_after = _; }) -> output_epilogue (fun () -> ` br {emit_reg i.arg.(0)}\n`) | Lop(Itailcall_imm { func; label_after = _; }) -> if func = !function_name then ` b {emit_label !tailrec_entry_point}\n` else - output_epilogue (fun () -> ` b {emit_symbol func}\n`) - | Lop(Iextcall { func; alloc = false; label_after = _; }) -> - ` bl {emit_symbol func}\n` - | Lop(Iextcall { func; alloc = true; label_after; }) -> - emit_load_symbol_addr reg_x15 func; - ` bl {emit_symbol "caml_c_call"}\n`; - `{record_frame i.live (Dbg_other i.dbg) ~label:label_after}\n` + output_epilogue (fun () -> ` b {emit_symbol s}\n`) + | Lop(Iextcall {func; alloc; stack_off; label_after}) -> + if stack_off > 0 then begin + ` mov {emit_reg reg_x19}, sp\n`; + ` add {emit_reg reg_x20}, sp, #{emit_int (Misc.align stack_off 16)}\n`; + emit_load_symbol_addr reg_x15 s; + ` bl {emit_symbol "caml_c_call_stack_args"}\n`; + `{record_frame i.live false i.dbg ~label:label_after}\n`; + end else if alloc then begin + emit_load_symbol_addr reg_x15 s; + ` bl {emit_symbol "caml_c_call"}\n`; + `{record_frame i.live false i.dbg ~label:label_after}\n`; + end else begin + ` mov {emit_reg reg_tmp1}, sp\n`; + `{load_domain_field Domainstate.Domain_system_sp reg_tmp2}\n`; + ` mov sp, {emit_reg reg_tmp2}\n`; + ` str {emit_reg reg_tmp1}, [sp, #-16]!\n`; + cfi_adjust_cfa_offset (16); + ` bl {emit_symbol s}\n`; + ` ldr {emit_reg reg_tmp1}, [sp], #16\n`; + cfi_adjust_cfa_offset (-16); + ` mov sp, {emit_reg reg_tmp1}\n`; + end | Lop(Istackoffset n) -> assert (n mod 16 = 0); emit_stack_adjustment (-n); @@ -665,7 +719,8 @@ let emit_instr i = | Ibased(s, ofs) -> assert (not !Clflags.dlcode); (* see selection.ml *) ` adrp {emit_reg reg_tmp1}, {emit_symbol_offset s ofs}\n`; - reg_tmp1 in + reg_tmp1 + in begin match size with | Byte_unsigned -> ` ldrb {emit_wreg dst}, {emit_addressing addr base}\n` @@ -707,10 +762,10 @@ let emit_instr i = | Word_int | Word_val | Double | Double_u -> ` str {emit_reg src}, {emit_addressing addr base}\n` end - | Lop(Ialloc { bytes = n; label_after_call_gc; dbginfo }) -> - assembly_code_for_allocation i ~n ~far:false ~label_after_call_gc ~dbginfo - | Lop(Ispecific (Ifar_alloc { bytes = n; label_after_call_gc; dbginfo })) -> - assembly_code_for_allocation i ~n ~far:true ~label_after_call_gc ~dbginfo + | Lop(Ialloc { bytes = n; label_after_call_gc; }) -> + assembly_code_for_allocation i ~n ~far:false ?label_after_call_gc + | Lop(Ispecific (Ifar_alloc { bytes = n; label_after_call_gc; })) -> + assembly_code_for_allocation i ~n ~far:true ?label_after_call_gc | Lop(Iintop(Icomp cmp)) -> ` cmp {emit_reg i.arg.(0)}, {emit_reg i.arg.(1)}\n`; ` cset {emit_reg i.res.(0)}, {emit_string (name_for_comparison cmp)}\n` @@ -902,28 +957,26 @@ let emit_instr i = | Lpushtrap { lbl_handler; } -> ` adr {emit_reg reg_tmp1}, {emit_label lbl_handler}\n`; stack_offset := !stack_offset + 16; - ` str {emit_reg reg_trap_ptr}, [sp, -16]!\n`; + ` str {emit_reg reg_trap_off}, [sp, #-16]!\n`; ` str {emit_reg reg_tmp1}, [sp, #8]\n`; cfi_adjust_cfa_offset 16; - ` mov {emit_reg reg_trap_ptr}, sp\n` + `{load_domain_field Domainstate.Domain_stack_high reg_trap_off}\n`; + ` mov {emit_reg reg_tmp1}, sp\n`; + ` sub {emit_reg reg_trap_off}, {emit_reg reg_trap_off}, {emit_reg reg_tmp1}\n` | Lpoptrap -> - ` ldr {emit_reg reg_trap_ptr}, [sp], 16\n`; + ` ldr {emit_reg reg_trap_off}, [sp], #16\n`; cfi_adjust_cfa_offset (-16); stack_offset := !stack_offset - 16 | Lraise k -> begin match k with - | Lambda.Raise_regular -> - let offset = Domainstate.(idx_of_field Domain_backtrace_pos) * 8 in - ` str xzr, [{emit_reg reg_domain_state_ptr}, {emit_int offset}]\n`; + | Cmm.Raise_withtrace -> ` bl {emit_symbol "caml_raise_exn"}\n`; - `{record_frame Reg.Set.empty (Dbg_raise i.dbg)}\n` - | Lambda.Raise_reraise -> - ` bl {emit_symbol "caml_raise_exn"}\n`; - `{record_frame Reg.Set.empty (Dbg_raise i.dbg)}\n` - | Lambda.Raise_notrace -> - ` mov sp, {emit_reg reg_trap_ptr}\n`; + `{record_frame Reg.Set.empty true i.dbg}\n` + | Cmm.Raise_notrace -> + `{load_domain_field Domainstate.Domain_stack_high reg_tmp1}\n`; + ` sub sp, {emit_reg reg_tmp1}, {emit_reg reg_trap_off}\n`; ` ldr {emit_reg reg_tmp1}, [sp, #8]\n`; - ` ldr {emit_reg reg_trap_ptr}, [sp], 16\n`; + ` ldr {emit_reg reg_trap_off}, [sp], #16\n`; ` br {emit_reg reg_tmp1}\n` end @@ -932,6 +985,38 @@ let emit_instr i = let rec emit_all i = if i.desc = Lend then () else (emit_instr i; emit_all i.next) + +type fun_preproc_info = + {max_stack_size : int; + contains_nontail_calls : bool; + contains_external_calls : bool} + +let preproc_fun fun_body fun_name = + let rec proc_instr r a i = + if i.desc = Lend then r else + let upd_size r delta = + {r with max_stack_size = max r.max_stack_size (a+delta)} + in + let (r',a') = match i.desc with + | Lop (Istackoffset n) -> (upd_size r n, a+n) + | Lpushtrap -> (upd_size r 16, a+16) + | Lpoptrap -> (r, a-16) + | Lop (Iextcall _ | Ialloc _ | Iintop Icheckbound | Iintop_imm (Icheckbound, _)) -> + ({r with contains_external_calls = true}, a) + | Lop (Icall_ind | Icall_imm _ ) -> + ({r with contains_nontail_calls = true}, a) + | _ -> (r, a) + in + proc_instr r' a' i.next + in + let fs = frame_size () in + let r = + {max_stack_size = fs; + contains_nontail_calls = false; + contains_external_calls = false} + in + proc_instr r fs fun_body + (* Emission of a function declaration *) let fundecl fundecl = @@ -942,7 +1027,8 @@ let fundecl fundecl = stack_offset := 0; call_gc_sites := []; bound_error_sites := []; - for i = 0 to Proc.num_register_classes - 1 do + read_barrier_call_sites := []; + for i = 0 to Proc.num_register_classes - 1 do num_stack_slots.(i) <- fundecl.fun_num_stack_slots.(i); done; prologue_required := fundecl.fun_prologue_required; @@ -958,13 +1044,54 @@ let fundecl fundecl = num_call_gc_and_check_bound_points fundecl.fun_body in let max_out_of_line_code_offset = - max_out_of_line_code_offset ~num_call_gc + max_out_of_line_code_offset fundecl.fun_body ~num_call_gc ~num_check_bound in BR.relax fundecl.fun_body ~max_out_of_line_code_offset; - emit_all fundecl.fun_body; - List.iter emit_call_gc !call_gc_sites; - List.iter emit_call_bound_error !bound_error_sites; + + let preproc_res = preproc_fun fundecl.fun_body fundecl.fun_name in + let s = preproc_res.max_stack_size in + + (* Extra 32 bytes for caml_context at the bottom of OCaml stack if the + * function makes external calls *) + let s = if preproc_res.contains_external_calls then s + 32 else s in + + if not preproc_res.contains_nontail_calls && s < stack_threshold_size + then begin + `{emit_label !tailrec_entry_point}:\n`; + emit_all fundecl.fun_body; + List.iter emit_call_gc !call_gc_sites; + List.iter emit_call_read_barrier !read_barrier_call_sites; + List.iter emit_call_bound_error !bound_error_sites; + end + else begin + (* XXX KC: fundecl.fun_body.live does not capture liveness at the start of + the function properly. Hence, consider all argument registers as live. + Stragely, all arguments are typed as Int regs (see regs.mli). These are + ignored by record_frame_label. Hence, consider all of them to be type Val. + *) + let live_initially = + Reg.Set.(fold (fun r s -> add {r with typ = Val} s) + fundecl.fun_args empty) + in + let handle_overflow = new_label() in + let after_overflow = record_frame_label live_initially Debuginfo.none in + + `{load_domain_field Domainstate.Domain_stack_threshold reg_tmp1}\n`; + ` add {emit_reg reg_tmp1}, {emit_reg reg_tmp1}, #{emit_int s}\n`; + ` cmp sp, {emit_reg reg_tmp1}\n`; + ` bcc {emit_label handle_overflow}\n`; + `{emit_label !tailrec_entry_point}:\n`; + emit_all fundecl.fun_body; + List.iter emit_call_gc !call_gc_sites; + List.iter emit_call_read_barrier !read_barrier_call_sites; + List.iter emit_call_bound_error !bound_error_sites; + `{emit_label handle_overflow}:\n`; + ` bl {emit_symbol "caml_call_realloc_stack"}\n`; + `{emit_label after_overflow}:\n`; + ` b {emit_label !tailrec_entry_point}\n`; + end; + assert (List.length !call_gc_sites = num_call_gc); assert (List.length !bound_error_sites = num_check_bound); cfi_endproc(); @@ -1037,7 +1164,6 @@ let end_assembly () = efa_data_label = (fun lbl -> ` .type {emit_label lbl}, %object\n`; ` .quad {emit_label lbl}\n`); - efa_8 = (fun n -> ` .byte {emit_int n}\n`); efa_16 = (fun n -> ` .short {emit_int n}\n`); efa_32 = (fun n -> ` .long {emit_int32 n}\n`); efa_word = (fun n -> ` .quad {emit_int n}\n`); diff --git a/asmcomp/arm64/proc.ml b/asmcomp/arm64/proc.ml index f9c73f2fdb..e362b6b63b 100644 --- a/asmcomp/arm64/proc.ml +++ b/asmcomp/arm64/proc.ml @@ -99,6 +99,8 @@ let all_phys_regs = let phys_reg n = if n < 100 then hard_int_reg.(n) else hard_float_reg.(n - 100) +let reg_x0 = phys_reg 0 +let reg_x1 = phys_reg 1 let reg_x15 = phys_reg 15 let reg_d7 = phys_reg 107 @@ -159,10 +161,12 @@ let outgoing ofs = Outgoing ofs let not_supported _ofs = fatal_error "Proc.loc_results: cannot call" (* OCaml calling convention: - first integer args in r0...r15 + first integer args in x0...x15 first float args in d0...d15 remaining args on stack. - Return values in r0...r15 or d0...d15. *) + Return values in x0...x15 or d0...d15. *) + +let max_arguments_for_tailcalls = 16 let max_arguments_for_tailcalls = 16 @@ -174,7 +178,7 @@ let loc_results res = let (loc, _) = calling_conventions 0 15 100 115 not_supported res in loc (* C calling convention: - first integer args in r0...r7 + first integer args in x0...x7 first float args in d0...d7 remaining args on stack. macOS/iOS peculiarity: int32 arguments passed on stack occupy 4 bytes, @@ -247,10 +251,12 @@ let destroyed_at_c_call = 124;125;126;127;128;129;130;131]) let destroyed_at_oper = function - | Iop(Icall_ind _ | Icall_imm _) | Iop(Iextcall { alloc = true; }) -> + | Iop(Icall_ind _ | Icall_imm _) -> all_phys_regs - | Iop(Iextcall { alloc = false; }) -> - destroyed_at_c_call + | Iop(Iextcall { alloc ; stack_ofs; }) -> + assert (stack_ofs >= 0); + if alloc || stack_ofs > 0 then all_phys_regs + else destroyed_at_c_call | Iop(Ialloc _) -> [| reg_x15 |] | Iop(Iintoffloat | Ifloatofint | Iload(Single, _) | Istore(Single, _, _)) -> diff --git a/asmcomp/asmgen.ml b/asmcomp/asmgen.ml index a6468b6c19..2d6f7b060b 100644 --- a/asmcomp/asmgen.ml +++ b/asmcomp/asmgen.ml @@ -89,6 +89,7 @@ let compile_fundecl ~ppf_dump fd_cmm = ++ Profile.record ~accumulate:true "cse" CSE.fundecl ++ pass_dump_if ppf_dump dump_cse "After CSE" ++ Profile.record ~accumulate:true "liveness" liveness + ++ Profile.record ~accumulate:true "polling" Polling.fundecl ++ Profile.record ~accumulate:true "deadcode" Deadcode.fundecl ++ pass_dump_if ppf_dump dump_live "Liveness analysis" ++ Profile.record ~accumulate:true "spill" Spill.fundecl diff --git a/asmcomp/cmm.ml b/asmcomp/cmm.ml index 79cc2265ce..249d1853ef 100644 --- a/asmcomp/cmm.ml +++ b/asmcomp/cmm.ml @@ -142,7 +142,10 @@ and operation = | Cextcall of string * machtype * exttype list * bool * label option (** If specified, the given label will be placed immediately after the call (at the same place as any frame descriptor would reference). *) - | Cload of memory_chunk * Asttypes.mutable_flag + | Cload of + { memory_chunk: memory_chunk + ; mutability: Asttypes.mutable_flag + ; is_atomic: bool } | Calloc | Cstore of memory_chunk * Lambda.initialization_or_assignment | Caddi | Csubi | Cmuli | Cmulhi | Cdivi | Cmodi @@ -156,6 +159,8 @@ and operation = | Ccmpf of float_comparison | Craise of Lambda.raise_kind | Ccheckbound + | Cpoll + | Cnop type expression = Cconst_int of int * Debuginfo.t diff --git a/asmcomp/cmm.mli b/asmcomp/cmm.mli index ee8714e73d..2dfe24f4e6 100644 --- a/asmcomp/cmm.mli +++ b/asmcomp/cmm.mli @@ -142,7 +142,10 @@ and operation = (** The [machtype] is the machine type of the result. The [exttype list] describes the unboxing types of the arguments. An empty list means "all arguments are machine words [XInt]". *) - | Cload of memory_chunk * Asttypes.mutable_flag + | Cload of + { memory_chunk: memory_chunk + ; mutability: Asttypes.mutable_flag + ; is_atomic: bool } | Calloc | Cstore of memory_chunk * Lambda.initialization_or_assignment | Caddi | Csubi | Cmuli | Cmulhi | Cdivi | Cmodi @@ -160,6 +163,8 @@ and operation = then the index. It results in a bounds error if the index is greater than or equal to the bound. *) + | Cpoll + | Cnop (** Every basic block should have a corresponding [Debuginfo.t] for its beginning. *) diff --git a/asmcomp/cmm_helpers.ml b/asmcomp/cmm_helpers.ml index 5fd58924d0..367446e724 100644 --- a/asmcomp/cmm_helpers.ml +++ b/asmcomp/cmm_helpers.ml @@ -571,9 +571,13 @@ let unbox_float dbg = | Some (Uconst_float x) -> Cconst_float (x, dbg) (* or keep _dbg? *) | _ -> - Cop(Cload (Double_u, Immutable), [cmm], dbg) + Cop(Cload {memory_chunk=Double_u; mutability=Immutable; + is_atomic=false}, + [cmm], dbg) end - | cmm -> Cop(Cload (Double_u, Immutable), [cmm], dbg) + | cmm -> Cop(Cload {memory_chunk=Double_u; mutability=Immutable; + is_atomic=false}, + [cmm], dbg) ) (* Complex *) @@ -581,10 +585,12 @@ let unbox_float dbg = let box_complex dbg c_re c_im = Cop(Calloc, [alloc_floatarray_header 2 dbg; c_re; c_im], dbg) -let complex_re c dbg = Cop(Cload (Double_u, Immutable), [c], dbg) -let complex_im c dbg = Cop(Cload (Double_u, Immutable), - [Cop(Cadda, [c; Cconst_int (size_float, dbg)], dbg)], - dbg) +let complex_re c dbg = + Cop(Cload {memory_chunk=Double_u; mutability=Immutable; is_atomic=false}, + [c], dbg) +let complex_im c dbg = + Cop(Cload {memory_chunk=Double_u; mutability=Immutable; is_atomic=false}, + [Cop(Cadda, [c; Cconst_int (size_float, dbg)], dbg)], dbg) (* Unit *) @@ -621,13 +627,17 @@ let rec remove_unit = function (* Access to block fields *) +let mk_load_mut memory_chunk = + Cload {memory_chunk; mutability=Mutable; is_atomic=false} + let field_address ptr n dbg = if n = 0 then ptr else Cop(Cadda, [ptr; Cconst_int(n * size_addr, dbg)], dbg) -let get_field_gen mut ptr n dbg = - Cop(Cload (Word_val, mut), [field_address ptr n dbg], dbg) +let get_field_gen mutability ptr n dbg = + Cop(Cload {memory_chunk=Word_val; mutability; is_atomic=false}, + [field_address ptr n dbg], dbg) let set_field ptr n newval init dbg = Cop(Cstore (Word_val, init), [field_address ptr n dbg; newval], dbg) @@ -640,7 +650,7 @@ let non_profinfo_mask = let get_header ptr dbg = (* We cannot deem this as [Immutable] due to the presence of [Obj.truncate] and [Obj.set_tag]. *) - Cop(Cload (Word_int, Mutable), + Cop(mk_load_mut Word_int, [Cop(Cadda, [ptr; Cconst_int(-size_int, dbg)], dbg)], dbg) let get_header_without_profinfo ptr dbg = @@ -657,7 +667,7 @@ let get_tag ptr dbg = Cop(Cand, [get_header ptr dbg; Cconst_int (255, dbg)], dbg) else (* If byte loads are efficient *) (* Same comment as [get_header] above *) - Cop(Cload (Byte_unsigned, Mutable), + Cop(mk_load_mut Byte_unsigned, [Cop(Cadda, [ptr; Cconst_int(tag_offset, dbg)], dbg)], dbg) let get_size ptr dbg = @@ -724,23 +734,23 @@ let array_indexing ?typ log2size ptr ofs dbg = Cconst_int((-1) lsl (log2size - 1), dbg)], dbg) let addr_array_ref arr ofs dbg = - Cop(Cload (Word_val, Mutable), + Cop(mk_load_mut Word_val, [array_indexing log2_size_addr arr ofs dbg], dbg) let int_array_ref arr ofs dbg = - Cop(Cload (Word_int, Mutable), + Cop(mk_load_mut Word_int, [array_indexing log2_size_addr arr ofs dbg], dbg) let unboxed_float_array_ref arr ofs dbg = - Cop(Cload (Double_u, Mutable), + Cop(mk_load_mut Double_u, [array_indexing log2_size_float arr ofs dbg], dbg) let float_array_ref arr ofs dbg = box_float dbg (unboxed_float_array_ref arr ofs dbg) let addr_array_set arr ofs newval dbg = - Cop(Cextcall("caml_modify", typ_void, [], false, None), - [array_indexing log2_size_addr arr ofs dbg; newval], dbg) + Cop(Cextcall("caml_modify_field", typ_void, [], false, None), + [arr; untag_int ofs dbg; newval], dbg) let addr_array_initialize arr ofs newval dbg = - Cop(Cextcall("caml_initialize", typ_void, [], false, None), - [array_indexing log2_size_addr arr ofs dbg; newval], dbg) + Cop(Cextcall("caml_initialize_field", typ_void, [], false, None), + [arr; untag_int ofs dbg; newval], dbg) let int_array_set arr ofs newval dbg = Cop(Cstore (Word_int, Lambda.Assignment), [array_indexing log2_size_addr arr ofs dbg; newval], dbg) @@ -765,11 +775,11 @@ let string_length exp dbg = dbg), Cop(Csubi, [Cvar tmp_var; - Cop(Cload (Byte_unsigned, Mutable), + Cop(mk_load_mut Byte_unsigned, [Cop(Cadda, [str; Cvar tmp_var], dbg)], dbg)], dbg))) let bigstring_length ba dbg = - Cop(Cload (Word_int, Mutable), [field_address ba 5 dbg], dbg) + Cop(mk_load_mut Word_int, [field_address ba 5 dbg], dbg) (* Message sending *) @@ -781,7 +791,7 @@ let lookup_tag obj tag dbg = let lookup_label obj lab dbg = bind "lab" lab (fun lab -> - let table = Cop (Cload (Word_val, Mutable), [obj], dbg) in + let table = Cop (mk_load_mut Word_val, [obj], dbg) in addr_array_ref table lab dbg) let call_cached_method obj tag cache pos args dbg = @@ -812,8 +822,8 @@ let make_alloc_generic set_fn dbg tag wordsize args = let make_alloc dbg tag args = let addr_array_init arr ofs newval dbg = - Cop(Cextcall("caml_initialize", typ_void, [], false, None), - [array_indexing log2_size_addr arr ofs dbg; newval], dbg) + Cop(Cextcall("caml_initialize_field", typ_void, [], false, None), + [arr; untag_int ofs dbg; newval], dbg) in make_alloc_generic addr_array_init dbg tag (List.length args) args @@ -874,7 +884,7 @@ let bigarray_indexing unsafe elt_kind layout b args dbg = bind "idx" arg (fun idx -> (* Load the untagged int bound for the given dimension *) let bound = - Cop(Cload (Word_int, Mutable), + Cop(mk_load_mut Word_int, [field_address b dim_ofs dbg], dbg) in let idxn = untag_int idx dbg in @@ -885,7 +895,7 @@ let bigarray_indexing unsafe elt_kind layout b args dbg = let rem = ba_indexing (dim_ofs + delta_ofs) delta_ofs argl in (* Load the untagged int bound for the given dimension *) let bound = - Cop(Cload (Word_int, Mutable), + Cop(mk_load_mut Word_int, [field_address b dim_ofs dbg], dbg) in if unsafe then add_int (mul_int (decr_int rem dbg) bound dbg) arg1 dbg @@ -912,7 +922,7 @@ let bigarray_indexing unsafe elt_kind layout b args dbg = bigarray_elt_size elt_kind in (* [array_indexing] can simplify the given expressions *) array_indexing ~typ:Addr (Misc.log2 elt_size) - (Cop(Cload (Word_int, Mutable), + (Cop(mk_load_mut Word_int, [field_address b 1 dbg], dbg)) offset dbg let bigarray_word_kind : Lambda.bigarray_kind -> memory_chunk = function @@ -939,13 +949,13 @@ let bigarray_get unsafe elt_kind layout b args dbg = bind "addr" (bigarray_indexing unsafe elt_kind layout b args dbg) (fun addr -> bind "reval" - (Cop(Cload (kind, Mutable), [addr], dbg)) (fun reval -> + (Cop(mk_load_mut kind, [addr], dbg)) (fun reval -> bind "imval" - (Cop(Cload (kind, Mutable), + (Cop(mk_load_mut kind, [Cop(Cadda, [addr; Cconst_int (sz, dbg)], dbg)], dbg)) (fun imval -> box_complex dbg reval imval))) | _ -> - Cop(Cload (bigarray_word_kind elt_kind, Mutable), + Cop(mk_load_mut (bigarray_word_kind elt_kind), [bigarray_indexing unsafe elt_kind layout b args dbg], dbg)) @@ -1027,8 +1037,8 @@ let split_int64_for_32bit_target arg dbg = bind "split_int64" arg (fun arg -> let first = Cop (Cadda, [Cconst_int (size_int, dbg); arg], dbg) in let second = Cop (Cadda, [Cconst_int (2 * size_int, dbg); arg], dbg) in - Ctuple [Cop (Cload (Thirtytwo_unsigned, Mutable), [first], dbg); - Cop (Cload (Thirtytwo_unsigned, Mutable), [second], dbg)]) + Ctuple [Cop (mk_load_mut Thirtytwo_unsigned, [first], dbg); + Cop (mk_load_mut Thirtytwo_unsigned, [second], dbg)]) let alloc_matches_boxed_int bi ~hdr ~ops = match (bi : Primitive.boxed_integer), hdr, ops with @@ -1048,9 +1058,11 @@ let unbox_int dbg bi = if size_int = 4 && bi = Primitive.Pint64 then split_int64_for_32bit_target arg dbg else + let memory_chunk = if bi = Primitive.Pint32 + then Thirtytwo_signed else Word_int + in Cop( - Cload((if bi = Primitive.Pint32 then Thirtytwo_signed else Word_int), - Immutable), + Cload {memory_chunk; mutability=Immutable; is_atomic=false}, [Cop(Cadda, [arg; Cconst_int (size_addr, dbg)], dbg)], dbg) in map_tail @@ -1103,11 +1115,11 @@ let make_unsigned_int bi arg dbg = let unaligned_load_16 ptr idx dbg = if Arch.allow_unaligned_access - then Cop(Cload (Sixteen_unsigned, Mutable), [add_int ptr idx dbg], dbg) + then Cop(mk_load_mut Sixteen_unsigned, [add_int ptr idx dbg], dbg) else let cconst_int i = Cconst_int (i, dbg) in - let v1 = Cop(Cload (Byte_unsigned, Mutable), [add_int ptr idx dbg], dbg) in - let v2 = Cop(Cload (Byte_unsigned, Mutable), + let v1 = Cop(mk_load_mut Byte_unsigned, [add_int ptr idx dbg], dbg) in + let v2 = Cop(mk_load_mut Byte_unsigned, [add_int (add_int ptr idx dbg) (cconst_int 1) dbg], dbg) in let b1, b2 = if Arch.big_endian then v1, v2 else v2, v1 in Cop(Cor, [lsl_int b1 (cconst_int 8) dbg; b2], dbg) @@ -1132,17 +1144,17 @@ let unaligned_set_16 ptr idx newval dbg = let unaligned_load_32 ptr idx dbg = if Arch.allow_unaligned_access - then Cop(Cload (Thirtytwo_unsigned, Mutable), [add_int ptr idx dbg], dbg) + then Cop(mk_load_mut Thirtytwo_unsigned, [add_int ptr idx dbg], dbg) else let cconst_int i = Cconst_int (i, dbg) in - let v1 = Cop(Cload (Byte_unsigned, Mutable), [add_int ptr idx dbg], dbg) in - let v2 = Cop(Cload (Byte_unsigned, Mutable), + let v1 = Cop(mk_load_mut Byte_unsigned, [add_int ptr idx dbg], dbg) in + let v2 = Cop(mk_load_mut Byte_unsigned, [add_int (add_int ptr idx dbg) (cconst_int 1) dbg], dbg) in - let v3 = Cop(Cload (Byte_unsigned, Mutable), + let v3 = Cop(mk_load_mut Byte_unsigned, [add_int (add_int ptr idx dbg) (cconst_int 2) dbg], dbg) in - let v4 = Cop(Cload (Byte_unsigned, Mutable), + let v4 = Cop(mk_load_mut Byte_unsigned, [add_int (add_int ptr idx dbg) (cconst_int 3) dbg], dbg) in let b1, b2, b3, b4 = @@ -1194,23 +1206,23 @@ let unaligned_set_32 ptr idx newval dbg = let unaligned_load_64 ptr idx dbg = assert(size_int = 8); if Arch.allow_unaligned_access - then Cop(Cload (Word_int, Mutable), [add_int ptr idx dbg], dbg) + then Cop(mk_load_mut Word_int, [add_int ptr idx dbg], dbg) else let cconst_int i = Cconst_int (i, dbg) in - let v1 = Cop(Cload (Byte_unsigned, Mutable), [add_int ptr idx dbg], dbg) in - let v2 = Cop(Cload (Byte_unsigned, Mutable), + let v1 = Cop(mk_load_mut Byte_unsigned, [add_int ptr idx dbg], dbg) in + let v2 = Cop(mk_load_mut Byte_unsigned, [add_int (add_int ptr idx dbg) (cconst_int 1) dbg], dbg) in - let v3 = Cop(Cload (Byte_unsigned, Mutable), + let v3 = Cop(mk_load_mut Byte_unsigned, [add_int (add_int ptr idx dbg) (cconst_int 2) dbg], dbg) in - let v4 = Cop(Cload (Byte_unsigned, Mutable), + let v4 = Cop(mk_load_mut Byte_unsigned, [add_int (add_int ptr idx dbg) (cconst_int 3) dbg], dbg) in - let v5 = Cop(Cload (Byte_unsigned, Mutable), + let v5 = Cop(mk_load_mut Byte_unsigned, [add_int (add_int ptr idx dbg) (cconst_int 4) dbg], dbg) in - let v6 = Cop(Cload (Byte_unsigned, Mutable), + let v6 = Cop(mk_load_mut Byte_unsigned, [add_int (add_int ptr idx dbg) (cconst_int 5) dbg], dbg) in - let v7 = Cop(Cload (Byte_unsigned, Mutable), + let v7 = Cop(mk_load_mut Byte_unsigned, [add_int (add_int ptr idx dbg) (cconst_int 6) dbg], dbg) in - let v8 = Cop(Cload (Byte_unsigned, Mutable), + let v8 = Cop(mk_load_mut Byte_unsigned, [add_int (add_int ptr idx dbg) (cconst_int 7) dbg], dbg) in let b1, b2, b3, b4, b5, b6, b7, b8 = if Arch.big_endian @@ -1731,7 +1743,7 @@ let cache_public_method meths tag cache dbg = Clet_mut ( VP.create li, typ_int, cconst_int 3, Clet_mut ( - VP.create hi, typ_int, Cop(Cload (Word_int, Mutable), [meths], dbg), + VP.create hi, typ_int, Cop(mk_load_mut Word_int, [meths], dbg), Csequence( ccatch (raise_num, [], @@ -1747,7 +1759,7 @@ let cache_public_method meths tag cache dbg = Cifthenelse (Cop (Ccmpi Clt, [tag; - Cop(Cload (Word_int, Mutable), + Cop(mk_load_mut Word_int, [Cop(Cadda, [meths; lsl_const (Cvar mi) log2_size_addr dbg], dbg)], @@ -1838,12 +1850,12 @@ let send_function arity = let cached_pos = Cvar cached in let tag_pos = Cop(Cadda, [Cop (Cadda, [cached_pos; Cvar meths], dbg ()); cconst_int(3*size_addr-1)], dbg ()) in - let tag' = Cop(Cload (Word_int, Mutable), [tag_pos], dbg ()) in + let tag' = Cop(mk_load_mut Word_int, [tag_pos], dbg ()) in Clet ( - VP.create meths, Cop(Cload (Word_val, Mutable), [obj], dbg ()), + VP.create meths, Cop(mk_load_mut Word_val, [obj], dbg ()), Clet ( VP.create cached, - Cop(Cand, [Cop(Cload (Word_int, Mutable), [cache], dbg ()); mask], + Cop(Cand, [Cop(mk_load_mut Word_int, [cache], dbg ()); mask], dbg ()), Clet ( VP.create real, @@ -1853,7 +1865,7 @@ let send_function arity = dbg (), cached_pos, dbg ()), - Cop(Cload (Word_val, Mutable), + Cop(mk_load_mut Word_val, [Cop(Cadda, [Cop (Cadda, [Cvar real; Cvar meths], dbg ()); cconst_int(2*size_addr-1)], dbg ())], dbg ())))) @@ -2093,7 +2105,7 @@ let generic_functions shared units = type unary_primitive = expression -> Debuginfo.t -> expression let floatfield n ptr dbg = - Cop(Cload (Double_u, Mutable), + Cop(mk_load_mut Double_u, [if n = 0 then ptr else Cop(Cadda, [ptr; Cconst_int(n * size_float, dbg)], dbg)], dbg) @@ -2118,7 +2130,7 @@ let offsetref n arg dbg = (bind "ref" arg (fun arg -> Cop(Cstore (Word_int, Assignment), [arg; - add_const (Cop(Cload (Word_int, Mutable), [arg], dbg)) + add_const (Cop(mk_load_mut Word_int, [arg], dbg)) (n lsl 1) dbg], dbg))) @@ -2175,23 +2187,24 @@ let assignment_kind (init: Lambda.initialization_or_assignment) = match init, ptr with | Assignment, Pointer -> Caml_modify - | Heap_initialization, Pointer -> Caml_initialize + | Heap_initialization, Pointer + | Root_initialization, Pointer -> Caml_initialize | Assignment, Immediate | Heap_initialization, Immediate - | Root_initialization, (Immediate | Pointer) -> Simple + | Root_initialization, Immediate -> Simple let setfield n ptr init arg1 arg2 dbg = match assignment_kind ptr init with | Caml_modify -> - return_unit dbg - (Cop(Cextcall("caml_modify", typ_void, [], false, None), - [field_address arg1 n dbg; arg2], - dbg)) + return_unit dbg (Cop(Cextcall("caml_modify_field", + typ_void, [], false, None), + [arg1; Cconst_int (n, dbg); arg2], + dbg)) | Caml_initialize -> - return_unit dbg - (Cop(Cextcall("caml_initialize", typ_void, [], false, None), - [field_address arg1 n dbg; arg2], - dbg)) + return_unit dbg (Cop(Cextcall("caml_initialize_field", + typ_void, [], false, None), + [arg1; Cconst_int (n, dbg); arg2], + dbg)) | Simple -> return_unit dbg (set_field arg1 n arg2 init dbg) @@ -2265,7 +2278,7 @@ let int_comp_caml cmp arg1 arg2 dbg = [arg1; arg2], dbg)) dbg let stringref_unsafe arg1 arg2 dbg = - tag_int(Cop(Cload (Byte_unsigned, Mutable), + tag_int(Cop(mk_load_mut Byte_unsigned, [add_int arg1 (untag_int arg2 dbg) dbg], dbg)) dbg @@ -2275,7 +2288,7 @@ let stringref_safe arg1 arg2 dbg = bind "index" (untag_int arg2 dbg) (fun idx -> Csequence( make_checkbound dbg [string_length str dbg; idx], - Cop(Cload (Byte_unsigned, Mutable), + Cop(mk_load_mut Byte_unsigned, [add_int str idx dbg], dbg))))) dbg let string_load size unsafe arg1 arg2 dbg = @@ -2291,7 +2304,7 @@ let bigstring_load size unsafe arg1 arg2 dbg = (bind "ba" arg1 (fun ba -> bind "index" (untag_int arg2 dbg) (fun idx -> bind "ba_data" - (Cop(Cload (Word_int, Mutable), [field_address ba 1 dbg], dbg)) + (Cop(mk_load_mut Word_int, [field_address ba 1 dbg], dbg)) (fun ba_data -> check_bound unsafe size dbg (bigstring_length ba dbg) @@ -2496,7 +2509,7 @@ let bigstring_set size unsafe arg1 arg2 arg3 dbg = bind "index" (untag_int arg2 dbg) (fun idx -> bind "newval" arg3 (fun newval -> bind "ba_data" - (Cop(Cload (Word_int, Mutable), [field_address ba 1 dbg], dbg)) + (Cop(mk_load_mut Word_int, [field_address ba 1 dbg], dbg)) (fun ba_data -> check_bound unsafe size dbg (bigstring_length ba dbg) idx (unaligned_set size ba_data idx newval dbg)))))) @@ -2572,7 +2585,7 @@ let entry_point namelist = let incr_global_inited () = Cop(Cstore (Word_int, Assignment), [cconst_symbol "caml_globals_inited"; - Cop(Caddi, [Cop(Cload (Word_int, Mutable), + Cop(Caddi, [Cop(mk_load_mut Word_int, [cconst_symbol "caml_globals_inited"], dbg ()); cconst_int 1], dbg ())], dbg ()) in let body = diff --git a/asmcomp/cmm_helpers.mli b/asmcomp/cmm_helpers.mli index 6463edc27e..5f6c90bc7f 100644 --- a/asmcomp/cmm_helpers.mli +++ b/asmcomp/cmm_helpers.mli @@ -188,6 +188,7 @@ val return_unit : Debuginfo.t -> expression -> expression val remove_unit : expression -> expression (** Blocks *) +val mk_load_mut : memory_chunk -> operation (** [field_address ptr n dbg] returns an expression for the address of the [n]th field of the block pointed to by [ptr] *) diff --git a/asmcomp/cmmgen.ml b/asmcomp/cmmgen.ml index 7b7656cdbb..bea15d0b3f 100644 --- a/asmcomp/cmmgen.ml +++ b/asmcomp/cmmgen.ml @@ -518,7 +518,7 @@ let rec transl env e = dbg) | (Pbigarraydim(n), [b]) -> let dim_ofs = 4 + n in - tag_int (Cop(Cload (Word_int, Mutable), + tag_int (Cop(mk_load_mut Word_int, [field_address (transl env b) dim_ofs dbg], dbg)) dbg | (p, [arg]) -> @@ -534,6 +534,9 @@ let rec transl env e = -> fatal_error "Cmmgen.transl:prim, wrong arity" | ((Pfield_computed|Psequand + | Prunstack | Pperform | Presume | Preperform | Ppoll | Pnop + | Patomic_load _ | Patomic_exchange + | Patomic_cas | Patomic_fetch_add | Psequor | Pnot | Pnegint | Paddint | Psubint | Pmulint | Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint | Pintoffloat | Pfloatofint @@ -668,7 +671,7 @@ let rec transl env e = end | Uunreachable -> let dbg = Debuginfo.none in - Cop(Cload (Word_int, Mutable), [Cconst_int (0, dbg)], dbg) + Cop(mk_load_mut Word_int, [Cconst_int (0, dbg)], dbg) and transl_catch env nfail ids body handler dbg = let ids = List.map (fun (id, kind) -> (id, kind, ref No_result)) ids in @@ -784,7 +787,7 @@ and transl_prim_1 env p arg dbg = Popaque -> transl env arg (* Heap operations *) - | Pfield n -> + | Pfield(n, _, _) -> get_field env (transl env arg) n dbg | Pfloatfield n -> let ptr = transl env arg in @@ -841,7 +844,21 @@ and transl_prim_1 env p arg dbg = | Pbswap16 -> tag_int (bswap16 (ignore_high_bit_int (untag_int (transl env arg) dbg)) dbg) dbg + | Pperform -> + let cont = make_alloc dbg Obj.cont_tag [int_const dbg 0] in + Cop(Capply typ_val, [Cconst_symbol ("caml_perform", dbg); transl env arg; cont], + dbg) + | Ppoll -> + Cop(Cpoll, [transl env arg], dbg) + | Pnop -> + Cop(Cnop, [transl env arg], dbg) + | Patomic_load {immediate_or_pointer = Immediate} -> + Cop(mk_load_mut Word_int, [transl env arg], dbg) + | Patomic_load {immediate_or_pointer = Pointer} -> + Cop(mk_load_mut Word_val, [transl env arg], dbg) | (Pfield_computed | Psequand | Psequor + | Prunstack | Presume | Preperform + | Patomic_exchange | Patomic_cas | Patomic_fetch_add | Paddint | Psubint | Pmulint | Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint | Paddfloat | Psubfloat | Pmulfloat | Pdivfloat @@ -1025,6 +1042,14 @@ and transl_prim_2 env p arg1 arg2 dbg = tag_int (Cop(Ccmpi cmp, [transl_unbox_int dbg env bi arg1; transl_unbox_int dbg env bi arg2], dbg)) dbg + | Patomic_exchange -> + Cop (Cextcall ("caml_atomic_exchange", typ_val, [], false, None), + [transl env arg1; transl env arg2], dbg) + | Patomic_fetch_add -> + Cop (Cextcall ("caml_atomic_fetch_add", typ_int, [], false, None), + [transl env arg1; transl env arg2], dbg) + | Prunstack | Pperform | Presume | Preperform | Ppoll | Pnop + | Patomic_cas | Patomic_load _ | Pnot | Pnegint | Pintoffloat | Pfloatofint | Pnegfloat | Pabsfloat | Pstringlength | Pbyteslength | Pbytessetu | Pbytessets | Pisint | Pbswap16 | Pint_as_pointer | Popaque | Pread_symbol _ @@ -1076,6 +1101,28 @@ and transl_prim_3 env p arg1 arg2 arg3 dbg = bigstring_set size unsafe (transl env arg1) (transl env arg2) (transl_unbox_sized size dbg env arg3) dbg + | Patomic_cas -> + Cop (Cextcall ("caml_atomic_cas", typ_int, [], false, None), + [transl env arg1; transl env arg2; transl env arg3], dbg) + + (* Effects *) + | Presume -> + Cop (Capply typ_val, [Cconst_symbol ("caml_resume", dbg); transl env arg1; + transl env arg2; transl env arg3], + dbg) + + | Prunstack -> + Cop (Capply typ_val, [Cconst_symbol ("caml_runstack", dbg); transl env arg1; + transl env arg2; transl env arg3], + dbg) + + | Preperform -> + Cop (Capply typ_val, [Cconst_symbol ("caml_reperform", dbg); transl env arg1; + transl env arg2; transl env arg3], + dbg) + + | Pperform | Ppoll | Pnop + | Patomic_exchange | Patomic_fetch_add | Patomic_load _ | Pfield_computed | Psequand | Psequor | Pnot | Pnegint | Paddint | Psubint | Pmulint | Pandint | Porint | Pxorint | Plslint | Plsrint | Pasrint | Pintoffloat | Pfloatofint | Pnegfloat | Pabsfloat | Paddfloat | Psubfloat diff --git a/asmcomp/emitaux.ml b/asmcomp/emitaux.ml index 9a1e621467..36b21b7a19 100644 --- a/asmcomp/emitaux.ml +++ b/asmcomp/emitaux.ml @@ -106,7 +106,6 @@ let emit_float32_directive directive x = (* Record live pointers at call points *) type frame_debuginfo = - | Dbg_alloc of Debuginfo.alloc_dbginfo | Dbg_raise of Debuginfo.t | Dbg_other of Debuginfo.t @@ -184,16 +183,14 @@ let emit_frames a = match fd.fd_debuginfo with | Dbg_other d | Dbg_raise d -> if Debuginfo.is_none d then 0 else 1 - | Dbg_alloc dbgs -> - if !Clflags.debug && not Config.spacetime && - List.exists (fun d -> - not (Debuginfo.is_none d.Debuginfo.alloc_dbg)) dbgs - then 3 else 2 in a.efa_code_label fd.fd_lbl; a.efa_16 (fd.fd_frame_size + flags); - a.efa_16 (List.length fd.fd_live_offset); - List.iter a.efa_16 fd.fd_live_offset; + let uniq_fd_live_offset = + List.sort_uniq compare fd.fd_live_offset + in + a.efa_16 (List.length uniq_fd_live_offset); + List.iter a.efa_16 uniq_fd_live_offset; begin match fd.fd_debuginfo with | _ when flags = 0 -> () @@ -203,23 +200,6 @@ let emit_frames a = | Dbg_raise dbg -> a.efa_align 4; a.efa_label_rel (label_debuginfos true dbg) Int32.zero - | Dbg_alloc dbg -> - assert (List.length dbg < 256); - a.efa_8 (List.length dbg); - List.iter (fun Debuginfo.{alloc_words;_} -> - (* Possible allocations range between 2 and 257 *) - assert (2 <= alloc_words && - alloc_words - 1 <= Config.max_young_wosize && - Config.max_young_wosize <= 256); - a.efa_8 (alloc_words - 2)) dbg; - if flags = 3 then begin - a.efa_align 4; - List.iter (fun Debuginfo.{alloc_dbg; _} -> - if Debuginfo.is_none alloc_dbg then - a.efa_32 Int32.zero - else - a.efa_label_rel (label_debuginfos false alloc_dbg) Int32.zero) dbg - end end; a.efa_align Arch.size_addr in @@ -301,12 +281,25 @@ let cfi_endproc () = if is_cfi_enabled () then emit_string "\t.cfi_endproc\n" +let cfi_remember_state () = + if is_cfi_enabled () then + emit_string "\t.cfi_remember_state\n" + +let cfi_restore_state () = + if is_cfi_enabled () then + emit_string "\t.cfi_restore_state\n" + let cfi_adjust_cfa_offset n = if is_cfi_enabled () then begin emit_string "\t.cfi_adjust_cfa_offset\t"; emit_int n; emit_string "\n"; end +let cfi_def_cfa_offset n = + if is_cfi_enabled () then begin + emit_string "\t.cfi_def_cfa_offset\t"; emit_int n; emit_string "\n"; + end + let cfi_offset ~reg ~offset = if is_cfi_enabled () then begin emit_string "\t.cfi_offset "; @@ -351,6 +344,43 @@ let emit_debug_info_gen dbg file_emitter loc_emitter = file_num in loc_emitter ~file_num ~line ~col; end + end + +(* Emission of block headers immediately prior to function entry points *) + +let emit_block_header_for_closure ~word_directive ~comment_string + ~function_entry_points_are_doubleword_aligned = + if true (* Config.no_naked_pointers *) then begin + let header = + (* Claim that the function is a zero-size [Abstract_tag] block + marked black. *) + (* CR-someday mshinwell: For multicore, to make marshalling work, + this will need to use a distinguished tag. *) + (* CR mshinwell: factor this definition out from here and cmmgen.ml, + and make sure it matches [Caml_black]. *) + let not_markable = Nativeint.shift_left (Nativeint.of_int 3) 8 in + Nativeint.logor not_markable (Nativeint.of_int Obj.abstract_tag) + in + (* The caller of [emit_block_header_for_closure] must ensure that we are + already sufficiently aligned. If that involved doubleword alignment, + we emit a zero word here, to ensure that the function entry point + remains doubleword-aligned. *) + if function_entry_points_are_doubleword_aligned then begin + emit_string "\t"; + emit_string word_directive; + emit_string "\t"; + emit_nativeint Nativeint.zero; + emit_string " "; + emit_string comment_string; + emit_string " preserve entry point alignment\n" + end; + emit_string "\t"; + emit_string word_directive; + emit_string "\t"; + emit_nativeint header; + emit_string " "; + emit_string comment_string; + emit_string " GC block header\n" end let emit_debug_info dbg = diff --git a/asmcomp/emitaux.mli b/asmcomp/emitaux.mli index 2b4867d0b8..bd4f2d46fc 100644 --- a/asmcomp/emitaux.mli +++ b/asmcomp/emitaux.mli @@ -39,7 +39,6 @@ val emit_debug_info_gen : (file_num:int -> line:int -> col:int -> unit) -> unit type frame_debuginfo = - | Dbg_alloc of Debuginfo.alloc_dbginfo | Dbg_raise of Debuginfo.t | Dbg_other of Debuginfo.t @@ -70,7 +69,9 @@ val cfi_startproc : unit -> unit val cfi_endproc : unit -> unit val cfi_adjust_cfa_offset : int -> unit val cfi_offset : reg:int -> offset:int -> unit - +val cfi_def_cfa_offset : int -> unit +val cfi_remember_state : unit -> unit +val cfi_restore_state : unit -> unit val binary_backend_available: bool ref (** Is a binary backend available. If yes, we don't need @@ -79,3 +80,9 @@ val binary_backend_available: bool ref val create_asm_file: bool ref (** Are we actually generating the textual assembly file? *) + +val emit_block_header_for_closure + : word_directive:string + -> comment_string:string + -> function_entry_points_are_doubleword_aligned:bool + -> unit diff --git a/asmcomp/i386/selection.ml b/asmcomp/i386/selection.ml index ca8212a137..45bf40d9f3 100644 --- a/asmcomp/i386/selection.ml +++ b/asmcomp/i386/selection.ml @@ -246,13 +246,13 @@ method! select_operation op args dbg = method select_floatarith regular_op reversed_op mem_op mem_rev_op args = match args with - [arg1; Cop(Cload (chunk, _), [loc2], _)] -> - let (addr, arg2) = self#select_addressing chunk loc2 in - (Ispecific(Ifloatarithmem(chunk_double chunk, mem_op, addr)), + [arg1; Cop(Cload {memory_chunk}, [loc2], _)] -> + let (addr, arg2) = self#select_addressing memory_chunk loc2 in + (Ispecific(Ifloatarithmem(chunk_double memory_chunk, mem_op, addr)), [arg1; arg2]) - | [Cop(Cload (chunk, _), [loc1], _); arg2] -> - let (addr, arg1) = self#select_addressing chunk loc1 in - (Ispecific(Ifloatarithmem(chunk_double chunk, mem_rev_op, addr)), + | [Cop(Cload {memory_chunk}, [loc1], _); arg2] -> + let (addr, arg1) = self#select_addressing memory_chunk loc1 in + (Ispecific(Ifloatarithmem(chunk_double memory_chunk, mem_rev_op, addr)), [arg2; arg1]) | [arg1; arg2] -> (* Evaluate bigger subexpression first to minimize stack usage. @@ -286,10 +286,10 @@ method select_push exp = Cconst_int (n, _) -> (Ispecific(Ipush_int(Nativeint.of_int n)), Ctuple []) | Cconst_natint (n, _) -> (Ispecific(Ipush_int n), Ctuple []) | Cconst_symbol (s, _) -> (Ispecific(Ipush_symbol s), Ctuple []) - | Cop(Cload ((Word_int | Word_val as chunk), _), [loc], _) -> + | Cop(Cload ({memory_chunk = (Word_int | Word_val) as chunk}, _), [loc], _) -> let (addr, arg) = self#select_addressing chunk loc in (Ispecific(Ipush_load addr), arg) - | Cop(Cload (Double_u, _), [loc], _) -> + | Cop(Cload ({memory_chunk = Double_u}, _), [loc], _) -> let (addr, arg) = self#select_addressing Double_u loc in (Ispecific(Ipush_load_float addr), arg) | _ -> (Ispecific(Ipush), exp) diff --git a/asmcomp/linear.ml b/asmcomp/linear.ml index 37cf920035..e0cf104cdc 100644 --- a/asmcomp/linear.ml +++ b/asmcomp/linear.ml @@ -49,6 +49,7 @@ let has_fallthrough = function type fundecl = { fun_name: string; + fun_args: Reg.Set.t; fun_body: instruction; fun_fast: bool; fun_dbg : Debuginfo.t; diff --git a/asmcomp/linear.mli b/asmcomp/linear.mli index 2d1ce9430e..3d289411fe 100644 --- a/asmcomp/linear.mli +++ b/asmcomp/linear.mli @@ -50,6 +50,7 @@ val invert_test: Mach.test -> Mach.test type fundecl = { fun_name: string; + fun_args: Reg.Set.t; fun_body: instruction; fun_fast: bool; fun_dbg : Debuginfo.t; diff --git a/asmcomp/linearize.ml b/asmcomp/linearize.ml index 31b992a468..33a1b5b5fe 100644 --- a/asmcomp/linearize.ml +++ b/asmcomp/linearize.ml @@ -328,6 +328,7 @@ let fundecl f = fun_prologue_required in { fun_name = f.Mach.fun_name; + fun_args = Reg.set_of_array f.Mach.fun_args; fun_body; fun_fast = not (List.mem Cmm.Reduce_code_size f.Mach.fun_codegen_options); fun_dbg = f.Mach.fun_dbg; diff --git a/asmcomp/mach.ml b/asmcomp/mach.ml index 248c8185cd..2383068a31 100644 --- a/asmcomp/mach.ml +++ b/asmcomp/mach.ml @@ -52,7 +52,8 @@ type operation = | Itailcall_imm of { func : string; label_after : label; } | Iextcall of { func : string; ty_res : Cmm.machtype; ty_args : Cmm.exttype list; - alloc : bool; label_after : label; } + alloc : bool; label_after : label; + stack_ofs : int; } | Istackoffset of int | Iload of Cmm.memory_chunk * Arch.addressing_mode | Istore of Cmm.memory_chunk * Arch.addressing_mode * bool @@ -65,6 +66,8 @@ type operation = | Ispecific of Arch.specific_operation | Iname_for_debugger of { ident : Backend_var.t; which_parameter : int option; provenance : unit option; is_assignment : bool; } + | Ipoll + | Inop type instruction = { desc: instruction_desc; @@ -196,7 +199,7 @@ let spacetime_node_hole_pointer_is_live_before insn = | Iconst_symbol _ | Istackoffset _ | Iload _ | Istore _ | Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf | Ifloatofint | Iintoffloat - | Iname_for_debugger _ -> false + | Iname_for_debugger _ | Ipoll | Inop -> false end | Iend | Ireturn | Iifthenelse _ | Iswitch _ | Icatch _ | Iexit _ | Itrywith _ | Iraise _ -> false diff --git a/asmcomp/mach.mli b/asmcomp/mach.mli index d3cdd7a93d..51276e2d11 100644 --- a/asmcomp/mach.mli +++ b/asmcomp/mach.mli @@ -59,7 +59,8 @@ type operation = | Itailcall_imm of { func : string; label_after : label; } | Iextcall of { func : string; ty_res : Cmm.machtype; ty_args : Cmm.exttype list; - alloc : bool; label_after : label; } + alloc : bool; label_after : label; + stack_ofs : int; } | Istackoffset of int | Iload of Cmm.memory_chunk * Arch.addressing_mode | Istore of Cmm.memory_chunk * Arch.addressing_mode * bool @@ -81,6 +82,8 @@ type operation = (b) If [is_assignment] is [true], any information about other [Reg.t]s that have been previously deemed to hold the value of that identifier is forgotten. *) + | Ipoll + | Inop type instruction = { desc: instruction_desc; diff --git a/asmcomp/polling.ml b/asmcomp/polling.ml new file mode 100644 index 0000000000..c87bbd14d6 --- /dev/null +++ b/asmcomp/polling.ml @@ -0,0 +1,150 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) +open Mach +open Reg + +(* constants *) +let lmax = 50 +let k = 10 +let e = lmax/k + +let is_addr_live i = + not (Reg.Set.is_empty (Reg.Set.filter (fun f -> f.typ = Cmm.Addr) i)) + +let insert_poll_instr instr = + { desc = Iop (Ipoll); + next = instr; + arg = instr.arg; + res = [||]; + dbg = Debuginfo.none; + live = instr.live; + available_before = instr.available_before; + available_across = instr.available_across; + } + +let rec insert_poll_aux delta instr = + if (is_addr_live instr.live) then begin + { instr with next = (insert_poll_aux delta instr.next) } + end else begin + match instr.desc with + (* terminating condition *) + | Iend -> instr + + (* reset counter *) + | Iop (Ipoll) + | Iop (Ialloc _) -> + { instr with next = (insert_poll_aux 0 instr.next) } + + (* | Iop (Imove) *) + (* | Iop (Ispill) *) + (* | Iop (Ireload) *) + (* + -> + if (instr.Mach.arg.(0).loc = instr.Mach.res.(0).loc) then begin + { instr with next = (insert_poll_aux delta instr.next) } + end else begin + let updated_instr = { instr with next = insert_poll_aux delta instr.next} in + insert_poll_instr updated_instr + end + *) + + (* call type *) + (* + | Iop (Icall_imm _) -> + let updated_instr = { instr with next = insert_poll_aux delta instr.next} in + let poll_instr = insert_poll_instr updated_instr in + (poll_instr.live <- Reg.Set.add ({Reg.dummy with loc = Reg.Reg 0 ; typ = Cmm.Val}) poll_instr.live); + poll_instr + *) + + | Iop (Iconst_int _) + | Iop (Iconst_float _) + | Iop (Iconst_symbol _) + (* | Iop (Icall_ind _) *) + (* | Iop (Itailcall_ind _) *) + (* | Iop (Itailcall_imm _) *) + (* | Iop (Iextcall _) *) + | Iop (Istackoffset _) + (* | Iop (Iload _) *) + (* | Iop (Iintop _) (* signal_alloc.ml *) *) + | Iop (Inegf) + | Iop (Iabsf) + | Iop (Iaddf) + | Iop (Isubf) + | Iop (Imulf) + | Iop (Idivf) + | Iop (Ifloatofint) + | Iop (Iintoffloat) + (* | Iop (Iname_for_debugger _) *) + -> + if (delta > lmax-e) then begin + let updated_instr = { instr with next = insert_poll_aux 0 instr.next} in + insert_poll_instr updated_instr + end else begin + { instr with next = insert_poll_aux (delta+1) instr.next} + end + + (* other *) + (* | Iop (Iintop_imm (_, _, is_addr_upd)) -> (* signals_alloc failing *) + if (is_addr_upd) then begin + { instr with next = (insert_poll_aux delta instr.next) } + end else begin + let updated_instr = { instr with next = insert_poll_aux delta instr.next} in + insert_poll_instr updated_instr + end *) + (* + | Iop (Istore (_, _, is_assign)) -> + if (is_assign) then begin + let updated_instr = { instr with next = insert_poll_aux delta instr.next} in + insert_poll_instr updated_instr + end else begin + { instr with next = (insert_poll_aux delta instr.next) } + end + | Iop (Ispecific (Istore_int _)) -> + { instr with next = (insert_poll_aux delta instr.next) } + *) + (* signal_alloc failing + | Iop (Ispecific _) -> + let updated_instr = { instr with next = insert_poll_aux delta instr.next} in + insert_poll_instr updated_instr + *) + (* pass through - temp until all instructions handled *) + | Iifthenelse (t, ifso, ifnot) -> + { instr with + desc = Iifthenelse(t, + insert_poll_aux delta ifso, + insert_poll_aux delta ifnot); + next = insert_poll_aux delta instr.next } + | Iswitch (vals, cases) -> + { instr with + desc = Iswitch(vals, Array.map (insert_poll_aux delta) cases); + next = insert_poll_aux delta instr.next } + | Icatch (isrec, handlers, body) -> + { instr with + desc = Icatch(isrec, + List.map (fun (i,c) -> i, insert_poll_aux delta c) handlers, + insert_poll_aux delta body); + next = insert_poll_aux delta instr.next } + | Itrywith (e, h) -> + { instr with + desc = Itrywith(insert_poll_aux delta e, + insert_poll_aux delta h); + next = insert_poll_aux delta instr.next } + | _ -> { instr with next = (insert_poll_aux delta instr.next) } + end + +let insert_poll fun_body = + insert_poll_aux (lmax-e) fun_body + +let fundecl f = + let new_body = + insert_poll f.fun_body + in + { f with fun_body = new_body } diff --git a/asmcomp/polling.mli b/asmcomp/polling.mli new file mode 100644 index 0000000000..465fd9bcfd --- /dev/null +++ b/asmcomp/polling.mli @@ -0,0 +1,17 @@ +(**************************************************************************) +(* *) +(* OCaml *) +(* *) +(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) +(* *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) +(* *) +(* All rights reserved. This file is distributed under the terms of *) +(* the GNU Lesser General Public License version 2.1, with the *) +(* special exception on linking described in the file LICENSE. *) +(* *) +(**************************************************************************) + +(* Insertion of poll points according to balanced polling *) +val fundecl : Mach.fundecl -> Mach.fundecl diff --git a/asmcomp/printcmm.ml b/asmcomp/printcmm.ml index 61e7e04671..9814b42e1b 100644 --- a/asmcomp/printcmm.ml +++ b/asmcomp/printcmm.ml @@ -118,8 +118,10 @@ let operation d = function | Capply _ty -> "app" ^ location d | Cextcall(lbl, _ty_res, _ty_args, _alloc, _) -> Printf.sprintf "extcall \"%s\"%s" lbl (location d) - | Cload (c, Asttypes.Immutable) -> Printf.sprintf "load %s" (chunk c) - | Cload (c, Asttypes.Mutable) -> Printf.sprintf "load_mut %s" (chunk c) + | Cload {memory_chunk; mutability} -> ( + match mutability with + | Asttypes.Immutable -> Printf.sprintf "load %s" (chunk memory_chunk) + | Asttypes.Mutable -> Printf.sprintf "load_mut_imm %s" (chunk memory_chunk) ) | Calloc -> "alloc" ^ location d | Cstore (c, init) -> let init = @@ -156,6 +158,8 @@ let operation d = function | Ccmpf c -> Printf.sprintf "%sf" (float_comparison c) | Craise k -> Lambda.raise_kind k ^ location d | Ccheckbound -> "checkbound" ^ location d + | Cpoll -> "poll" + | Cnop -> "nop" let rec expr ppf = function | Cconst_int (n, _dbg) -> fprintf ppf "%i" n diff --git a/asmcomp/printmach.ml b/asmcomp/printmach.ml index 39128955af..78cdfe22ea 100644 --- a/asmcomp/printmach.ml +++ b/asmcomp/printmach.ml @@ -165,6 +165,8 @@ let operation op arg ppf res = reg arg.(0) | Ispecific op -> Arch.print_specific_operation reg op ppf arg + | Ipoll -> fprintf ppf "poll" + | Inop -> fprintf ppf "nop" let rec instr ppf i = if !Clflags.dump_live then begin diff --git a/asmcomp/reg.ml b/asmcomp/reg.ml index 2311a529bb..bc36dc9962 100644 --- a/asmcomp/reg.ml +++ b/asmcomp/reg.ml @@ -139,6 +139,22 @@ let name t = | None -> with_spilled | Some part -> with_spilled ^ "#" ^ Int.to_string part +let to_string r = + let loc_str = match r.loc with + | Unknown -> "U" + | Reg i -> "R("^(string_of_int i)^")" + | Stack sl -> match sl with + | Local i -> "S_L("^(string_of_int i)^")" + | Incoming i-> "S_I("^(string_of_int i)^")" + | Outgoing i -> "S_O("^(string_of_int i)^")" + in + let typ_str = match r.typ with + | Addr -> "A" + | Int -> "I" + | Float -> "F" + | Val -> "V" + in "("^loc_str^","^typ_str^")" + let first_virtual_reg_stamp = ref (-1) let reset() = diff --git a/asmcomp/reg.mli b/asmcomp/reg.mli index ad462c20a2..89b4e4220b 100644 --- a/asmcomp/reg.mli +++ b/asmcomp/reg.mli @@ -54,6 +54,7 @@ val anonymous : t -> bool (* Name for printing *) val name : t -> string +val to_string : t -> string module Set: Set.S with type elt = t module Map: Map.S with type key = t diff --git a/asmcomp/schedgen.ml b/asmcomp/schedgen.ml index 966dbbec1e..35fe1ec95c 100644 --- a/asmcomp/schedgen.ml +++ b/asmcomp/schedgen.ml @@ -388,6 +388,7 @@ method schedule_fundecl f = let new_body = schedule f.fun_body 0 in clear_code_dag(); { fun_name = f.fun_name; + fun_args = f.fun_args; fun_body = new_body; fun_fast = f.fun_fast; fun_dbg = f.fun_dbg; diff --git a/asmcomp/selectgen.ml b/asmcomp/selectgen.ml index f706518774..da8e003a5a 100644 --- a/asmcomp/selectgen.ml +++ b/asmcomp/selectgen.ml @@ -67,14 +67,15 @@ let env_empty = { let oper_result_type = function Capply ty -> ty | Cextcall(_s, ty_res, _ty_args, _alloc, _) -> ty_res - | Cload (c, _) -> - begin match c with + | Cload {memory_chunk} -> + begin match memory_chunk with | Word_val -> typ_val | Single | Double | Double_u -> typ_float | _ -> typ_int end | Calloc -> typ_val | Cstore (_c, _) -> typ_void + | Cpoll | Cnop -> typ_void | Caddi | Csubi | Cmuli | Cmulhi | Cdivi | Cmodi | Cand | Cor | Cxor | Clsl | Clsr | Casr | Ccmpi _ | Ccmpa _ | Ccmpf _ -> typ_int @@ -267,7 +268,7 @@ module Effect_and_coeffect : sig val none : t val arbitrary : t - val effect : t -> Effect.t + val effect_ : t -> Effect.t val coeffect : t -> Coeffect.t val pure_and_copure : t -> bool @@ -283,7 +284,7 @@ end = struct let none = Effect.None, Coeffect.None let arbitrary = Effect.Arbitrary, Coeffect.Arbitrary - let effect (e, _ce) = e + let effect_ (e, _ce) = e let coeffect (_e, ce) = ce let pure_and_copure (e, ce) = Effect.pure e && Coeffect.copure ce @@ -324,7 +325,8 @@ method is_simple_expr = function | Cop(op, args, _) -> begin match op with (* The following may have side effects *) - | Capply _ | Cextcall _ | Calloc | Cstore _ | Craise _ -> false + | Capply _ | Cextcall _ | Cnop | Cpoll | Calloc | Cstore _ + | Craise _ -> false (* The remaining operations are simple if their args are *) | Cload _ | Caddi | Csubi | Cmuli | Cmulhi | Cdivi | Cmodi | Cand | Cor | Cxor | Clsl | Clsr | Casr | Ccmpi _ | Caddv | Cadda | Ccmpa _ | Cnegf @@ -364,12 +366,13 @@ method effects_of exp = | Cop (op, args, _) -> let from_op = match op with - | Capply _ | Cextcall _ -> EC.arbitrary - | Calloc -> EC.none + | Capply _ | Cextcall _ | Cnop -> EC.arbitrary + | Calloc | Cpoll -> EC.none | Cstore _ -> EC.effect_only Effect.Arbitrary | Craise _ | Ccheckbound -> EC.effect_only Effect.Raise - | Cload (_, Asttypes.Immutable) -> EC.none - | Cload (_, Asttypes.Mutable) -> EC.coeffect_only Coeffect.Read_mutable + | Cload {mutability = Asttypes.Immutable} -> EC.none + | Cload {mutability = Asttypes.Mutable} -> + EC.coeffect_only Coeffect.Read_mutable | Caddi | Csubi | Cmuli | Cmulhi | Cdivi | Cmodi | Cand | Cor | Cxor | Clsl | Clsr | Casr | Ccmpi _ | Caddv | Cadda | Ccmpa _ | Cnegf | Cabsf | Caddf | Csubf | Cmulf | Cdivf | Cfloatofint | Cintoffloat | Ccmpf _ -> @@ -418,8 +421,8 @@ method mark_instr = function | Lambda.Raise_regular | Lambda.Raise_reraise -> (* PR#6239 *) - (* caml_stash_backtrace; we #mark_call rather than - #mark_c_tailcall to get a good stack backtrace *) + (* caml_stash_backtrace; we #mark_call rather than + #mark_c_tailcall to get a good stack backtrace *) self#mark_call end | Itrywith _ -> @@ -451,10 +454,10 @@ method select_operation op args _dbg = | None -> Cmm.new_label () | Some label_after -> label_after in - Iextcall { func; ty_res; ty_args; alloc; label_after; }, args - | (Cload (chunk, _mut), [arg]) -> - let (addr, eloc) = self#select_addressing chunk arg in - (Iload(chunk, addr), [eloc]) + Iextcall { func; alloc; ty_res; ty_args; label_after; stack_ofs = -1}, args + | (Cload {memory_chunk}, [arg]) -> + let (addr, eloc) = self#select_addressing memory_chunk arg in + (Iload(memory_chunk, addr), [eloc]) | (Cstore (chunk, init), [arg1; arg2]) -> let (addr, eloc) = self#select_addressing chunk arg1 in let is_assign = @@ -470,6 +473,8 @@ method select_operation op args _dbg = (Istore(chunk, addr, is_assign), [arg2; eloc]) (* Inversion addr/datum in Istore *) end + | (Cpoll, _) -> Ipoll, args + | (Cnop, _) -> Inop, args | (Calloc, _) -> (self#select_allocation 0), args | (Caddi, _) -> self#select_arith_comm Iadd args | (Csubi, _) -> self#select_arith Isub args @@ -741,15 +746,15 @@ method emit_expr (env:environment) exp = self#insert_debug env (Iop new_op) dbg loc_arg loc_res; self#insert_move_results env loc_res rd stack_ofs; Some rd - | Iextcall { ty_args; _} -> + | Iextcall r -> let spacetime_reg = self#about_to_emit_call env (Iop new_op) [| |] dbg in let (loc_arg, stack_ofs) = - self#emit_extcall_args env ty_args new_args in + self#emit_extcall_args env r.ty_args new_args in self#maybe_emit_spacetime_move env ~spacetime_reg; let rd = self#regs_for ty in let loc_res = - self#insert_op_debug env new_op dbg + self#insert_op_debug env (Iextcall {r with stack_ofs = stack_ofs}) dbg loc_arg (Proc.loc_external_results (Reg.typv rd)) in self#insert_move_results env loc_res rd stack_ofs; Some rd @@ -902,7 +907,7 @@ method private emit_parts (env:environment) ~effects_after exp = let module EC = Effect_and_coeffect in let may_defer_evaluation = let ec = self#effects_of exp in - match EC.effect ec with + match EC.effect_ ec with | Effect.Arbitrary | Effect.Raise -> (* Preserve the ordering of effectful expressions by evaluating them early (in the correct order) and assigning their results to @@ -924,14 +929,14 @@ method private emit_parts (env:environment) ~effects_after exp = every [exp'] (for [exp'] as in the comment above) has no effects "worse" (in the sense of the ordering in [Effect.t]) than raising an exception. *) - match EC.effect effects_after with + match EC.effect_ effects_after with | Effect.None | Effect.Raise -> true | Effect.Arbitrary -> false end | Coeffect.Arbitrary -> begin (* Arbitrary expressions may only be deferred if evaluation of every [exp'] (for [exp'] as in the comment above) has no effects. *) - match EC.effect effects_after with + match EC.effect_ effects_after with | Effect.None -> true | Effect.Arbitrary | Effect.Raise -> false end diff --git a/asmcomp/selectgen.mli b/asmcomp/selectgen.mli index f0d9df03fc..bb21b5c10a 100644 --- a/asmcomp/selectgen.mli +++ b/asmcomp/selectgen.mli @@ -49,7 +49,7 @@ module Effect_and_coeffect : sig val none : t val arbitrary : t - val effect : t -> Effect.t + val effect_ : t -> Effect.t val coeffect : t -> Coeffect.t val effect_only : Effect.t -> t diff --git a/asmcomp/spacetime_profiling.ml b/asmcomp/spacetime_profiling.ml index 9791026f46..9b6e649058 100644 --- a/asmcomp/spacetime_profiling.ml +++ b/asmcomp/spacetime_profiling.ml @@ -65,6 +65,9 @@ let reset ~spacetime_node_ident:ident ~function_label = current_function_label := Some function_label; reverse_shape := [] +let mk_load_mut memory_chunk = let open Cmm in + Cload {memory_chunk; mutability=Asttypes.Mutable; is_atomic=false} + let code_for_function_prologue ~function_name ~fun_dbg:dbg ~node_hole = let node = V.create_local "node" in let new_node = V.create_local "new_node" in @@ -98,9 +101,10 @@ let code_for_function_prologue ~function_name ~fun_dbg:dbg ~node_hole = Cop (Cor, [Cvar new_node; cconst_int 1], dbg), body) in + let pc = V.create_local "pc" in Clet (VP.create node, - Cop (Cload (Word_int, Asttypes.Mutable), [Cvar node_hole], dbg), + Cop (mk_load_mut Word_int, [Cvar node_hole], dbg), Clet (VP.create must_allocate_node, Cop (Cand, [Cvar node; cconst_int 1], dbg), Cifthenelse ( @@ -118,7 +122,7 @@ let code_for_function_prologue ~function_name ~fun_dbg:dbg ~node_hole = ], dbg)), Clet (VP.create new_node, - Cop (Cload (Word_int, Asttypes.Mutable), [Cvar node_hole], dbg), + Cop (mk_load_mut Word_int, [Cvar node_hole], dbg), if no_tail_calls then Cvar new_node else Cifthenelse ( @@ -166,7 +170,7 @@ let code_for_blockheader ~value's_header ~node ~dbg = cconst_int offset_into_node; ], dbg), Clet (VP.create existing_profinfo, - Cop (Cload (Word_int, Asttypes.Mutable), [Cvar address_of_profinfo], + Cop (mk_load_mut Word_int, [Cvar address_of_profinfo], dbg), Clet (VP.create profinfo, Cifthenelse ( @@ -177,7 +181,7 @@ let code_for_blockheader ~value's_header ~node ~dbg = generate_new_profinfo, dbg), Clet (VP.create existing_count, - Cop (Cload (Word_int, Asttypes.Mutable), [ + Cop (mk_load_mut Word_int, [ Cop (Caddi, [Cvar address_of_profinfo; cconst_int Arch.size_addr], dbg) ], dbg), @@ -255,7 +259,7 @@ let code_for_call ~node ~callee ~is_tail ~label dbg = Clet (VP.create count_addr, Cop (Caddi, [Cvar place_within_node; cconst_int Arch.size_addr], dbg), Clet (VP.create count, - Cop (Cload (Word_int, Asttypes.Mutable), [Cvar count_addr], dbg), + Cop (mk_load_mut Word_int, [Cvar count_addr], dbg), Csequence ( Cop (Cstore (Word_int, Lambda.Assignment), (* Adding 2 really means adding 1; the count is encoded @@ -336,7 +340,7 @@ class virtual instruction_selection = object (self) assert (Array.length arg = 1); self#instrument_indirect_call ~env ~callee:arg.(0) ~is_tail:true ~label_after dbg - | M.Iop (M.Iextcall { func; alloc = true; label_after; _}) -> + | M.Iop (M.Iextcall { func; alloc = true; label_after; _ }) -> (* N.B. No need to instrument "noalloc" external calls. *) assert (Array.length arg = 0); self#instrument_direct_call ~env ~func ~is_tail:false ~label_after dbg diff --git a/asmcomp/strmatch.ml b/asmcomp/strmatch.ml index 63d8407e57..a90881ae98 100644 --- a/asmcomp/strmatch.ml +++ b/asmcomp/strmatch.ml @@ -76,7 +76,7 @@ module Make(I:I) = struct let mk_let_cell id str ind body = let dbg = Debuginfo.none in let cell = - Cop(Cload (Word_int, Asttypes.Mutable), + Cop(Cload {memory_chunk=Word_int; mutability=Asttypes.Mutable; is_atomic=false}, [Cop(Cadda,[str;Cconst_int(Arch.size_int*ind, dbg)], dbg)], dbg) in Clet(id, cell, body) diff --git a/asmcomp/x86_ast.mli b/asmcomp/x86_ast.mli index 96d87bebb0..d3355bdf5b 100644 --- a/asmcomp/x86_ast.mli +++ b/asmcomp/x86_ast.mli @@ -208,6 +208,10 @@ type asm_line = | Cfi_adjust_cfa_offset of int | Cfi_endproc | Cfi_startproc + | Cfi_remember_state + | Cfi_restore_state + | Cfi_def_cfa_register of string + | Cfi_def_cfa_offset of int | File of int * string (* (file_num, file_name) *) | Indirect_symbol of string | Loc of int * int * int (* (file_num, line, col) *) diff --git a/asmcomp/x86_dsl.ml b/asmcomp/x86_dsl.ml index e647f66c67..18fecddf24 100644 --- a/asmcomp/x86_dsl.ml +++ b/asmcomp/x86_dsl.ml @@ -48,8 +48,10 @@ let ah = Reg8H AH let cl = Reg8L RCX let ax = Reg16 RAX let rax = Reg64 RAX +let rdx = Reg64 RDX let r10 = Reg64 R10 let r11 = Reg64 R11 +let r12 = Reg64 R12 let r13 = Reg64 R13 let r14 = Reg64 R14 let r15 = Reg64 R15 @@ -84,6 +86,10 @@ module D = struct let cfi_adjust_cfa_offset n = directive (Cfi_adjust_cfa_offset n) let cfi_endproc () = directive Cfi_endproc let cfi_startproc () = directive Cfi_startproc + let cfi_remember_state () = directive Cfi_remember_state + let cfi_restore_state () = directive Cfi_restore_state + let cfi_def_cfa_register reg = directive (Cfi_def_cfa_register reg) + let cfi_def_cfa_offset n = directive (Cfi_def_cfa_offset n) let comment s = directive (Comment s) let data () = section [ ".data" ] None [] let extrn s ptr = directive (External (s, ptr)) diff --git a/asmcomp/x86_dsl.mli b/asmcomp/x86_dsl.mli index 080331fcee..c587e8fac1 100644 --- a/asmcomp/x86_dsl.mli +++ b/asmcomp/x86_dsl.mli @@ -37,8 +37,10 @@ val ah: arg val cl: arg val ax: arg val rax: arg +val rdx: arg val r10: arg val r11: arg +val r12: arg val r13: arg val r14: arg val r15: arg @@ -74,6 +76,10 @@ module D : sig val cfi_adjust_cfa_offset: int -> unit val cfi_endproc: unit -> unit val cfi_startproc: unit -> unit + val cfi_remember_state: unit -> unit + val cfi_restore_state: unit -> unit + val cfi_def_cfa_register: string -> unit + val cfi_def_cfa_offset: int -> unit val comment: string -> unit val data: unit -> unit val extrn: string -> data_type -> unit diff --git a/asmcomp/x86_gas.ml b/asmcomp/x86_gas.ml index 6d2363a76b..4576e2a512 100644 --- a/asmcomp/x86_gas.ml +++ b/asmcomp/x86_gas.ml @@ -279,6 +279,10 @@ let print_line b = function | Cfi_adjust_cfa_offset n -> bprintf b "\t.cfi_adjust_cfa_offset %d" n | Cfi_endproc -> bprintf b "\t.cfi_endproc" | Cfi_startproc -> bprintf b "\t.cfi_startproc" + | Cfi_remember_state -> bprintf b "\t.cfi_remember_state" + | Cfi_restore_state -> bprintf b "\t.cfi_restore_state" + | Cfi_def_cfa_register reg -> bprintf b "\t.cfi_def_cfa_register %%%s" reg + | Cfi_def_cfa_offset n -> bprintf b "\t.cfi_def_cfa_offset %d" n | File (file_num, file_name) -> bprintf b "\t.file\t%d\t\"%s\"" file_num (X86_proc.string_of_string_literal file_name) diff --git a/asmcomp/x86_masm.ml b/asmcomp/x86_masm.ml index eb010b8b70..aa74e0c933 100644 --- a/asmcomp/x86_masm.ml +++ b/asmcomp/x86_masm.ml @@ -239,6 +239,10 @@ let print_line b = function | Cfi_adjust_cfa_offset _ | Cfi_endproc | Cfi_startproc + | Cfi_def_cfa_register _ + | Cfi_def_cfa_offset _ + | Cfi_remember_state + | Cfi_restore_state | File _ | Indirect_symbol _ | Loc _ diff --git a/boot/menhir/menhirLib.ml b/boot/menhir/menhirLib.ml index 8e1dc20f2a..8d7a20b4cb 100644 --- a/boot/menhir/menhirLib.ml +++ b/boot/menhir/menhirLib.ml @@ -3133,8 +3133,14 @@ module Make type item = int * int + let low_bits = + 10 + + let low_limit = + 1 lsl low_bits + let export t : item = - (t lsr 7, t mod 128) + (t lsr low_bits, t mod low_limit) let items s = (* Map [s] to its LR(0) core. *) @@ -3513,5 +3519,5 @@ module MakeEngineTable (T : TableFormat.TABLES) = struct end end module StaticVersion = struct -let require_20190924 = () +let require_20200211 = () end diff --git a/boot/menhir/menhirLib.mli b/boot/menhir/menhirLib.mli index fa523f59a5..714105e5a0 100644 --- a/boot/menhir/menhirLib.mli +++ b/boot/menhir/menhirLib.mli @@ -1701,5 +1701,5 @@ module MakeEngineTable and type nonterminal = int end module StaticVersion : sig -val require_20190924 : unit +val require_20200211: unit end diff --git a/boot/menhir/parser.ml b/boot/menhir/parser.ml index a643300db9..0b47eaeb97 100644 --- a/boot/menhir/parser.ml +++ b/boot/menhir/parser.ml @@ -2,7 +2,7 @@ (* This generated code requires the following version of MenhirLib: *) let () = - MenhirLib.StaticVersion.require_20190924 + MenhirLib.StaticVersion.require_20200211 module MenhirBasics = struct @@ -16,7 +16,7 @@ module MenhirBasics = struct | VAL | UNDERSCORE | UIDENT of ( -# 697 "parsing/parser.mly" +# 698 "parsing/parser.mly" (string) # 22 "parsing/parser.ml" ) @@ -28,7 +28,7 @@ module MenhirBasics = struct | THEN | STRUCT | STRING of ( -# 685 "parsing/parser.mly" +# 686 "parsing/parser.mly" (string * Location.t * string option) # 34 "parsing/parser.ml" ) @@ -41,12 +41,12 @@ module MenhirBasics = struct | RBRACKET | RBRACE | QUOTED_STRING_ITEM of ( -# 689 "parsing/parser.mly" +# 690 "parsing/parser.mly" (string * Location.t * string * Location.t * string option) # 47 "parsing/parser.ml" ) | QUOTED_STRING_EXPR of ( -# 687 "parsing/parser.mly" +# 688 "parsing/parser.mly" (string * Location.t * string * Location.t * string option) # 52 "parsing/parser.ml" ) @@ -54,7 +54,7 @@ module MenhirBasics = struct | QUESTION | PRIVATE | PREFIXOP of ( -# 671 "parsing/parser.mly" +# 672 "parsing/parser.mly" (string) # 60 "parsing/parser.ml" ) @@ -64,7 +64,7 @@ module MenhirBasics = struct | PERCENT | OR | OPTLABEL of ( -# 664 "parsing/parser.mly" +# 665 "parsing/parser.mly" (string) # 70 "parsing/parser.ml" ) @@ -82,12 +82,12 @@ module MenhirBasics = struct | MATCH | LPAREN | LIDENT of ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) # 88 "parsing/parser.ml" ) | LETOP of ( -# 629 "parsing/parser.mly" +# 630 "parsing/parser.mly" (string) # 93 "parsing/parser.ml" ) @@ -107,39 +107,39 @@ module MenhirBasics = struct | LBRACE | LAZY | LABEL of ( -# 634 "parsing/parser.mly" +# 635 "parsing/parser.mly" (string) # 113 "parsing/parser.ml" ) | INT of ( -# 633 "parsing/parser.mly" +# 634 "parsing/parser.mly" (string * char option) # 118 "parsing/parser.ml" ) | INITIALIZER | INHERIT | INFIXOP4 of ( -# 627 "parsing/parser.mly" +# 628 "parsing/parser.mly" (string) # 125 "parsing/parser.ml" ) | INFIXOP3 of ( -# 626 "parsing/parser.mly" +# 627 "parsing/parser.mly" (string) # 130 "parsing/parser.ml" ) | INFIXOP2 of ( -# 625 "parsing/parser.mly" +# 626 "parsing/parser.mly" (string) # 135 "parsing/parser.ml" ) | INFIXOP1 of ( -# 624 "parsing/parser.mly" +# 625 "parsing/parser.mly" (string) # 140 "parsing/parser.ml" ) | INFIXOP0 of ( -# 623 "parsing/parser.mly" +# 624 "parsing/parser.mly" (string) # 145 "parsing/parser.ml" ) @@ -147,7 +147,7 @@ module MenhirBasics = struct | IN | IF | HASHOP of ( -# 682 "parsing/parser.mly" +# 683 "parsing/parser.mly" (string) # 153 "parsing/parser.ml" ) @@ -160,7 +160,7 @@ module MenhirBasics = struct | FUN | FOR | FLOAT of ( -# 612 "parsing/parser.mly" +# 613 "parsing/parser.mly" (string * char option) # 166 "parsing/parser.ml" ) @@ -172,26 +172,27 @@ module MenhirBasics = struct | EOF | END | ELSE + | EFFECT | DOWNTO | DOTOP of ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 180 "parsing/parser.ml" +# 181 "parsing/parser.ml" ) | DOTDOT | DOT | DONE | DOCSTRING of ( -# 705 "parsing/parser.mly" +# 706 "parsing/parser.mly" (Docstrings.docstring) -# 188 "parsing/parser.ml" +# 189 "parsing/parser.ml" ) | DO | CONSTRAINT | COMMENT of ( -# 704 "parsing/parser.mly" +# 705 "parsing/parser.mly" (string * Location.t) -# 195 "parsing/parser.ml" +# 196 "parsing/parser.ml" ) | COMMA | COLONGREATER @@ -202,7 +203,7 @@ module MenhirBasics = struct | CHAR of ( # 592 "parsing/parser.mly" (char) -# 206 "parsing/parser.ml" +# 207 "parsing/parser.ml" ) | BEGIN | BARRBRACKET @@ -213,9 +214,9 @@ module MenhirBasics = struct | ASSERT | AS | ANDOP of ( -# 630 "parsing/parser.mly" +# 631 "parsing/parser.mly" (string) -# 219 "parsing/parser.ml" +# 220 "parsing/parser.ml" ) | AND | AMPERSAND @@ -789,7 +790,7 @@ let mk_directive ~loc name arg = } -# 793 "parsing/parser.ml" +# 794 "parsing/parser.ml" module Tables = struct @@ -799,60 +800,62 @@ module Tables = struct fun _tok -> match _tok with | AMPERAMPER -> - 123 + 124 | AMPERSAND -> - 122 + 123 | AND -> - 121 + 122 | ANDOP _ -> - 120 + 121 | AS -> - 119 + 120 | ASSERT -> - 118 + 119 | BACKQUOTE -> - 117 + 118 | BANG -> - 116 + 117 | BAR -> - 115 + 116 | BARBAR -> - 114 + 115 | BARRBRACKET -> - 113 + 114 | BEGIN -> - 112 + 113 | CHAR _ -> - 111 + 112 | CLASS -> - 110 + 111 | COLON -> - 109 + 110 | COLONCOLON -> - 108 + 109 | COLONEQUAL -> - 107 + 108 | COLONGREATER -> - 106 + 107 | COMMA -> - 105 + 106 | COMMENT _ -> - 104 + 105 | CONSTRAINT -> - 103 + 104 | DO -> - 102 + 103 | DOCSTRING _ -> - 101 + 102 | DONE -> - 100 + 101 | DOT -> - 99 + 100 | DOTDOT -> - 98 + 99 | DOTOP _ -> - 97 + 98 | DOWNTO -> + 97 + | EFFECT -> 96 | ELSE -> 95 @@ -1107,6 +1110,8 @@ module Tables = struct Obj.repr _v | DOWNTO -> Obj.repr () + | EFFECT -> + Obj.repr () | ELSE -> Obj.repr () | END -> @@ -1299,22 +1304,22 @@ module Tables = struct Obj.repr () and default_reduction = - (16, "\000\000\000\000\000\000\002\247\002\246\002\245\002\244\002\243\002\198\002\242\002\241\002\240\002\239\002\238\002\237\002\236\002\235\002\234\002\233\002\232\002\231\002\230\002\229\002\228\002\227\002\226\002\225\002\224\002\197\002\223\002\222\002\221\002\220\002\219\002\218\002\217\002\216\002\215\002\214\002\213\002\212\002\211\002\210\002\209\002\208\002\207\002\206\002\205\002\204\002\203\002\202\002\201\002\200\002\199\000\000\000\000\000*\000\186\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003<\001\168\001\147\001\165\001\164\001\163\001\169\001\173\000\000\003=\001\167\001\166\001\148\001\171\001\162\001\161\001\160\001\159\001\158\001\156\001\172\001\170\000\000\000\000\000\000\000\220\000\000\000\000\001\151\000\000\000\000\000\000\001\153\000\000\000\000\000\000\001\155\001\177\001\174\001\157\001\149\001\175\001\176\000\000\003;\003:\003>\000\000\000\000\000\024\001B\000\188\000\000\000\216\000\217\000\023\000\000\000\000\001\199\001\198\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0037\000\000\0032\000\000\000\000\0034\000\000\0036\000\000\0033\0035\000\000\003-\000\000\003,\003(\0022\000\000\003+\000\000\0023\000\000\000\000\000\000\000\000\000j\000\000\000\000\000h\000\000\000\000\001@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\184\001N\000\000\000\000\000\000\000\000\000\000\000\000\002\029\000\000\000\000\000\000\000\000\000\000\000\000\000e\000\000\000\000\000\000\000\000\001L\000\000\000\000\001O\001M\001U\000A\002\134\000\000\001\018\000\000\000\000\000\000\000\015\000\014\000\000\000\000\000\000\000\000\002\179\000\000\002e\002f\000\000\002c\002d\000\000\000\000\000\000\000\000\000\000\001e\001d\000\000\002\177\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\223\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\016\003\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000g\000\000\000\231\000\000\002h\002g\000\000\000\000\000\000\001\181\000\000\000\000\000%\000\000\000\000\000\000\000\000\000\000\001T\000\000\001S\000\000\001C\001R\000\000\001A\000b\000\030\000\000\000\000\001|\000\025\000\000\000\000\000\000\000\000\003'\000(\000\000\000\000\000\031\000\026\000\000\000\000\000\000\000\201\000\000\000\000\000\000\000\203\002<\002.\000\000\000\"\000\000\002/\000\000\000\000\001\178\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\017\003\017\000\000\003\018\000\000\000y\000\000\000\000\000!\000\000\000\000\000\000\000#\000\000\000$\000\000\000&\000\000\000\000\000'\002$\002#\000\000\000\000\000\000\000\000\000\000\000\000\000c\000\000\002\184\000f\000i\000d\002\173\003?\002\174\001\239\002\176\000\000\000\000\002\181\002b\002\183\000\000\000\000\000\000\002\190\002\187\000\000\000\000\000\000\001\236\001\222\000\000\000\000\000\000\000\000\001\226\000\000\001\221\000\000\001\238\002\196\000\000\001\237\000q\001\229\000\000\000o\000\000\002\189\002\188\000\000\001\232\000\000\000\000\001\228\000\000\000\000\001\224\001\223\000\000\002\186\000\000\002j\002i\000\000\000\000\002F\002\185\002\182\000\000\000\000\000\000\000\000\001\183\001-\001.\002l\000\000\002m\002k\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\241\000\242\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\204\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001o\000\000\000\000\000\000\000\000\000\000\000\000\003T\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003*\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002,\000\000\000\000\002-\000\000\000\000\001n\000\000\000\000\000\000\001K\001t\001J\001r\002 \002\031\000\000\001m\001l\000\000\000\205\000\000\000\000\001^\000\000\000\000\001b\000\000\001\203\001\202\000\000\000\000\001\201\001\200\001a\001_\000\000\001c\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\138\001P\002\143\002\141\000\000\000\000\000\000\002\154\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\172\000\000\002\171\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\250\000\000\000\000\000\000\000\000\000\000\000\000\000\239\001\249\000\240\000\000\000\000\000\000\001~\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\234\000\000\000\235\000\000\000\000\000\000\002\151\000\000\000\000\000\000\002r\002q\000\000\000\000\000\000\000\000\003@\002\153\002\140\002\139\000\000\000\000\000\169\000\000\000\000\000\000\000\000\000\000\000\183\000\000\000\000\000\000\000\168\000\000\000\000\000\000\002M\002L\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\243\000\000\002\250\000\000\003$\000\000\000\000\003#\000\000\000\000\000\000\000\000\000\000\000\195\000\194\000\244\000\000\002\251\002\252\000\000\000\000\000p\000\000\002\191\002\175\000\000\002\194\000\000\002\193\002\192\000\000\000\000\000\000\000\000\000\000\000\000\000\248\000\000\000\000\002&\000\000\000\000\000\000\000\247\000\000\000\000\000\246\000\245\000\000\000\000\000\000\000\000\000\250\000\000\000\000\000\249\000\000\001\235\000\000\000\000\001\246\000\000\000\000\001\248\000\000\000\000\001\244\001\243\001\241\001\242\000\000\000\000\000\000\000\000\000\000\001\024\000\018\000\252\000\000\000\000\000\000\002t\002s\000\000\000\000\002\130\002\129\000\000\000\000\000\000\000\000\002~\002}\000\000\000\000\002@\000\000\000\000\002|\002{\000\000\000\000\002\128\002\127\002\147\000\000\000\000\000\000\000\000\000\000\002x\000\000\000\000\000\000\000\000\000\000\002v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\"\002!\000\167\000\000\002w\000\000\000\000\002u\000\000\000\000\002y\000\000\000z\000{\000\000\000\000\000\000\000\000\000\138\000\196\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\197\000\000\000\198\000\199\000\131\000\000\000\130\000\000\000\000\0010\000\000\0011\001/\002(\000\000\000\000\002)\002'\000\000\000\000\000\000\000\000\000\000\001\003\000\000\000\000\001\004\000\000\000\000\000\170\000\000\001\006\001\005\000\000\000\000\002\155\002\148\000\000\002\164\000\000\002\165\002\163\000\000\002\169\000\000\002\170\002\168\000\000\000\000\002\150\002\149\000\000\000\000\000\000\002\016\000\000\001\197\000\000\000\000\000\000\002I\002\015\000\000\002\159\002\158\000\000\000\000\000\000\001Q\000\000\002\132\000\000\002\133\002\131\000\000\002\157\002\156\000\000\000\000\000\000\002C\002\146\000\000\002\145\002\144\000\000\002\167\002\166\000\128\000\000\000\000\000\000\000\000\000\127\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000}\000\000\001X\000\000\000\000\000\000\000k\000\000\000\000\000l\000\000\000\000\000\000\000\000\001v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\225\000\000\000\000\000u\000\000\000\228\000\226\000\000\000\000\000\000\000\207\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000~\000m\000\000\000\000\002\014\000\000\000\000\000\251\001\195\000\000\000\237\000\238\001\002\000\000\000\000\000\000\000\000\000\000\001\210\001\204\000\000\001\209\000\000\001\207\000\000\001\208\000\000\001\205\000\000\000\000\001\206\000\000\001\144\000\000\000\000\000\000\001\143\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001s\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\014\003\t\000\000\000\000\003\b\000\000\000\000\000\000\000\000\000\000\001\255\000\000\000\000\000\000\000\000\000\000\000\000\003\014\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\128\000\000\002\005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\249\000\000\000\000\002N\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\146\000\000\000\000\000\000\001\145\000\000\000\000\000\000\000\000\000\000\001g\000\000\001f\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\016\002\\\000\000\000\000\000\000\002Z\000\000\000\000\000\000\002Y\000\000\001Z\000\000\000\000\000\000\000\000\002_\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003H\000\000\000\000\000\000\000\193\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000E\000\000\000\000\000\000\000\000\001{\000\000\001z\000\000\000\000\000\000\000\000\000H\000\000\000\000\000\000\002\012\000\000\002\011\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000I\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000N\000\000\000\000\000\000\000O\000M\000\000\000R\000\000\000\000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\000\000\000\000\000\000J\000\000\000Q\000P\000\000\000K\000L\000\000\001!\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\012\000a\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000^\000\000\000`\000_\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\n\002`\002R\000\000\002X\002S\002^\002]\002[\001\027\000\000\002P\000\000\000\000\000\000\000\000\000\000\002\029\000\000\000\000\001\020\002T\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\139\001\135\000\000\000\000\000\000\000\210\000\000\000\000\002\019\002\029\000\000\000\000\001\022\002\017\002\018\000\000\000\000\000\000\000\000\000\000\001\142\001\138\001\134\000\000\000\000\000\211\000\000\000\000\001\141\001\137\001\133\001\131\002U\002Q\002a\001\026\001\252\002O\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003C\000\000\000\000\003E\000\000\0006\000\000\000\000\003K\000\000\003J\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003B\000\000\000\000\003D\000\000\000\000\000\000\002\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001?\000\000\000\000\001=\001;\000\000\0007\000\000\000\000\003N\000\000\003M\000\000\000\000\000\000\0019\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001>\000\000\000\000\001<\001:\000\000\000\000\000\000\0009\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\254\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000X\000\000\000\000\000\000\000\000\000\000\000\000\0003\000\000\000\000\000W\000\000\0001\000\255\000\000\000@\000-\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\253\000\000\000V\000U\000\000\000\000\000[\000Z\000\000\000\000\001\185\000\000\0005\000\000\000\000\000\000\0004\000\000\000\000\000\000\0008\000\000\000Y\000\\\000\000\000:\000;\000\000\001#\000\000\000\000\000\000\000\000\000\000\000\000\000>\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\b\003\012\003\003\000\000\000\000\003\007\002\248\003\002\003\011\003\n\001\031\000\000\000\000\003\000\000\000\003\004\003\001\003\r\001\251\000\000\000\000\002\254\000\000\000\191\002\253\000\000\000\000\000\222\000\000\000\000\001\030\001\029\000\000\001\\\001[\000\000\000\000\002\195\002\178\000\000\000B\000\000\000\000\000C\000\000\000\000\000\142\000\141\002\162\000\000\002\161\002\160\002\142\000\000\000\000\000\000\000\000\002\135\000\000\002\137\000\000\002\136\000\000\002o\002n\000\000\002p\000\000\000\000\000\134\000\000\000\000\002\004\000\215\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\189\000\000\003\006\002\024\002\025\002\020\002\022\002\021\002\023\000\000\000\000\000\000\000\190\000\000\000\000\002\029\000\000\000\214\000\000\000\000\000\000\000\000\003\005\000\000\000\187\000\000\000\000\000\000\000\000\0018\0012\000\000\000\000\0013\000\029\000\000\000\028\000\000\000\000\000\202\000\000\000\000\000\000\000 \000\027\000\000\000\000\000\000\000\021\000\000\000\000\000\000\000\000\001\140\001\136\000\000\001\132\003&\000\000\002\029\000\000\000\213\000\000\000\000\000\000\000\000\002W\002\028\002\026\002\027\000\000\000\000\000\000\002\029\000\000\000\212\000\000\000\000\000\000\000\000\002V\000\000\001i\001h\000\000\000\022\000\000\003F\000\000\000+\000\000\000\000\000\000\000\000\000\137\000\000\000\218\000\001\000\000\000\000\000\221\000\002\000\000\000\000\000\000\001E\001F\000\003\000\000\000\000\000\000\000\000\001H\001I\001G\000\019\001D\000\020\000\000\001\211\000\000\000\004\000\000\001\212\000\000\000\005\000\000\001\213\000\000\000\000\001\214\000\006\000\000\000\007\000\000\001\215\000\000\000\b\000\000\001\216\000\000\000\t\000\000\001\217\000\000\000\000\001\218\000\n\000\000\000\000\001\219\000\011\000\000\000\000\000\000\000\000\000\000\003\025\003\020\003\021\003\024\003\022\000\000\003\029\000\012\000\000\003\028\000\000\001%\000\000\000\000\003\026\000\000\003\027\000\000\000\000\000\000\000\000\001)\001*\000\000\000\000\001(\001'\000\r\000\000\000\000\000\000\0039\000\000\0038") + (16, "\000\000\000\000\000\000\003\001\003\000\002\255\002\254\002\253\002\208\002\252\002\251\002\250\002\249\002\248\002\247\002\246\002\245\002\244\002\243\002\242\002\241\002\240\002\239\002\238\002\237\002\236\002\235\002\234\002\207\002\233\002\232\002\231\002\230\002\229\002\228\002\227\002\226\002\225\002\224\002\223\002\222\002\221\002\220\002\219\002\218\002\217\002\216\002\215\002\214\002\213\002\212\002\211\002\210\002\209\000\000\000\000\000*\000\194\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003G\001\176\001\155\001\173\001\172\001\171\001\177\001\181\000\000\003H\001\175\001\174\001\156\001\179\001\170\001\169\001\168\001\167\001\166\001\164\001\180\001\178\000\000\000\000\000\000\000\228\000\000\000\000\001\159\000\000\000\000\000\000\001\161\000\000\000\000\000\000\001\163\001\185\001\182\001\165\001\157\001\183\001\184\000\000\003F\003E\003I\000\000\000\000\000\024\001J\000\196\000\000\000\224\000\225\000\023\000\000\000\000\001\207\001\206\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003B\000\000\003=\000\000\000\000\003?\000\000\003A\000\000\003>\003@\000\000\0038\000\000\0037\0033\002;\000\000\0036\000\000\002<\000\000\000\000\000\000\000\000\000j\000\000\000\000\000h\000\000\000\000\001H\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\192\001V\000\000\000\000\000\000\000\000\000\000\000\000\002&\000\000\000\000\000\000\000\000\000\000\000\000\000e\000\000\000\000\000\000\000\000\001T\000\000\000\000\001W\001U\001]\000A\002\144\000\000\001\026\000\000\000\000\000\000\000\015\000\014\000\000\000\000\000\000\000\000\002\189\000\000\002o\002p\000\000\002m\002n\000\000\000\000\000\000\000\000\000\000\001m\001l\000\000\002\187\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\231\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\027\003\026\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000g\000\000\000\239\000\000\002r\002q\000\000\000\000\000\000\001\189\000\000\000\000\000%\000\000\000\000\000\000\000\000\000\000\001\\\000\000\001[\000\000\001K\001Z\000\000\001I\000b\000\030\000\000\000\000\001\132\000\025\000\000\000\000\000\000\000\000\0032\000(\000\000\000\000\000\031\000\026\000\000\000\000\000\000\000\209\000\000\000\000\000\000\000\211\002E\0027\000\000\000\"\000\000\0028\000\000\000\000\001\186\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\017\003\028\000\000\003\029\000\000\000y\000\000\000\000\000!\000\000\000\000\000\000\000#\000\000\000$\000\000\000&\000\000\000\000\000'\002-\002,\000\000\000\000\000\000\000\000\000\000\000\000\000c\000\000\002\194\000f\000i\000d\002\183\003J\002\184\001\248\002\186\000\000\000\000\002\191\002l\002\193\000\000\000\000\000\000\002\200\002\197\000\000\000\000\000\000\000\000\000\000\001\238\002\206\002\192\000q\001\245\001\230\000\000\000\000\000\000\000\000\001\234\000\000\001\229\000\000\001\247\000\000\001\246\001\237\000\000\000o\000\000\002\199\002\198\000\000\001\241\000\000\000\000\001\236\000\000\000\000\001\232\001\231\000\000\002\196\000\000\002t\002s\000\000\000\000\002O\002\195\000\000\000\000\000\000\000\000\001\191\0015\0016\002v\000\000\002w\002u\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\249\000\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\212\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001w\000\000\000\000\000\000\000\000\000\000\000\000\003_\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0035\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0025\000\000\000\000\0026\000\000\000\000\001v\000\000\000\000\000\000\001S\001|\001R\001z\002)\002(\000\000\001u\001t\000\000\000\213\000\000\000\000\001f\000\000\000\000\001j\000\000\001\211\001\210\000\000\000\000\001\209\001\208\001i\001g\000\000\001k\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\148\001X\002\153\002\151\000\000\000\000\000\000\002\164\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\182\000\000\002\181\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\003\000\000\000\000\000\000\000\000\000\000\000\000\000\247\002\002\000\248\000\000\000\000\000\000\001\134\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\242\000\000\000\243\000\000\000\000\000\000\002\161\000\000\000\000\000\000\002|\002{\000\000\000\000\000\000\000\000\003K\002\163\002\150\002\149\000\000\000\000\000\177\000\000\000\000\000\000\000\000\000\000\000\191\000\000\000\000\000\000\000\176\000\000\000\000\000\000\002V\002U\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\251\000\000\003\004\000\000\003/\000\000\000\000\003.\000\000\000\000\000\000\000\000\000\000\000\203\000\202\000\252\000\000\003\005\003\006\000\000\000\000\000p\000\000\002\201\002\185\000\000\002\204\000\000\002\203\002\202\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\002/\000\000\000\000\000\000\000\255\000\000\000\000\000\254\000\253\000\000\000\000\000\000\000\000\001\002\000\000\000\000\001\001\000\000\001\244\000\000\000\000\001\255\000\000\000\000\002\001\000\000\000\000\001\253\001\252\001\250\001\251\000\000\000\000\000\000\000\000\000\000\001 \000\018\001\004\000\000\000\000\000\000\002~\002}\000\000\000\000\002\140\002\139\000\000\000\000\000\000\000\000\002\136\002\135\000\000\000\000\002I\000\000\000\000\002\134\002\133\000\000\000\000\002\138\002\137\002\157\000\000\000\000\000\000\000\000\000\000\002\130\000\000\000\000\000\000\000\000\000\000\002\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\132\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002+\002*\000\175\000\000\002\129\000\000\000\000\002\127\000\000\000\000\002\131\000\000\000z\000{\000\000\000\000\000\000\000\000\000\146\000\204\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\205\000\000\000\206\000\207\000\139\000\000\000\138\000\000\000\000\0018\000\000\0019\0017\0021\000\000\000\000\0022\0020\000\000\000\000\000\000\000\000\000\000\001\011\000\000\000\000\001\012\000\000\000\000\000\178\000\000\001\014\001\r\000\000\000\000\002\165\002\158\000\000\002\174\000\000\002\175\002\173\000\000\002\179\000\000\002\180\002\178\000\000\000\000\002\160\002\159\000\000\000\000\000\000\002\025\000\000\001\205\000\000\000\000\000\000\002R\002\024\000\000\002\169\002\168\000\000\000\000\000\000\001Y\000\000\002\142\000\000\002\143\002\141\000\000\002\167\002\166\000\000\000\000\000\000\002L\002\156\000\000\002\155\002\154\000\000\002\177\002\176\000\136\000\000\000\000\000\000\000\000\000\135\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\133\000\000\001`\000\000\000\000\000\000\000k\000\000\000\000\000l\000\000\000\000\000\000\000\000\001~\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\233\000\000\000\000\000u\000\000\000\236\000\234\000\000\000\000\000\000\000\215\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\134\000m\000\000\000\000\002\023\000\000\000\000\001\003\001\203\000\000\000\245\000\246\001\n\000\000\000\000\000\000\000\000\000\000\001\218\001\212\000\000\001\217\000\000\001\215\000\000\001\216\000\000\001\213\000\000\000\000\001\214\000\000\001\152\000\000\000\000\000\000\001\151\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001{\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\022\003\020\000\000\000\000\003\019\000\000\000\000\000\000\000\000\000\000\002\b\000\000\000\000\000\000\000\000\000\000\000\000\003\025\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\136\000\000\002\014\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\003\000\000\000\000\002W\000\000\003\n\000\131\000\130\000\000\000\000\000\000\000\000\000\127\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000~\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\154\000\000\000\000\000\000\001\153\000\000\000\000\000\000\000\000\000\000\001o\000\000\001n\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\024\002f\000\000\000\000\000\000\002d\000\000\000\000\000\000\002c\000\000\001b\000\000\000\000\000\000\000\000\002i\000\000\000\000\000\000\000\000\000\000\002Z\000\000\000\000\000\000\000\000\000\000\000\000\003S\000\000\000\000\000\000\000\201\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000E\000\000\000\000\000\000\000\000\001\131\000\000\001\130\000\000\000\000\000\000\000\000\000H\000\000\000\000\000\000\002\021\000\000\002\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000I\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000N\000\000\000\000\000\000\000O\000M\000\000\000R\000\000\000\000\000\000\000\000\000\000\000G\000\000\000\000\000\000\000\000\000\000\000\000\000J\000\000\000Q\000P\000\000\000K\000L\000\000\001)\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\020\000a\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000^\000\000\000`\000_\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\018\002j\002\\\000\000\002b\002]\002h\002g\002e\001#\000\000\002Y\000\000\000\000\000\000\000\000\000\000\002&\000\000\000\000\001\028\002^\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\147\001\143\000\000\000\000\000\000\000\218\000\000\000\000\002\028\002&\000\000\000\000\001\030\002\026\002\027\000\000\000\000\000\000\000\000\000\000\001\150\001\146\001\142\000\000\000\000\000\219\000\000\000\000\001\149\001\145\001\141\001\139\002_\002[\002k\001\"\002\005\002X\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003N\000\000\000\000\003P\000\000\0006\000\000\000\000\003V\000\000\003U\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003M\000\000\000\000\003O\000\000\000\000\000\000\002\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001G\000\000\000\000\001E\001C\000\000\0007\000\000\000\000\003Y\000\000\003X\000\000\000\000\000\000\001A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001F\000\000\000\000\001D\001B\000\000\000\000\000\000\0009\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000X\000\000\000\000\000\000\000\000\000\000\000\000\0003\000\000\000\000\000W\000\000\0001\001\007\000\000\000@\000-\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\005\000\000\000V\000U\000\000\000\000\000[\000Z\000\000\000\000\001\193\000\000\0005\000\000\000\000\000\000\0004\000\000\000\000\000\000\0008\000\000\000Y\000\\\000\000\000:\000;\000\000\001+\000\000\000\000\000\000\000\000\000\000\000\000\000>\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\016\003\023\003\014\000\000\000\000\003\018\003\002\003\r\003\022\003\021\001'\000\000\000\000\003\011\000\000\003\015\003\012\003\024\002\004\000\000\000\000\003\b\000\000\000\199\003\007\000\000\000\000\000\230\000\000\000\000\001&\001%\000\000\001d\001c\000\000\000\000\002\205\002\188\000\000\000B\000\000\000\000\000C\000\000\000\000\000\150\000\149\002\172\000\000\002\171\002\170\002\152\000\000\000\000\000\000\000\000\002\145\000\000\002\147\000\000\002\146\000\000\002y\002x\000\000\002z\000\000\000\000\000\142\000\000\000\000\002\r\000\223\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\197\000\000\003\017\002!\002\"\002\029\002\031\002\030\002 \000\000\000\000\000\000\000\198\000\000\000\000\002&\000\000\000\222\000\000\000\000\000\000\000\000\003\016\000\000\000\195\000\000\000\000\000\000\000\000\001@\001:\000\000\000\000\001;\000\029\000\000\000\028\000\000\000\000\000\210\000\000\000\000\000\000\000 \000\027\000\000\000\000\000\000\000\021\000\000\000\000\000\000\000\000\001\148\001\144\000\000\001\140\0031\000\000\002&\000\000\000\221\000\000\000\000\000\000\000\000\002a\002%\002#\002$\000\000\000\000\000\000\002&\000\000\000\220\000\000\000\000\000\000\000\000\002`\000\000\001q\001p\000\000\000\022\000\000\003Q\000\000\000+\000\000\000\000\000\000\000\000\000\145\000\000\000\226\000\001\000\000\000\000\000\229\000\002\000\000\000\000\000\000\001M\001N\000\003\000\000\000\000\000\000\000\000\001P\001Q\001O\000\019\001L\000\020\000\000\001\219\000\000\000\004\000\000\001\220\000\000\000\005\000\000\001\221\000\000\000\000\001\222\000\006\000\000\000\007\000\000\001\223\000\000\000\b\000\000\001\224\000\000\000\t\000\000\001\225\000\000\000\000\001\226\000\n\000\000\000\000\001\227\000\011\000\000\000\000\000\000\000\000\000\000\003$\003\031\003 \003#\003!\000\000\003(\000\012\000\000\003'\000\000\001-\000\000\000\000\003%\000\000\003&\000\000\000\000\000\000\000\000\0011\0012\000\000\000\000\0010\001/\000\r\000\000\000\000\000\000\003D\000\000\003C") and error = - (124, "'\225 \197\138\173\2433\208\020\015\228\000\003\142\0026\016\004\\(\223\018}\000@\248\000\000\024\224}\246D\b/\227P\000L\028\030\227\139\002\131@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\175\235f\245\155\175\2437\252\149\031\226\017\007\158\007\223d@\130\2545\000\004\193\193\2388\176(4\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000#a\000E\130\141\241'\208\004\015\128\000\001\142\007\223d@\130\2545\000\004\193\193\2388\176(4'\225\"\213\138\173\2433\208\020\015\224\000\007\142\000\000\000\000\004\000\012\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\192\004\000\000\000\000\000\000\000\000\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\128\000\128\007\224,$\000\003\226 \016@\016(\176\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000(\000\000\000\000\000\000\000\000\000\024\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\007\001\002\012\\ \000\016\000\000\000\000\000\001\000@@@ \193\004\000\000\016\000\000\000\000\000\016\004\004\000\002\012\016@\000\001\000\000\000\000\000\001\000@@\000 \193\000\000\000\016\000\000\000\000\012H\002\168\000\131\t!\192\001\016\007a\002 \004\132\128 \128\b \002\020\000\016\000b\000\002\000\bH\002\b\000\130\000!\000\001\000\006 \000 \000\003\000\000$\193\004\192\004\000\128\000\000\000\000\b\0000\000\002H\016L\000@\b\000\000\000\000\000\128\003\000\000$\129\004\192\000\000\128\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000 \000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000$\128\004\192\000\000\128\000\000\000\000\b\000 \000\002\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\002H\000@\000\000\b\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\002\b\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000$\128\004\000\000\000\128\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\bH\002( \130\000!\128\001\000\007`\017 \004\003 \000x\016\000\197\194\128\001\000\128 \000\016\bH\002(\000\194\t!\192\001\016\006a\016a\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\000\007\001\000\012\\(\000\016\b\002\000\001\000\003\000\bp\016 \197\194\000\001\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\197\128\187\128\b2R\028\012\017 v\001f\017`0\000\006\000\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\006\000\000\012\\ \000\018\000\002\000\000\000\001\000\016\000\000\000@\000\000\001 \000\000\004\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\bP\t\026\000\001$!\192\192\018\001!\018\000\016}\246D\b/\227P\000L\028\030\227\139\002\131B~\018-X\170\2233=\001@\254\000\000x\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000$\193\004\192\004\000\128\000\000\000\000\b\0000\000\002H\016L\000@\b\000\000\000\000\000\128\003\000\000$\129\004\192\000\000\128\000\000\000\000\b\0000\000\002H\000L\000\000\b\000\000\000\000\000\128\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\bH\002( \130\001!\128\001\016\007`\016 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\001!\128\001\016\006`\016 \004}\246D\b/\227P\000L\028\030\227\139\002\131B~\018-X\170\2233=\001@\254\000\000x\224#a\000E\194\141\241'\208\004\015\128\000\001\142\0026\016\004X(\223\018}\000@\248\000\000\024\224#a\000E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001!\000D\000\128\193#\144\000\001\128\000\001\140\000\016\000\000\004\000\004\000@\000\000\000\000\000\000\000\001\000\000\000\000\000@\004\000\000\000\000\000\000\000\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\175\235w\253\155\239\247\255\252\157?\230!\003\158@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\163a\136G\226\173\245#\211\230/\144@\025\174\184\018\016\132@\b\012\0189\000\000\024\000\000\024\192#a\000E\130\141\241#\208\004\015\128\000\001\206\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b@\000\b\004\000(!@\192\000\000 \016\000\000\132\000\000\128\000\002\130\020\012\000\000\002\001\000\000\b@\000\b\000\000(!\000\192\000\000 \016\000\000\003!\000@\128\004\193\"\208\001\001\160\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\131!\136G\224,\229\"\211\227!\176@\025,\184\000\000\128\000\000\000\000\001\000\000\016\000\000\000\000\131\000\000\000@\000\000\004\000\000\000\000\000\000\000\0000\000\000\000\000\000\000@\000\000\000\000\000\000\000\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\004\004\000\002\012\016\000\000\001\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\001\002\000@\000\000\129\004\000\000\016\000\000\000\000\000\016 \004\000\000\b\016\000\000\001\000\000\000\000\000\167\225 \197\138\173\2437\208\020\015\226\000\003\142\n~\018\012X\170\2233=\001@\254 \0008\224\167\225\"\197\138\173\2433\208\020\015\230\000\003\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\002\000@@\000\129\004\000\000\016\000\000\000\b\000\016 \004\004\000\b\016@\000\001\000\000\000\000\000\001\002\000@\000\000\129\004\000\000\016\000\000\000\000\000\016 \004\000\000\b\016\000\000\001\000\000\000\000\000\005\002\000@\000\000\129\000\000\000\016\000\000\000\000\0026\016\004X(\223\018}\000@\248\000\000\024\224#a\000E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0026\016\004\\(\223\018}\000@\248\000\000\024\224#a\000E\130\141\241'\208\004\015\128\000\001\142\0026\016\004X(\223\018=\000@\248\000\000\024\224\197\189\187\215\248\190\223?\191\251a\247\219\127\252\2426\016\004X(\223\018=\000@\248\000\000\024\224\003!\000@\128\004\193\"\208\001\001\128\000\001\004\0002\016\004\b\000L\018-\000\016\026\000\000\020@\003!\002@\128\004\193\"\208\001\001\160\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\001\016\000\000\000\000\000\000\000\001\000\000@\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\001@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000@\003\000\002p\016\000\197\194\000\001\000\000\000\000\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\004\0000\000\007\001\000\012\\ \000\016\000\000\000\001@\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\001\000\000\000\129\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\128\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000@\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012H\003\184\000\131!!\192\193\018\007`\022!\022\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\012H\011\184\000\131!!\192\193\018\007`\022!\022\003\000\000`\000\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012X\011\184\000\131%!\192\193\018\007`\022!\022\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\006\000\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012X\011\184\000\131%!\192\193\018\007`\022!\022\003\000\000`\000\000\197\194\000\001\000\000\000\000\000\012X\011\184\000\131%!\192\193\018\007`\022!\022\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000@\000\000@\000\002\000\000\000\001\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000 \000\000\000\000@\000\002\000\000\000\001\002\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\004\000\000 \000\000\000\017 \000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000@\000\002\000\000\000\001\018\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000@\000\002\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012H\003\184\000\131!!\192\193\018\007`\022!\020\000\000\002\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\0000\000\007\001\000\012\\ \000\016\000\000\000\000@\000\000\002\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000 \000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000 \000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\001\016\000\000\000\000@\000\000\001\000\000\000\000\128\000\017\000\000\000\000\000\000\000\000\016\000\000\000\0002\016\004\b\000L\018-\000\016\026\000\000\016@\003!\000@\192\004\193&\144\001\001\128\000\001\004\0002\016\004\b\000L\018i\000\016\024\000\000\016@\003!\000@\128\004\193\"\144\001\001\128\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\147)\027P\144\020\193&\176\001\001\148 mU\000\000\016\000\b\000@\000\001\000\000\016\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t2\145\181\t\001L\018o\000\016\027A\006\213P\001\000\000\000\000\000\128\"\128\000\000\000\000\000\000\b2\016\132\b\000L\018-\000\016\026\000\000\144@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003!\000@\192\004\193&\208\001\001\160\000\001\004\0002\016\004\b\000L\018m\000\016\026\000\000\016@\003!\000@\128\004\193\"\208\001\001\160\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\000\001\176\000\001\000\000@\000\000\001@\004\197\016\003!\000@\128\004\193\"\208\001\001\160\000\001\004\t\000\001\176\000\001\000\000@\000\000\001@\004\197\016\131!\000@\128\004\193\"\208\001\001\160\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\144\000\027\000\000\016\000\004\000\000\000\020\000LQ\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\147!\027@\128\020\193&\208\001\001\180\000MU\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t2\017\180\b\001L\018m\000\016\027@\004\213P\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\128\000\000\000\000@\000\000\000\000\004\129\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\131!\000@\128\004\193\"\208\001\001\160\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\144\000\027\000\000\016\000\004\000\000\000\020\000LQ\b2\016\004\b\000L\018-\000\016\026\000\000\016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\000\001\176\000\001\000\000@\000\000\001@\004\197\016\128\000\000\000\000\000\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\016$\b\000L\018-\000\016\026\000\000\016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\018\000\000\000\000\004\000\000\000\000\000HQ\b2\016$\b\000L\018-\000\016\026\000\000\020@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\001\016\000\000\000\000@\000\000\000\000\004\129\016\128\000\017\000\000\000\000\000\000\000\000\000\000\000\000\b0\000\016\000\000\004\000\000\000\000\000\000\000\000\000\128\000\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003)\000P\144\004\193&\176\001\001\144\000M\021\000\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\001\000\000@\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\128\000\000\000\000@\000\000\001\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\001\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\0002\016D\012\130L\018m\000\016\026\000\000\016@\001\002\000@@\000\129\004\000\000\016\000\000\000\b\000\016 \004\004\000\b\016@\000\001\000\000\000\000\000\001\002\000@\000\000\129\004\000\000\016\000\000\000\000\000\016 \004\000\000\b\016\000\000\001\000\000\000\000\000\000\000\000\000\000\000\128\004\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\003\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\016\004\004\000\002\012\016\000\000\001\000\000\000\000\000\001\000@@\000 \193\000\000\000\016\000\000\000\000\000\000\000\000\000\000\b\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\001\b\000\000\000\000\000\000\000\000\000\001\000@@\000 \193\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\128*\128\b0\018\028\000\017\000v\000\"\000@\b\000\000\000\002\000\000\000\000\000\000\000\000\000\000\003\000\000$\128\004\192\000\000\128\000\000\000\000\b\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\016\000\0000\000\007\129\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\196\128*\128\b0\018\028\000\017\000v\000\"\001@0\000\007\001\000\012\\ \000\016\000\000\000\000\000\196\128*\128\b0\018\028\000\017\000v\001\"\001LH\002\168\000\131\001!\192\001\016\007`\018 \004\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\001\000\000\000\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\012H\002\168\000\131\001!\192\001\016\007`\018 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\016\016\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\128*\128\b0\146\028\000\017\000v\016\"\000@\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012H\002\168\000\131\t!\192\001\016\007a\002 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012H\002\168\000\131\001!\192\001\016\007`\002 \004\000\128\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000@@\000 \193\000\000\000\016\000\000\000\000\012H\002\168\000\131\001!\192\001\016\007`\002 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\001\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\012H\002\168\000\131\t!\192\001\016\007a\002 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\192\000\b\000\000\016\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\128\000\001\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\b\000\000\000\000\000\000\000\000\000\001\002\000@\000\000\129\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\128*\128\b0\146\028\000\025\000v\000&\000@P \132\000\000\b\016\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\128\000\000\b\000@\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000@@\000 \193\000\000\000\016\000\000\000\000\012\000\000\128\000\001\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\128*\128\b0\146\028\000\025\000v\016&\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\004\000\b\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224#a\002E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\004\000\000\000\004\000\000\000\000\000\128\000\016\000\000\000\000\000\000\000@\016\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\001!\000D\000\128\193#\144\000\001\128\000\001\140\012\000\001\016\000\000\000\000\000\0000\001\005\002@\000#a\000E\194\141\241'\208\004\015\130\000\001\142\0026\016\004X(\223\018}\000@\248 \000\024\224#a\000E\130\141\241#\208\004\015\130\000\001\142\000\018\016\004D\b\012\018y\000\000\024\000\000\024\192\001!\000D\000\128\193'\144\000\001\128\000\001\140\000\018\016\004@\b\012\0189\000\000\024\000\000\024\192\001!\000D\000\128\193#\144\000\001\128\000\001\140\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012[\219\189\127\139\237s\251\255\182\031}\183\255\223\001\000\000\000\000\000\192#\128\000\000\000\000\000\000\n6\024\132~*\223R=>b\249\004\001\154\235\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n6\016\132X(\223\018=\000@\248\000\000\024\224\163a\bE\130\141\241#\208\004\015\128\000\001\142\b\016 \004\004\000\b\016@\000\001\000\000\000\000\000\001\002\000@\000\000\129\004\000\000\016\000\000\000\000\000\016 \004\000\000\b\016\000\000\001\000\000\000\000\000\000\000\000\000\000\000\128\004\000\000\000\000\000\004\000\b\016\004\004\000\002\012\016\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\128\000\001\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n6\016\132X(\223\018=\000@\248\000\000\024\224\163a\bE\130\141\241#\208\004\015\128\000\001\142\b2\016\132\b\000L\018-\000\016\024\000\000\016@\000\000\000\000\000\000\000\004\000\000\000\016\000L\017\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224#a\000E\194\141\241'\208\004\015\128\000\001\142\0026\016\004X(\223\018}\000@\248\000\000\024\224#a\000E\130\141\241#\208\004\015\128\000\001\142\0002\016\004\012\000L\018m\000\016\026\000\000\017@\003!\000@\128\004\193&\208\001\001\160\000\001\020\0002\016\004\b\000L\018-\000\016\026\000\000\017@\003!\000@\128\004\193\"\208\001\001\160\000\001\004\001\000\000\000\000\001\000\000@\000\000\000\000\004\129\016#a\000E\130\141\241#\208\004\015\128\000\001\142\0002\144\005\r\000L\018k\000\016\024\000\000\016@\003)\000P\144\004\193&\176\001\001\128\000\001\004\0002\144\005\t\000L\018+\000\016\024\000\000\016@\002\000\000\000\000\000\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003!\000@\128\004\193\"\208\001\001\160\000\001\004\000\000\000\128\000\000\000\000@\000\000\001\000\004\193\016\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\128\000\000\000\000@\000\000\001\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b:\024\132~\002\206R->2\027\004\001\146\203\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\128\000\000\004\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\003)\000P\144\020\193\"\176\001\001\128\000\005\004\0026\016\004X(\223\018=\000@\248\000\000\024\224\003!\000@\192\004\193&\208\001\001\160\000\001\004\0002\016\004\b\000L\018m\000\016\026\000\000\016@\003!\000@\128\004\193\"\208\001\001\160\000\001\004\000\000\000\000\000\000\000\000@\000\000\001\000\004\129\016#a\000E\130\141\241#\208\004\015\128\000\001\142\000\018\016\004D\b\012\018y\000\000\024\000\000\024\192\001!\000D\000\128\193'\144\000\001\128\000\001\140\000\018\016\004@\b\012\0189\000\000\024\000\000\024\192\196\148\187\131\232>\022\028\015\251`w\219~p\240\018\016\004@\b\012\0189\000\000\024\000\000\024\192\197\189\187\215\248\190\215?\191\251a\247\219\127\253\240\000\000\000\000\000\b\000(\000\000\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\0026\016\004X(\223\018=\000@\248\000\000\024\224\197\189\187\215\248\190\215?\191\251a\247\219\127\252\240\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\016\004@\b\012\0189\000\000\024\000\000\024\192\197\189\187\215\248\190\215?\191\251a\247\219\127\253\240\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\012\000(\000\000\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\b\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\148\187\131\232>\022\028\015\249`w\139~p\2426\016\004X(\223\018=\000@\248\000\000\024\224\197\189\187\215\248\190\215?\191\251a\247\219\127\252\252IK\184>\131\225a\192\255\182\007}\183\231\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000B6\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012[\219\189\127\139\237s\251\255\182\031}\183\255\207\196\148\187\131\232>\022\028\015\251`w\219~p\2426\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\014\127[\188~\171\255s\253\255\214\255x\183\255\239}\246D\b/\227P\000L\028\030\227\139\002\131B6\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015\003!\000@\128\004\193&\208\001\001\128\000\001\004\0002\016\004\b\000L\018-\000\016\024\000\000\016@\003)\000P\144\004\193&\176\001\001\144\000m\021\b:\024\132~\002\206R->2\027\004\001\146\203\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\003)\000P\144\004\193\"\176\001\001\144\000%\004\0002\016\004\b\000L\018)\000\016\024\000\000\016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b0\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\001\144\000\000\000\000@\000\000\001\000\000\000\000\131\000\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\025\000\000\000\000\004\000\000\000\016\000 \000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\128\000\025\000\000\000\000\004\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003)\000P\144\004\193\"\176\001\001\144\000%\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\128\000\000\000\000\001\000\000\016\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000\000\004\000\000\000\000\000L\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b0\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\128\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\131\128\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\001\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\001\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000L\017\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\001\000\004\129\016#a\000E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\131!\000@\128\004\193\"\208\001\001\160\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000H\017\b2\016\004\b\000L\018-\000\016\026\000\000\016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\001\000\004\129\016\131!\000@\128\004\193\"\208\001\001\160\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000H\017\b\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000H\017\0002\016\004\b\000L\018-\000\016\026\000\000\016@\000\000\000\000\000\000\000\004\000\000\000\016\000H\017\bH\002(\000\130\001!\128\001\144\006`\000 \004\132\128\"\128\b\"\018\024\012\025\000f\001\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\148\187\131\232>\022\028\015\249`w\139~p\2426\016\004X(\223\018=\000@\248\000\000\024\224\128\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\128\000\129\003\224\012\004\004\003\224 \016\000X 0\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\000\000\000\000\000\000\000\000\000\128\002\128\000\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\128\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\t\176>\000\192@@>\002\001\000\005\134\003\163a\011E\130\141\241#\208\004\015\128\000\001\206\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\b\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\b\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\016\004@\b\012\0189\000\000\024\000\000\024\192\197\189\187\215\248\190\215?\191\251a\247\219\127\253\240\000\000\000\000\000\b\000(\000\000\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\b\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012[\219\189\127\139\237\243\251\255\182\031}\183\255\207#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\b\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012[\219\189\127\139\237\243\251\255\182\031}\183\255\207#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\197\189\187\215\248\190\223?\191\251a\247\219\127\252\2426\016\004X(\223\018=\000@\248\000\000\024\224\196\148\187\131\232>\022\028\015\249`w\139~p\248\000\t\016>\000\192@@>\002\001\000\005\130\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\012\000(\000\000\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\b\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\197\189\187\215\248\190\223?\191\251a\247\219\127\252\2426\016\004X(\223\018=\000@\248\000\000\024\224\196\148\187\131\232>\022\028\015\249`w\139~p\2426\016\004X(\223\018=\000@\248\000\000\024\224\128\000\002\000\000\000\000\000\000\000\000\000\000\000\000\012[\219\189\127\139\237\243\251\255\182\031}\183\255\207#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\b\000\b\016>\000\192@@>\002\001\000\005\130\003\197\189\187\215\248\190\223?\191\251a\247\219\127\252\2426\016\004X(\223\018=\000@\248\000\000\024\224\196\148\187\131\232>\022\028\015\249`w\139~p\240\000\000\000\000\000\000\000\000\000\000\000\005\000\000\000\000\000\000\000\000\000\128\002\128\000\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\128\000\b\000\000\000\000\000\000\000\000\000\000\000\000\012[\219\189\127\139\237\243\251\255\182\031}\183\255\207#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015#a\000E\130\141\241#\208\004\015\128\000\001\142\b\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\197\189\187\215\248\190\223?\191\251a\247\219\127\252\2426\016\004X(\223\018=\000@\248\000\000\024\224\196\148\187\131\232>\022\028\015\249`w\139~p\2426\016\004X(\223\018=\000@\248\000\000\024\224\128\000\001\000\000\000\000\000\000\000\000\000\000\000\000\012[\219\189\127\139\237\243\251\255\182\031}\183\255\207#a\000E\130\141\241#\208\004\015\128\000\001\142\012IK\184>\131\225a\192\255\150\007x\183\231\015\197\189\187\215\248\190\223?\191\251a\247\219\127\252\2426\016\004X(\223\018=\000@\248\000\000\024\224\196\148\187\131\232>\022\028\015\249`w\139~p\252[\219\189\127\139\237s\251\255\182\031}\183\255\223\197\189\187\215\248\190\215?\191\249a\247\139\127\252\240\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\b\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b:\024\132~\002\206R->2\027\004\001\146\203\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\003)\000P\144\020\193\"\176\001\001\128\000\005\004\0000\000\006\000\000\012\\ \000\016\000\000\000\000\000\001\000\000\000\000\016@\000\000\001\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\144\005\t\001L\018+\000\016\024\000\000P@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\144\005\t\001L\018+\000\016\024\000\000P@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\016\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\148\187\131\232>\022\028\015\249`w\139~p\2402\016\004\b\000L\018-\000\016\026\000\000\016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\196\148\187\131\232>\022\028\015\249`w\139~p\2426\016\004X(\223\018=\000@\248\000\000\024\224\196\148\187\131\232>\022\028\015\249`w\139~p\240\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000H\017\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\b#a\000E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003!\000@\128\004\193\"\208\001\001\128\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\018\016\132@\b\012\0189\000\000\024\000\000\024\192\128\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\028\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000#a\002E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\016\004@\b\012\0189\000\000\024\000\000\024\192@\000\000\000\000\000\000\000\000\003\000\000P\000\000\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\001\016\000\000\000\000\000\000\000\001\000\002@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\001\016\000\000\000\000\000\000\000\001\000\000\000\000\128\000\017\000\000\000\000\000\000\000\000\000\000\000\000\b\016\000\016\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\0000\000\005\000\000\000\001\000\000\000\000\000\192#\128\000\000\000\000\000\000\012\000\001\016\000\000\000\000\000\0000\001\005\002@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012IK\184>\131\225a\192\255\182\007}\183\231\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\t\016>\000\192@@>\006\001\000\005\130\003\128\000\016\000\000\000\000\000\000\000@\000\000\000\000\b\000\000\000\000\000\004\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016 \004\000\000\b\016@\000\001\000\000\000\000\000\001\002\000@\000\000\129\000\000\000\016\000\000\000\000\000\000\000\000\000\000\b\000@\000\128\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000\000@\000\000\004\000\000\000\000\000\000\000\0000\000\000\000\000\000\000@\000\000\000\000\000\000\000\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\001\000\000@\000\001\002\000@\000\000\129\000\000\000\016\000\000\000\000\bH\002(\000\130\t!\192\001\144\006`\000 \004\001\000@@\000 \193\000\000\000\016\000\000\000\000\004\000\000\000\000\001\000\000@\000\000\001\000\000\000\000\001\002\000@\000\000\129\000\000\000\016\000\000\000\000\bH\002(\000\130\t!\192\001\144\006`\000 \004\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\001\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\000\000\004\000\b\000`\000\000\b\000\000\000\000\001 \000\000\000\000\128\006\000\000\000\128\000\000\000\000\018\000\000\000\000\b\000 \000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\128\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000@\000\128\000\000\000@\000\003\000\000`\000\000\197\194\128\001\000\000\000\000\000\000\000\000\000\000\004\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\016\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\017\000\000\000\000\004\000\000 \000\000\000\001\000\000\001\016\000\000\000\000@\000\000\000\000\000\000\000\000\000\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\004\004\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\016\000\000\000\000@\000\002\000\000\000\000\016\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000@@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000`\000\000\197\194\000\001\000\000\000\000\000\bX\n(\000\131\005!\192\001\144\006`\016!\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bX\n(\000\130\005!\192\001\144\006`\016!\004\003\000\000`\000\000\197\194\128\001\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\003\000\000`\000\000\197\194\000\001\000\000\000\000\000\bX\002(\000\130\005!\192\001\144\006`\016!\004\133\128\162\128\b0R\028\000\025\000f\001\002\016@\000\000\000\000\000\000\000@\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003!\004@\128\004\193&\208\001\001\128\000\001\004\0002\016D\b\000L\018-\000\016\024\000\000\016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\016\004\b\000L\018-\000\016\024\000\000\016@\132\128\"\128\b \018\024\000\025\000f\000\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012IK\184>\131\225a\192\255\150\007x\183\231\015@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\016\004\b\000L\018-\000\016\026\000\000\017@\196\148\187\131\232>\022\028\015\249`w\139~p\248\000\b\128>\000\192@@>\002\001\000\007\194\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\129\000@@\000 \193\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\b\000\000\016\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\129\000@@\000 \193\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\b\000\000\016\000\004\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000@@\000 \193\000\000\000\016\000\000\000\000\004\000\000\128\000\001\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\t!\192\001\016\006`\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016 \004\000\000\b\016@\000\001\000\000\000\000\000\001\002\000@\000\000\129\000\000\000\016\000\000\000\000\bH\002(\000\130\t!\192\001\016\006`\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0008\000@\004\000\000\000@\000\000\000\000\000\000\000\001\000\000\000@\000@\004\000\000\000\000\000\000\000\000\016\000\000\000\000\004\000@\000\000\000\000\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\bH\002(\000\130\001!\128\001\016\007`\000 \000\001\000@@\000 \193\000\000\000\016\000\000\000\000\012H\002(\000\131\001!\192\001\016\006`\000 \000\132\128\"\128\b \018\024\000\017\000f\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\004\000\000\000\000\004\000\000\000\000\000\000\000\0000\000@\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\001\000\000@\000\132\128\"\128\b \018\024\000\017\000f\000\002\000HH\002(\000\130\001!\000\001\016\006`\000 \004\003\000\000\000\000\000\000\004\000\000\000\000\000\000\000\0000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\016\000\004\000\bH\002(\000\130\001!\128\001\016\006`\000 \004\132\128\"\128\b \018\016\000\017\000f\000\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\001\000\000@\000\132\128\"\128\b \018\024\000\017\000f\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000}\246D\b/\227P\000L\028\030\227\139\002\131B~\018-X\170\2233=\001@\254\000\000x\224\003!\000@\128\004\193\"\208\001\001\160\000\001\004\001\000\000 \000\000\000\000@\000\000\000\000\004\129\016#a\000E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000}\246D\b/\227P\000L\028\030\227\139\002\131B~\018-X\170\2233=\001@\254\000\000x\224\001\002\000@@\000\129\004\000\000\016\000\000\000\000\000\016 \004\000\000\b\016@\000\001\000\000\000\000\000\001\002\000@\000\000\129\000\000\000\016\000\000\000\000\bH\002(\000\130\t!\192\001\016\006`\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\012\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\192\004\000\000\000\000\000\000\000\000\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\132\129\"\128\b \018\024\000\017\000f\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \018\024\000\017\000f\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001 \000\000@\000\128\006\000\000\000\128\000\000\000\000\018\000\000\000\000\b\000`\000\000\b\000\000\000\000\001 \000\000\000\000\128\002\000\000\000\128\000\000\000\bH\002(\000\194\001!\192\001\016\007`\000`\000\001 \000\000\000\000\128\002\000\000\000\128\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\128\000\132\128\"\128\b \018\028\000\017\000f\016\002\016\000\016\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\bH\002(\000\130\001!\192\001\016\006`\000 \000\132\128\"\128\b \018\024\000\017\000f\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \018\028\000\017\000f\000\002\000\bH\002(\000\130\001!\128\001\016\006`\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000x\002/\001\130\012} \001\016\006\000\000 \000\132\128\"\128\b \002\016\000\016\000f\000\002\000\000\016\000\000\004\000\000\000@\000\000\000\000\000\000\128\001\000\000\000@\000\000\004\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000@\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\b!\128\001\000\006a\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000@\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\b!\128\001\000\006a\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0008\000@\004\000\000\000@\000\000\000\000\000\000\000\003\000\004\000\000\000\000\004\000\000\000\000\000\000\000\0000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\016\000\020\000\b\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\b!\128\001\000\006a\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\016\004\004\000\002\012\016\000\000\001\000\000\000\000\000\196\128\"\128\b0\002\028\000\016\000f\000\002\000HH\002(\000\130\000!\000\001\000\006`\000 \004\003\000\000\000\000\000\000\004\000\000\000\000\000\000\000\0000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\016\004\004\000\002\012\016\000\000\001\000\000\000\000\000\196\128\"\128\b0\002\028\000\016\000f\000\002\000HH\002(\000\130\000!\000\001\000\006`\000 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\016\000\004\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \002\024\000\016\000f\016\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000@@\000 \193\000\000\000\016\000\000\000\000\012H\002(\000\131\000!\192\001\000\006`\000 \000\132\128\"\128\b \002\024\000\016\000f\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000@@@ \193\004\000\000\016\000\000\000\000\000\016\004\004\000\002\012\016@\000\001\000\000\000\000\000\001\000@@\000 \193\000\000\000\016\000\000\000\000\012H\002(\000\131\000!\192\001\000\006`\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\000\000\004\000\b\000`\000\000\b\000\000\000\000\001 \000\000\000\000\128\006\000\000\000\128\000\000\000\000\018\000\000\000\000\b\000 \000\000\b\000\000\000\000\132\128\"\128\012 \002\028\000\016\000f\000\006\000\000\136\000\000\004\000\004\000`\000\000\000\000\000\000\000\b\000\000\000@\000@\006\000\000\000\000\000\000\000\000\128\000\000\000\000\004\000`\000\000\000\000\000\000\000\b\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\002\000\000\000\000\000\000\000\000 \000\002H\000@\000\000\b\000\000\000\000\000\128\000\000\002\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\001\000\000@\002\000Q\002\000\000\000\000\000\000\000\b@\000\b\000\000(!@@\000\000 \016\000\000\132\000\000\128\000\002\130\016\004\000\000\002\001\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\b\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\128\000\002\002\016\004\000\000\002\001\000\000\000\128\000\000\000\004\004\000@\000\000\000\000\000\000\000\b\000\000\000\000@@\000\000\000\000\000\000\000\000\000\000\000\000\000\004\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\132\000\000\128\000\002\002\028\004\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\b\000\000@\004\000\000\000\000\000\000\000\000\128\000\000\128\000\004\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\001\000\000\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\b@\000\b\000\000 !\192\192\000\001 \016\000\000\132\000\000\128\000\002\002\024\004\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\128\000\002\002\028\012\000\000\018\001\000\000\000\016\000\004\000 \005\016`\000\000\000\000\000\000\000\001\000\000@\002\000Q\002\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\004\000\000\000\000\000\000\b\000\016\000\000\000\000\000\000@\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\001\000\000\000\001\000\000@\002\000Q\002\000\000\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000@\000\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\002\000\000\000\000\004\000\000\000\000\000@\000\000\000\000 \000\000\000\000@\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128*\128\b\"\018\028\004\017\000v\001\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\001\000\000\000\001\000\000@\002\000Q\002\000\000\000\000\000\000\000\bH\002\168\000\130!!\192A\016\007`\016 \004\132\000\000\128\000\002\002\028\004\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000p\016\000\197\198\000\001\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\132\000\000\128\000\002\002\028\012\000\000\002\001\000\000\b@\000\b\000\000 !\128@\000\000 \016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\128\000\002\002\024\004\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b@\000\b\000\000 !\000@\000\000 \016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\001!\192\001\016\006`\000 \004\132\128\"\128\b \018\016\000\017\000f\000\002\000@\128\000\000\000\000\004\000`\000\000\000\000\000\000\000\b\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\001\000\000@\002\000Q\002\000\000\000\000\000\000\000\bH\002(\000\130\001!\192\001\016\006`\000 \004\132\128\"\128\b \018\016\000\017\000f\000\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\004\000`\000\000\000\000\000\000\000\b\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\003\000\000p\018\000\213\194\000\001\000\000\000\000\000\bX\n\168\000\131\004!\192\001\016\007`\000`\004\003\000\000`\000\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\003\000\000p\018\000\213\194\000\001\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\001@\000\000\002\000\000\000\000\004\000\000\000\000\000@\016\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\003\000\000p\018\000\213\194\000\001\000\000\000\000\000\0000\000\006\000\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\0000\000\007\001 \r\\ \000\016\000\000\000\000\000\133\128\170\128\b0B\028\000\017\000v\000\002\000HX\n\168\000\131\004!\192\001\016\007`\000 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002\168\000\130\000!\192\001\000\007`\000 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \002\024\000\016\000f\000\002\000HH\002(\000\130\000!\000\001\000\006`\000 \004\b\000\000\000\000\000@\006\000\000\000\000\000\000\000\000\128\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\0000\000\007\001 \r\\ \000\016\000\000\000\000\000\132\128\"\128\b \002\024\000\016\000f\000\002\000HH\002(\000\130\000!\000\001\000\006`\000 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\000!\000\001\000\006`\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \002\024\000\016\000f\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \002\016\000\016\000f\000\002\000@ \000\002H\000L\000@\b\000\000\000\000\000\128\002\000\000$\128\004\192\000\000\128\000\000\000\000\b\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\132\128\"\128\b \018\024\000\017\000v\001\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \018\024\000\017\000f\001\002\000HH\002(\000\130\001!\000\001\016\006`\000 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \002\016\000\016\000f\000\002\000@ \000\002H\000L\000@\b\000\000\000\000\000\128\002\000\000$\128\004\192\000\000\128\000\000\000\000\b\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\0002\000\007\129\000\012\\(\000\016\b\002\000\001\000\003\000\002p\016\000\197\194\000\001\000\000\000\000\020\000\000\000\000\000\004\004\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bZ\002(\000\130\t!\160\001\016\014`\016 \004\132\128\"\128\012 \018\028\000\017\000f\001\006\016HH\002(\000\130\001!\192\001\016\006`\016!\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\001!\128\001\016\006`\016!\004\001 \000\000\000\000\128\002\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\000!\128\001\000\006`\016 \004\132\128\"\128\b \002\016\000\016\000f\000\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \018\028\000\017\000v\001\002\000@\018\000\000\128\000\b\000(\000\000\b\002\000\001\000\001 \000\000\000\000\128\002\128\000\000\128 \000\016\000\000\000\000\000\004\004\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\012 \018\028\000\017\000f\001\006\016HH\002(\000\130\001!\192\001\016\006`\016!\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\004\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000@\000\000\000\000\000\000\000\b\128\000\000@\000@\006\000\000\000\000\000\000\000\000\128\000\000\000\000\004\000`\000\000\000\000\000\000\000\b\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\0002\144\005\t\000L\018+\000\016\025\000\000P@\001\000\000@\002\000\209\002\000\000\004\000\000\000\000\b@\000\b\000\000(!@\192\000\000 \016\000\000\132\000\000\128\000\002\130\016\012\000\000\002\001\000\000\b@\000\b\000\000 !\000\192\000\000 \016\000\000\b\000\000\000\000@@\004\000\000\000\000\000\000\b\000\000\000\000\000\004\004\000@\000\000\000\000\000\000\000\000\000\000\000\000@@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000$\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\128\000\002\002\024\012\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000@@\000\000\000\000\000\000\000\000\000\000\000\000\000\004\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\132\000\000\128\000\002\002\028\012\000\000\002\001\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000$\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\b\000\000@\004\000\000\000\000\000\000\b\000\000\000\000\128\000\004\000@\000\000\000\000\000\000\000\000\000\000\b\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\0002\144\005\t\000L\018+\000\016\025\000\000P@\003\128\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b@\000\b\000\000 !\128\192\000\000 \016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\128\000\004\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\0002\144\005\t\000L\018+\000\016\025\000\000P@\003\128\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0026\016\004X(\223\018}\000@\248\000\000\024\224#a\000E\130\141\241#\208\004\015\128\000\001\142\b@\000\b\000\000 !\128\192\000\000 \016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\004\000 \r\016`\000\000@\000\000\000\128\001\000\000@\002\000\209\006\000\000\004\000\000\000\000\000\016\000\004\000 \r\016 \000\000@\000\000\000\000\001\000\000@\002\000\209\002\000\000\004\000\000\000\000\0002\016D\012\128L\018m\000\016\024\000\000\016@}\246D\b/\227P\000L\028\030\227\139\002\131@2\016D\b\000L\018m\000\016\024\000\000\016@\003!\004@\128\004\193\"\208\001\001\128\000\001\004\0002\016\004\b\000L\018-\000\016\024\000\000\016@\000\000\000\000\000\000\000\b\000\b\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\004\000\000\000\000\000\000\b\000\016\000\000\000\000\000\000@\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\001\000\000\000\001\000\000@\002\000\209\002\000\000\004\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000@\000\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\144\005\t\000L\018k\000\016\024\000\000\016@\003)\000P\144\004\193\"\176\001\001\128\000\001\004\0002\144\005\t\001L\018+\000\016\024\000\000\016@\001\000\000@\002\000\209\002\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\004\001\000\000@\002\000\209\002\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\133\169*\212\024\162\211?\188\017\001\230\001\007\141HZ\146\173A\138-3\251\193\016\030`\016x\212\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002\168\000\130!!\192\193\016\006`\016`\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128*\128\b\"\018\028\012\017\000f\001\006\001@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002\168\000\130!!\192\193\016\006`\016`\020\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\001\000\000\000\001\000\000@\002\000\209\002\000\000\004\000\000\000\000\bH\002\168\000\130!!\192\193\016\006`\016`\020\003!\004@\128\004\193\"\208\001\001\128\000\001\004\0002\016\004\b\000L\018-\000\016\024\000\000\016@\000\000\000\000\000\000\000\b\000\b\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000\000\004\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\007\001 \r\\ \000\016\000\000\000\000\000\128\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b@\000\b\000\000 !\192\192\000\000 \016\000\016\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\128\000\002\002\024\012\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000@\002\000\209\002\000\000\004\000\000\000\000\b@\000\b\000\000 !\192\192\000\000 \016\000\016\132\000\000\128\000\002\002\024\012\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000p\016\000\197\198\000\001\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\132\000\000\128\000\002\002\024\012\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b@\000\b\000\000 !\128\192\000\000 \016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\128\000\002\002\016\012\000\000\002\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \018\028\000\017\000f\000\002\000@0\000\007\001 \r\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\016\000\004\000 \r\016 \000\000@\000\000\000\000\132\128\"\128\b \018\028\000\017\000f\000\002\000@2\144\005\t\000L\018+\000\016\025\000\000P@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\001!\128\001\016\006`\000 \004\132\128\"\128\b \018\016\000\017\000f\000\002\000@\128\000\000\000\000\004\000`\000\000\000\000\000\000\000\b\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\0002\144\005\t\000L\018+\000\016\025\000\000P@\132\128\"\128\b \018\024\000\017\000f\000\002\000HH\002(\000\130\001!\000\001\016\006`\000 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\001!\000\001\000\006`\000 \000\003!\004@\192\004\193&\208\001\001\128\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\001!\000\001\016\006`\000 \004\132\128\"\128\b \018\024\000\017\000f\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \018\016\000\017\000f\000\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\001!\128\001\000\006`\000 \000\132\128\"\128\b \018\016\000\016\000f\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\001!\000\001\144\006`\000 \004\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \018\024\000\016\000f\000\002\000\bH\002(\000\130\001!\000\001\000\006`\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012H\002\168\000\131\t!\192\001\016\007`\002 \004\192\000\b\000\000\016\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000@\000\000\000\000\004\193\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\b\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\128\000\002\002\016\012\000\000\002\001\000\000\b\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\016 \004\004\000\b\016@\000\001\000\000\000\000\000\001\002\000@\000\000\129\004\000\000\016\000\000\000\000\000\016 \004\000\000\b\016\000\000\001\000\000\000\000\000\000\000\b\000\000\000\128\004\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\129\000@@\000 \193\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\b\000\000\016\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000\000\000\000\000\000\000\000$\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\131!\000@\128\004\193\"\208\001\001\160\000\001\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\148\187\131\232>\022\028\015\249`w\139~p\240\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\018\000\000\128\000\b\000 \000\000\b\000\000\001\000\001 \000\000\000\000\128\002\000\000\000\128\000\000\016\000\018\000\000\000\000\b\000 \000\000\b\000\000\000\000\132\128\"\128\012 \018\028\000\017\000v\000\006\016\000\018\000\000\000\000\b\000 \000\000\b\000\000\000\000\132\128\"\128\b \018\028\000\017\000f\000\002\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \018\024\000\017\000f\000\002\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\012 \018\028\000\017\000v\000\006\016\000\018\000\000\000\000\b\000 \000\000\b\000\000\000\000\132\128\"\128\b \018\028\000\017\000f\000\002\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\bH\002( \130\001!\128\001\016\007`\016 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\001!\128\001\016\006`\016 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\001 \000\b\000\000\128\002\000\000\000\128\000\000\016\000\018\000\000\000\000\b\000 \000\000\b\000\000\001\000\132\128\"\128\b \018\024\000\017\000f\000\002\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\004\000\000 \000\000\000\000\000\000\001\000\000\000\000\000\000\000\002\000\000\000\000\000\003\000\000`\000\000\197\198\000\001 \000 \000\000\0000\000\006\000\000\012\\ \000\018\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\016\000\000\000@\000\000\001 \000\000\000\000\0000\000\006\000\000\012\\ \000\018\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\004\000\000\001\000\000\000\000\000@\000\000\001\000\000\000\000\000\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\128\000\000\000\000@\000\000\000\000\004\000\000\000\000\b\000\000\000\000\004\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\128\000\000\000\000@\000\000\000\000\004\000\000\000\000\000\000\000@@\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \018\028\000\017\000f\001\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\000\007\129\000\012\\(\000\016\b\002\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\000!\128\001\000\006`\016 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\001 \000\b\000\000\128\002\000\000\000\128\000\000\016\000\018\000\000\000\000\b\000 \000\000\b\000\000\001\000\132\128\"\128\b \002\024\000\016\000f\000\002\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000\132\128\"\130\b \002\024\000\016\000v\001\018\000@2\000\007\129\000\012\\(\000\016\b\002\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\000!\128\001\000\006`\016 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\001 \000\b\000\000\128\002\000\000\000\128\000\000\016\000\018\000\000\000\000\b\000 \000\000\b\000\000\001\000\132\128\"\128\b \002\024\000\016\000f\000\002\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\128\000\001\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\001!\192\001\016\006`\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000H\002\b\000\130\000!\000\001\000\006@\000 \000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\000\000\000\000\012\000 \000\000\b\000\000\000\000\128\000\136\007\224,$\000\003\226 \016@\024(\176\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\001\000\000\000\001\000\000\000\000\000\192\000\000\000\000\000\000\000\000\b\000\b\000~\002\194@\000>\"\001\004\001\130\139\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\000\000\000\000\b\000 \000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\016\004\b\000L\018-\000\016\026\000\000\016@\000\000\000\000\000\000\000\004\000\000\000\004\000H\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\001\000\000\000\000\000\192\000\000\000\000\000\000\000\000\002~\018\012X\170\2233=\001P\254@\0008\224\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\000Z\018\b\000\130\r!\001\001\016\014@\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000H\002\b\000\130\001!\000\001\016\006A\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\128 \128\b \018\016\000\016\000`\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\b\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002~\018\012X\170\2233=\001P\254@\0008\224'\225 \197\138\173\2433\208\021\015\228\000\003\142\000H\002\b\000\130\001!\000\001\016\006@\000 \000\004\128 \128\b \018\016\000\017\000d\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000H\002\b\000\130\001!\128\001\016\006@\000 \000\004\128 \128\b \018\016\000\017\000d\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\128 \128\b \018\024\000\017\000d\000\002\000\000H\002\b\000\130\001!\000\001\016\006@\000 \000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000") + (125, "'\225 \197\138\173\2433\208\020\015\228\128\001\199\001\027\b\002.\020o\137>\128 |\000\000\0068\031}\145\002\011\248\212\000\019\007\007\184\209`Ph\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\191\173\155\214n\191\204\223\242T\127\138\"\015<\015\190\200\129\005\252j\000\t\131\131\220h\176(4\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\216@\017`\163|I\244\001\003\224\000\0001\192\251\236\136\016_\198\160\000\1528=\198\139\002\131B~\018-X\170\2233=\001@\254\b\000<p\000\000\000\000 \000`\002\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\024\000\000\000\000\000\000\000\000\000\128\000\128\007\224,$\000\003\226 \016 \b\020X\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000P\000\000\000\000\000\000\000\000\000\024\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\128\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000H\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\128\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\024\000\003\128\128\006.\016\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\128\0008\b\016b\225\000\000\128\000\000\000\000\000\004\001\001\001\000\131\004\016\000\000@\000\000\000\000\000 \b\b\000\004\024 \128\000\002\000\000\000\000\000\001\000@@\000 \193\000\000\000\016\000\000\000\000\006$\001T\000A\132\144\224\000\136\003\180@\136\001! \b \002\b\000\133\000\004\000\024\160\000@\001\t\000A\000\016@\004 \000 \000\197\000\002\000\0000\000\002L\016L\000@\b\000\000\000\000\000@\001\128\000\018@\130`\002\000@\000\000\000\000\002\000\012\000\000\146\004\019\000\000\002\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000 \000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\192\000\t \0010\000\000 \000\000\000\000\001\000\004\000\000@\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\018@\002\000\000\000@\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\004\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\t \001\000\000\000 \000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000B@\017A\004\016\001\012\000\b\000;@D\128\016\012\128\001\224@\003\023\n\000\004\002\000@\000 \016\144\004P\001\132\018C\128\002 \012\209\016a\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\025\000\003\128\128\006.\020\000\b\004\000\128\000@\000\192\002\028\004\b1p\128\000@\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012X\011\184\000\131%!\192\193\018\007h\0110\139\001\128\0000\000\000b\225\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`\000\012\000\000\024\184@\000$\000\002\000\000\000\001\000\016\000\000\000@\000\000\001 \000\000\002\000\000\024\000\003\128\128\006.\016\000\b\000\000\000\000\000\000@\000\000\000\000\016\000\000\000\000\000\000\000\000\001\n\001#@\000$\1328\024\002@$\017 \001\007\223d@\130\2545\000\004\193\193\2384X\020\026\019\240\145j\197V\249\153\232\n\007\240@\001\227\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000$\193\004\192\004\000\128\000\000\000\000\004\000\024\000\001$\b&\000 \004\000\000\000\000\000 \000\192\000\t A0\000\000 \000\000\000\000\001\000\006\000\000I\000\t\128\000\001\000\000\000\000\000\b\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000B@\017A\004\016\t\012\000\b\128;@@\128\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\144\004P\001\004\002C\000\002 \012\208\016 \004}\246D\b/\227P\000L\028\030\227E\129A\161?\t\022\172Uo\153\158\128\160\127\004\000\0308\b\216@\017p\163|I\244\001\003\224\000\0001\192F\194\000\139\005\027\226O\160\b\031\000\000\001\142\0026\016\004X(\223\018=\000@\248\000\000\012p\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\132\001\016\002\003\004\142@\000\006\000\000\003\024\000 \000\000\b\000\b\000\128\000\000\000\000\000\000\000\001\000\000\000\000\000@\004\000\000\000\000\000\000\000\000\b\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000+\250\221\255f\251\253\255\255'O\253\164 \243\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n6\024\132~*\223R=>b\249\002\000\205u\192\144\132\"\000@`\145\200\000\000\192\000\000c\000\141\132\001\022\n7\196\143@\016>\000\000\003\156\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004 \000\004\002\000\020\016\160`\000\000\016\004\000\000!\000\000 \000\000\160\133\003\000\000\000\128 \000\001\b\000\001\000\000\005\004 \024\000\000\004\001\000\000\0002\016\004\b\000L\018-\000\016\026\b\000\b \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b2\024\132~\002\206R->2\027\n\000\201e\192\000\004\000\000\000\000\000\b\000\000\128\000\000\000\002\012\000\000\001\000\000\000\016\000\000\000\000\000\000\000\000`\000\000\000\000\000\000\128\000\000\000\000\000\000\000\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128 \000\016`\128\000\000\b\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\001\002\000@\000\000\129\004\000\000\016\000\000\000\000\000\b\016\002\000\000\004\b\000\000\000\128\000\000\000\000)\248H1b\171|\205\244\005\003\248\160\000q\193O\194A\139\021[\230g\160(\031\197\000\003\142\n~\018,X\170\2233=\001@\254h\000\028p\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\b\001\001\000\002\004\016\000\000@\000\000\000\016\000 @\b\b\000\016 \128\000\002\000\000\000\000\000\001\002\000@\000\000\129\004\000\000\016\000\000\000\000\000\b\016\002\000\000\004\b\000\000\000\128\000\000\000\000\001@\128\016\000\000 @\000\000\004\000\000\000\000\000F\194\000\139\005\027\226O\160\b\031\000\000\001\142\0026\016\004X(\223\018=\000@\248\000\000\012p\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004l \b\184Q\190$\250\000\129\240\000\000\024\224#a\000E\130\141\241'\208\004\015\128\000\000\199\001\027\b\002,\020o\137\030\128 |\000\000\00681on\245\254/\183\207\239\254\216}\251o\255\158F\194\000\139\005\027\226G\160\b\031\000\000\001\142\0002\016\004\b\000L\018-\000\016\024\000\000\b \001\144\128 @\002`\145h\000\128\208@\000Q\000\012\132\t\002\000\019\004\139@\004\006\130\000\002\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\b\128\000\000\000\000\000\000\000\b\000\001\000\000\012\000\001\192@\003\023\b\000\004\000\000\000\000\000\000`\000\014\002\000\024\184@\000 \000\000\000\001@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\024\000\003\128\128\006.\016\000\b\000\000\000\000\016\000\192\000\156\004\0001p\128\000@\000\000\000\002\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000 \001\128\0008\b\000b\225\000\000\128\000\000\000\005\000\004\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\001\000\000\000\129\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000 \000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\000\000\224 \001\139\132\000\002\000\000\000\000\004\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\024\144\007p\001\006BC\129\130$\014\208\022!\022\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\006$\005\220\000A\144\144\224`\137\003\180\005\136E\128\192\000\024\000\0001p\128\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000b\192]\192\004\025)\014\006\b\144;@X\132X\004\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\024\000\003\000\000\006.\016\000\b\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\006\000\000\224 \001\139\132\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000b\192]\192\004\025)\014\006\b\144;@X\132X\012\000\001\128\000\003\023\b\000\004\000\000\000\000\000\024\176\023p\001\006JC\129\130$\014\208\022!\022\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\128\0008\b\000b\225\000\000\128\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\128\000\000\128\000\004\000\000\000\001\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\192\000\028\004\0001p\128\000@\000\000\000\000\000\000\000\004\000\000\000\000\b\000\000@\000\000\000\016 0\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\016\000\000\128\000\000\000\"@\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\b\000\000@\000\000\000\017 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\002\000\000\016\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\024\144\007p\001\006BC\129\130$\014\208\022!\020\000\000\002\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\006\000\000\224 \001\139\132\000\002\000\000\000\000\004\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000 \000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\004\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\002 \000\000\000\000\128\000\000\002\000\000\000\000\128\000\017\000\000\000\000\000\000\000\000\016\000\000\000\000\025\b\002\004\000&\t\022\128\b\r\004\000\004\016\000\200@\0160\0010I\164\000@`\000\000 \128\006B\000\129\000\t\130M \002\003\000\000\001\004\0002\016\004\b\000L\018)\000\016\024\000\000\b \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\147)\027P\144\020\193&\176\001\001\148\0166\170\128\000\b\000\004\000 \000\000\128\000\b\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000I\148\141\168H\n`\147x\000\128\218D\027U@\004\000\000\000\000\002\000\138\000\000\000\000\000\000\000\016d!\b\016\000\152$Z\000 4\016\000\144@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\200@\0160\0010I\180\000@h \000 \128\006B\000\129\000\t\130M\160\002\003A\000\001\004\0002\016\004\b\000L\018-\000\016\026\b\000\b \001\144\128 @\002`\145H\000\128\192\000\000A\000\012\132\001\002\000\019\004\138@\004\006\000\000\002\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000H\000\r\128\000\b\000\002\000\000\000\n\000\019\020@\012\132\001\002\000\019\004\139@\004\006\130\000\002\b\018\000\003`\000\002\000\000\128\000\000\002\128\004\197\016\131!\000@\128\004\193\"\208\001\001\160\128\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000\006\192\000\004\000\001\000\000\000\005\000\t\138 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t2\017\180\b\001L\018m\000\016\027H\002j\168\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002L\132m\002\000S\004\155@\004\006\210\000\154\170\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\016\000\000\000\000\b\000\000\000\000\000H\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\012\132\001\002\000\019\004\139@\004\006\130\000\002\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\144\000\027\000\000\016\000\004\000\000\000\020\000&(\132\025\b\002\004\000&\t\022\128\b\r\004\000\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001 \0006\000\000 \000\b\000\000\000(\000LQ\b\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000d H\016\000\152$Z\000 4\016\000\016@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\001 \000\000\000\000@\000\000\000\000\002B\136A\144\129 @\002`\145h\000\128\208@\000Q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\017\000\000\000\000\004\000\000\000\000\000$\b\132\000\000\136\000\000\000\000\000\000\000\000\000\000\000\000 \192\000@\000\000\016\000\000\000\000\000\000\000\000\001\000\000\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006R\000\161 \t\130M`\002\003 \000M\021\000\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000@\000\b\000\000`\000\014\002\000\024\184@\000 \000\000\000\000\000\000\000\b\000\000\000\000\004\000\000\000\016\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000@\000\000\000\004l \b\176Q\190$z\000\129\240\000\000\024\224\003!\004@\200$\193&\208\001\001\160\000\000\130\000\b\016\002\002\000\004\b \000\000\128\000\000\000 \000@\128\016\016\000 A\000\000\004\000\000\000\000\000\002\004\000\128\000\001\002\b\000\000 \000\000\000\000\000\016 \004\000\000\b\016\000\000\001\000\000\000\000\000\000\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000`\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000@\016\016\000\b0@\000\000\004\000\000\000\000\000\002\000\128\128\000A\130\000\000\000 \000\000\000\000\000\000\000\000\000\000\b\000@\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000B\000\000\000\000\000\000\000\000\000\000 \b\b\000\004\024 \000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006$\001T\000A\128\144\224\000\136\003\180\000\136\001\000 \000\000\000\b\000\000\000\000\000\000\000\000\000\000\006\000\000I\000\t\128\000\001\000\000\000\000\000\b\000\016\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\004\000\000\012\000\001\224@\003\023\b\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\006$\001T\000A\128\144\224\000\136\003\180\000\136\005\000\192\000\028\004\0001p\128\000@\000\000\000\000\001\137\000U\000\016`$8\000\"\000\237\001\"\001LH\002\168\000\131\001!\192\001\016\007h\t\016\002\001\128\0008\b\000b\225\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000@\000\000\000\000`\000\014\002\000\024\184@\000 \000\000\000\000\000\196\128*\128\b0\018\028\000\017\000v\128\145\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \016\016\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000b@\021@\004\024I\014\000\b\128;D\b\128\016\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\128*\128\b0\146\028\000\017\000v\136\017\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001 \n\160\002\012\004\135\000\004@\029\160\004@\b\001\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128 \000\016`\128\000\000\b\000\000\000\000\003\018\000\170\000 \192Hp\000D\001\218\000D\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\b\000\000\000\b\000\000\000\000\002\000\000\000\000\000\000\000\000\0001 \n\160\002\012$\135\000\004@\029\162\004@\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\000\000@\000\000\128\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\128\000\001\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000B\000\000\000\000\000\000\000\000\000\000 @\b\000\000\016 \000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006$\001T\000A\132\144\224\000\200\003\180\000\152\001\001@\130\016\000\000 @\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\128\000\000\b\000@\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \b\b\000\004\024 \000\000\002\000\000\000\000\000\192\000\b\000\000\016\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000b@\021@\004\024I\014\000\012\128;D\t\128\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\128\001\000\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\000\199\001\027\b\018,\020o\137\030\128 |\000\000\0068\000\000\000\000\000\000\016\000\000\000\016\000\000\000\000\001\000\000 \000\000\000\000\000\000\000\128 \000\000\000\0026\016\004X(\223\018=\000@\248\000\000\012p\000\144\128\"\000@`\145\200\000\000\192\000\000c\003\000\000D\000\000\000\000\000\000\012\000@\160H\000\004l \b\184Q\190$\250\000\129\240@\000\024\224#a\000E\130\141\241'\208\004\015\130\000\000\199\001\027\b\002,\020o\137\030\128 |\016\000\0068\000H@\017\016 0I\228\000\000`\000\0001\128\002B\000\136\001\001\130O \000\003\000\000\001\140\000\018\016\004@\b\012\0189\000\000\024\000\000\012`\000\144\128\"\000@`\145\200\000\000\192\000\000c\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001on\245\254/\181\207\239\254\216}\251o\255\190\002\000\000\000\000\001\128G\000\000\000\000\000\000\000\n6\024\132~*\223R=>b\249\002\000\205u\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\141\132!\022\n7\196\143@\016>\000\000\003\028\020l!\b\176Q\190$z\000\129\240\000\000\024\224\129\002\000@@\000\129\004\000\000\016\000\000\000\000\000\b\016\002\000\000\004\b \000\000\128\000\000\000\000\000@\128\016\000\000 @\000\000\004\000\000\000\000\000\000\000\000\000\000\001\000\b\000\000\000\000\000\004\000\b\016\004\004\000\002\012\016\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000 \000\000@\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\163a\bE\130\141\241#\208\004\015\128\000\000\199\005\027\bB,\020o\137\030\128 |\000\000\0068 \200B\016 \0010H\180\000@`\000\000 \128\000\000\000\000\000\000\000\b\000\000\000 \000L\017\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\b\000\000\000\000\141\132\001\022\n7\196\143@\016>\000\000\003\028\004l \b\184Q\190$\250\000\129\240\000\000\024\224#a\000E\130\141\241'\208\004\015\128\000\000\199\001\027\b\002,\020o\137\030\128 |\000\000\0068\000\200@\0160\0010I\180\000@h \000\"\128\006B\000\129\000\t\130M\160\002\003A\000\001\020\0002\016\004\b\000L\018-\000\016\026\b\000\b\160\001\144\128 @\002`\145h\000\128\208@\000A\000@\000\000\000\000@\000\016\000\000\000\000\000\144\"\004l \b\176Q\190$z\000\129\240\000\000\024\224\003)\000P\208\004\193&\176\001\001\128\000\000\130\000\025H\002\132\128&\t5\128\b\012\000\000\004\016\000\202@\020$\0010H\172\000@`\000\000 \128\004\000\000\000\000\001\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\144\128 @\002`\145h\000\128\208@\000A\000\000\000 \000\000\000\000\016\000\000\000@\000\152\"\000`\000\014\002\000\024\184@\000 \000\000\000\000\000\000\000\b\000\000\000\000\004\000\000\000\016\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\128\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\014\134!\031\128\179\148\139O\140\134\194\1282Y`\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000@\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\006R\000\161 )\130E`\002\003\000\000\005\004\0026\016\004X(\223\018=\000@\248\000\000\012p\001\144\128 `\002`\147h\000\128\208@\000A\000\012\132\001\002\000\019\004\155@\004\006\130\000\002\b\000d \b\016\000\152$Z\000 4\016\000\016@\000\000\000\000\000\000\000\004\000\000\000\016\000$\b\129\027\b\002,\020o\137\030\128 |\000\000\0068\000H@\017\016 0I\228\000\000`\000\0001\128\002B\000\136\001\001\130O \000\003\000\000\001\140\000\018\016\004@\b\012\0189\000\000\024\000\000\012`bJ]\193\244\031\011\014\007\253\176;\246\223\156<\004\132\001\016\002\003\004\142@\000\006\000\000\003\024\024\183\183z\255\023\218\231\247\255l>\253\183\255\223\000\000\000\000\000\000\128\002\128\000\000\000\000\000\000\001\027\b\002,\020o\137\030\128 |\000\000\0068\b\216@\017`\163|H\244\001\003\224\000\0001\193\139{w\175\241}\174\127\127\246\195\239\219\127\252\240\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001!\000D\000\128\193#\144\000\001\128\000\000\198\006-\237\222\191\197\246\185\253\255\219\015\191m\255\247\192\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\012\000(\000\000\000\000\000\000\000\017\176\128\"\193F\248\145\232\002\007\192\000\000c\130\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006$\165\220\031A\240\176\224\127\203\003\190-\249\195\200\216@\017`\163|H\244\001\003\224\000\0001\193\139{w\175\241}\174\127\127\246\195\239\219\127\252\252IK\184>\131\225a\192\255\182\007~\219\243\135\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\001\b\216@\017`\163|H\244\001\003\224\000\0001\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012IK\184>\131\225a\192\255\150\007|[\243\135\145\176\128\"\193F\248\145\232\002\007\192\000\000c\131\018R\238\015\160\248Xp?\229\129\223\022\252\225\228l \b\176Q\190$z\000\129\240\000\000\024\224\196\148\187\131\232>\022\028\015\249`w\197\1918x\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001on\245\254/\181\207\239\254\216}\251o\255\159\137)w\007\208|,8\031\246\192\239\219~p\2426\016\004X(\223\018=\000@\248\000\000\012p\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\159\214\239\031\170\255\220\255\127\245\191\223\022\255\253\239\190\200\129\005\252j\000\t\131\131\220h\176(4#a\000E\130\141\241#\208\004\015\128\000\000\199\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000F\194\000\139\005\027\226G\160\b\031\000\000\001\142\012IK\184>\131\225a\192\255\150\007|[\243\135\145\176\128\"\193F\248\145\232\002\007\192\000\000c\131\018R\238\015\160\248Xp?\229\129\223\022\252\225\228l \b\176Q\190$z\000\129\240\000\000\024\224\196\148\187\131\232>\022\028\015\249`w\197\1918y\027\b\002,\020o\137\030\128 |\000\000\00681%.\224\250\015\133\135\003\254X\029\241o\206\030F\194\000\139\005\027\226G\160\b\031\000\000\001\142\012IK\184>\131\225a\192\255\150\007|[\243\135\145\176\128\"\193F\248\145\232\002\007\192\000\000c\131\018R\238\015\160\248Xp?\229\129\223\022\252\225\228l \b\176Q\190$z\000\129\240\000\000\024\224\196\148\187\131\232>\022\028\015\249`w\197\1918y\027\b\002,\020o\137\030\128 |\000\000\00681%.\224\250\015\133\135\003\254X\029\241o\206\030F\194\000\139\005\027\226G\160\b\031\000\000\001\142\012IK\184>\131\225a\192\255\150\007|[\243\135\145\176\128\"\193F\248\145\232\002\007\192\000\000c\131\018R\238\015\160\248Xp?\229\129\223\022\252\225\228l \b\176Q\190$z\000\129\240\000\000\024\224\196\148\187\131\232>\022\028\015\249`w\197\1918y\027\b\002,\020o\137\030\128 |\000\000\00681%.\224\250\015\133\135\003\254X\029\241o\206\030F\194\000\139\005\027\226G\160\b\031\000\000\001\142\012IK\184>\131\225a\192\255\150\007|[\243\135\145\176\128\"\193F\248\145\232\002\007\192\000\000c\131\018R\238\015\160\248Xp?\229\129\223\022\252\225\228l \b\176Q\190$z\000\129\240\000\000\024\224\196\148\187\131\232>\022\028\015\249`w\197\1918y\027\b\002,\020o\137\030\128 |\000\000\00681%.\224\250\015\133\135\003\254X\029\241o\206\030F\194\000\139\005\027\226G\160\b\031\000\000\001\142\012IK\184>\131\225a\192\255\150\007|[\243\135\145\176\128\"\193F\248\145\232\002\007\192\000\000c\131\018R\238\015\160\248Xp?\229\129\223\022\252\225\228l \b\176Q\190$z\000\129\240\000\000\024\224\196\148\187\131\232>\022\028\015\249`w\197\1918y\027\b\002,\020o\137\030\128 |\000\000\00681%.\224\250\015\133\135\003\254X\029\241o\206\030\006B\000\129\000\t\130M\160\002\003\000\000\001\004\0002\016\004\b\000L\018-\000\016\024\000\000\b \001\148\128(H\002`\147X\000\128\200\000\027EB\014\134!\031\128\179\148\139O\140\134\194\1282Y`\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\025H\002\132\128&\t\021\128\b\012\128\000\148\016\000\200@\016 \0010H\164\000@`\000\000 \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\012p\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\012\000\001\192@\003\023\b\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\025\000\000\000\000\004\000\000\000\016\000\000\000\004\024\000\003\128\128\006.\016\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\0002\000\000\000\000\b\000\000\000 \000 \000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000@\000\012\128\000\000\000\002\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\004l \b\176Q\190$z\000\129\240\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006R\000\161 \t\130E`\002\003 \000%\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000 \000\000\000\000\000@\000\004\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000@\000\000\000\000 \000\000\000\000\0010D\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b0\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000 \000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\028\000\003\128\128\006.\016\000\b\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\b\000\000\000\000\141\132\001\022\n7\196\143@\016>\000\000\003\028\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\b\000\000\000\b\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\000\000\224 \001\139\132\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\001\000\000\000\000\017\176\128\"\193F\248\145\232\002\007\192\000\000c\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\000\199\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000 \000L\017\0000\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\b\000\000\000\000\141\132\001\022\n7\196\143@\016>\000\000\003\028\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000$\b\129\027\b\002,\020o\137\030\128 |\000\000\0068\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\006B\000\129\000\t\130E\160\002\003A\000\001\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\b\000\018\004B\012\132\001\002\000\019\004\139@\004\006\130\000\002\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000$\b\132\025\b\002\004\000&\t\022\128\b\r\004\000\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000 \000H\017\b\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\128\001 D\000\200@\016 \0010H\180\000@h \000 \128\000\000\000\000\000\000\000\b\000\000\000 \000H\017\bH\002(\000\130\001!\128\001\144\006h\000\016\002B@\017@\004\017\t\012\006\012\1283@@\128\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006$\165\220\031A\240\176\224\127\203\003\190-\249\195\200\216@\017`\163|H\244\001\003\224\000\0001\193\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\141\132\001\022\n7\196\143@\016>\000\000\003\028\016\000\016 |\001\128\128\128|\004\002\000\005\130\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\000\000\000\000\000\000\000\000\001\000\005\000\000\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\012p@\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\155\003\224\012\004\004\003\224 \016\000,0\029\027\bZ,\020o\137\030\128 |\000\000\0078\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000F\194\000\139\005\027\226G\160\b\031\000\000\001\142\b\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004l \b\176Q\190$z\000\129\240\000\000\024\224\128\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\016\004@\b\012\0189\000\000\024\000\000\012`b\222\221\235\252_k\159\223\253\176\251\246\223\255|\000\000\000\000\000\002\000\n\000\000\000\000\000\000\000\004l \b\176Q\190$z\000\129\240\000\000\024\224\128\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001on\245\254/\183\207\239\254\216}\251o\255\158F\194\000\139\005\027\226G\160\b\031\000\000\001\142\012IK\184>\131\225a\192\255\150\007|[\243\135\145\176\128\"\193F\248\145\232\002\007\192\000\000c\130\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\197\189\187\215\248\190\223?\191\251a\247\237\191\254y\027\b\002,\020o\137\030\128 |\000\000\00681%.\224\250\015\133\135\003\254X\029\241o\206\030F\194\000\139\005\027\226G\160\b\031\000\000\001\142\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000b\222\221\235\252_o\159\223\253\176\251\246\223\255<\141\132\001\022\n7\196\143@\016>\000\000\003\028\024\146\151p}\007\194\195\129\255,\014\248\183\231\015\128\000\145\003\224\012\004\004\003\224 \016\000,\016\024\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\0000\000\160\000\000\000\000\000\000\000F\194\000\139\005\027\226G\160\b\031\000\000\001\142\b\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000b\222\221\235\252_o\159\223\253\176\251\246\223\255<\141\132\001\022\n7\196\143@\016>\000\000\003\028\024\146\151p}\007\194\195\129\255,\014\248\183\231\015#a\000E\130\141\241#\208\004\015\128\000\000\199\004\000\000\016\000\000\000\000\000\000\000\000\000\000\000\0001on\245\254/\183\207\239\254\216}\251o\255\158F\194\000\139\005\027\226G\160\b\031\000\000\001\142\012IK\184>\131\225a\192\255\150\007|[\243\135\145\176\128\"\193F\248\145\232\002\007\192\000\000c\130\000\002\004\015\1280\016\016\015\128\128@\000\176@x\183\183z\255\023\219\231\247\255l>\253\183\255\207#a\000E\130\141\241#\208\004\015\128\000\000\199\006$\165\220\031A\240\176\224\127\203\003\190-\249\195\192\000\000\000\000\000\000\000\000\000\000\000\n\000\000\000\000\000\000\000\000\001\000\005\000\000\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\012p@\000\004\000\000\000\000\000\000\000\000\000\000\000\000\003\022\246\239_\226\251|\254\255\237\135\223\182\255\249\228l \b\176Q\190$z\000\129\240\000\000\024\224\196\148\187\131\232>\022\028\015\249`w\197\1918y\027\b\002,\020o\137\030\128 |\000\000\0068 \000\000\128\000\000\000\000\000\000\000\000\000\000\000\001\139{w\175\241}\190\127\127\246\195\239\219\127\252\2426\016\004X(\223\018=\000@\248\000\000\012pbJ]\193\244\031\011\014\007\252\176;\226\223\156<\141\132\001\022\n7\196\143@\016>\000\000\003\028\016\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\197\189\187\215\248\190\223?\191\251a\247\237\191\254y\027\b\002,\020o\137\030\128 |\000\000\00681%.\224\250\015\133\135\003\254X\029\241o\206\031\139{w\175\241}\190\127\127\246\195\239\219\127\252\2426\016\004X(\223\018=\000@\248\000\000\012pbJ]\193\244\031\011\014\007\252\176;\226\223\156?\022\246\239_\226\251\\\254\255\237\135\223\182\255\251\248\183\183z\255\023\218\231\247\255,>\248\183\255\207\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\176\128\"\193F\248\145\232\002\007\192\000\000c\130\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\000\199\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\141\132\001\022\n7\196\143@\016>\000\000\003\028\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000#a\000E\130\141\241#\208\004\015\128\000\000\199\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b:\024\132~\002\206R->2\027\n\000\201e\128\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000e \n\018\002\152$V\000 0\000\000P@\003\000\000`\000\000\197\194\000\001\000\000\000\000\000\000\b\000\000\000\000\130\000\000\000\b\000\000\000\000\000\b\216@\017`\163|H\244\001\003\224\000\0001\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002\144\005\t\001L\018+\000\016\024\000\000( \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003)\000P\144\020\193\"\176\001\001\128\000\002\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000F\194\000\139\005\027\226G\160\b\031\000\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\176\128\"\193F\248\145\232\002\007\192\004\000c\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006$\165\220\031A\240\176\224\127\203\003\190-\249\195\192\200@\016 \0010H\180\000@h \000 \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\141\132\001\022\n7\196\143@\016>\000\000\003\028\024\146\151p}\007\194\195\129\255,\014\248\183\231\015#a\000E\130\141\241#\208\004\015\128\000\000\199\006$\165\220\031A\240\176\224\127\203\003\190-\249\195\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000 \000H\017\0026\016\004X(\223\018=\000@\248\000\000\012p\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\001\004l \b\176Q\190$z\000\129\240\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\025\b\002\004\000&\t\022\128\b\012\000\000\004\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\018\016\132@\b\012\0189\000\000\024\000\000\012`@\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\000\231\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\176\129\"\193F\248\145\232\002\007\192\000\000c\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\132\001\016\002\003\004\142@\000\006\000\000\003\024\b\000\000\000\000\000\000\000\000\000`\000\005\000\000\000\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\004@\000\000\000\000\000\000\000\004\000\004\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\001\016\000\000\000\000\000\000\000\001\000\000\000\000@\000\b\128\000\000\000\000\000\000\000\000\000\000\000\002\004\000\004\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\0000\000\002\128\000\000\000\128\000\000\000\000`\017\192\000\000\000\000\000\000\003\000\000D\000\000\000\000\000\000\012\000@\160H\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\196\148\187\131\232>\022\028\015\251`w\237\1918x\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\145\003\224\012\004\004\003\224`\016\000,\016\028\000\000\128\000\000\000\000\000\000\002\000\000\000\000\000 \000\000\000\000\000\016\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016 \004\000\000\b\016@\000\001\000\000\000\000\000\000\129\000 \000\000@\128\000\000\b\000\000\000\000\000\000\000\000\000\000\002\000\016\000 \000\000\000\000\000\004l \b\176Q\190$z\000\129\240\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\024\000\000\002\000\000\000 \000\000\000\000\000\000\000\000\192\000\000\000\000\000\001\000\000\000\000\000\000\000\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\001\000\000 \000\000\129\000 \000\000@\128\000\000\b\000\000\000\000\002\018\000\138\000 \130Hp\000d\001\154\000\004\000\128 \b\b\000\004\024 \000\000\002\000\000\000\000\000@\000\000\000\000\016\000\004\000\000\000\016\000\000\000\000\b\016\002\000\000\004\b\000\000\000\128\000\000\000\000! \b\160\002\b$\135\000\006@\025\160\000@\b\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\0026\016\004X(\223\018=\000@\248\000\000\012p\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000@\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001 \000\000@\000\128\006\000\000\000\128\000\000\000\000\t\000\000\000\000\004\0000\000\000\004\000\000\000\000\000H\000\000\000\000 \000\128\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000@\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\004\000\b\000\000\000\002\000\000\024\000\003\000\000\006.\020\000\b\000\000\000\000\000\000\000\000\000\000\016\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\012\000\001\192@\003\023\b\000\004\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\001\000\000\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\136\000\000\000\000 \000\001\000\000\000\000\004\000\000\004@\000\000\000\001\000\000\000\000\000\000\000\000\000\000\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\004\004\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000D\000\000\000\000\016\000\000\128\000\000\000\002\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\002\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\001\128\0000\000\000b\225\000\000\128\000\000\000\000\002\022\002\138\000 \193Hp\000d\001\154\002\004 \128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\133\128\162\128\b R\028\000\025\000f\128\129\b \024\000\003\000\000\006.\020\000\b\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\006\000\000\192\000\001\139\132\000\002\000\000\000\000\000\bX\002(\000\130\005!\192\001\144\006h\b\016\130B\192Q@\004\024)\014\000\012\1283@@\132\016\000\000\000\000\000\000\000\016\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000#a\000E\130\141\241#\208\004\015\128\000\000\199\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006B\b\129\000\t\130M\160\002\003\000\000\001\004\0002\016D\b\000L\018-\000\016\024\000\000\b \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\132\001\002\000\019\004\139@\004\006\000\000\002\b\016\144\004P\001\004\002C\000\003 \012\208\000 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\018R\238\015\160\248Xp?\229\129\223\022\252\225\232\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003!\000@\128\004\193\"\208\001\001\160\128\000\138\006$\165\220\031A\240\176\224\127\203\003\190-\249\195\224\000\"\000\248\003\001\001\000\248\b\004\000\015\132\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\128 \000\016`\128\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\001\000\000\002\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\b\002\002\000\001\006\b\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\016\000\000 \000\b\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128 \000\016`\128\000\000\b\000\000\000\000\001\000\000 \000\000@\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \146\028\000\017\000f\128\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\128\016\000\000 A\000\000\004\000\000\000\000\000\002\004\000\128\000\001\002\000\000\000 \000\000\000\000\bH\002(\000\130\t!\192\001\016\006h\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\014\000\016\001\000\000\000\016\000\000\000\000\000\000\000\000 \000\000\b\000\b\000\128\000\000\000\000\000\000\000\001\000\000\000\000\000@\004\000\000\000\000\000\000\000\000\b\000\000\000\000\002\000\000\000\000\000\000\000\000\000! \b\160\002\b\004\134\000\004@\029\160\000@\000\002\000\128\128\000A\130\000\000\000 \000\000\000\000\012H\002(\000\131\001!\192\001\016\006h\000\016\000B@\017@\004\016\t\012\000\b\1283@\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`\000\128\000\000\000\000\128\000\000\000\000\000\000\000\003\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\024\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\004\000\000\128\001\t\000E\000\016@$0\000\"\000\205\000\002\000HH\002(\000\130\001!\000\001\016\006h\000\016\002\001\128\000\000\000\000\000\002\000\000\000\000\000\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\002\000\000@\000\132\128\"\128\b \018\024\000\017\000f\128\001\000$$\001\020\000A\000\144\128\000\136\0034\000\b\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\001\000\000 \000B@\017@\004\016\t\012\000\b\1283@\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\015\190\200\129\005\252j\000\t\131\131\220h\176(4'\225\"\213\138\173\2433\208\020\015\224\128\003\199\000\025\b\002\004\000&\t\022\128\b\r\004\000\004\016\004\000\000\128\000\000\000\001\000\000\000\000\000\t\002 F\194\000\139\005\027\226G\160\b\031\000\000\001\142\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000>\251\"\004\023\241\168\000&\014\015q\162\192\160\208\159\132\139V*\183\204\207@P?\130\000\015\028\000 @\b\b\000\016 \128\000\002\000\000\000\000\000\001\002\000@\000\000\129\004\000\000\016\000\000\000\000\000\b\016\002\000\000\004\b\000\000\000\128\000\000\000\000! \b\160\002\b$\135\000\004@\025\160\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\012\000@\000\000\000\000\000\000\000\000\000\000\000\000\000`\002\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\128\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\001\t\002E\000\016@$0\000\"\000\205\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000B@\017@\004\016\t\012\000\b\1283@\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\000\000\b\000\016\000\192\000\000\016\000\000\000\000\001 \000\000\000\000\128\006\000\000\000\128\000\000\000\000\t\000\000\000\000\004\000\016\000\000\004\000\000\000\000! \b\160\003\b\004\135\000\004@\029\160\000\192\000\002@\000\000\000\001\000\004\000\000\001\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000@\000B@\017@\004\016\t\014\000\b\1283D\000\132\000\004\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\132\128\"\128\b \018\028\000\017\000f\128\001\000\004$\001\020\000A\000\144\192\000\136\0034\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\t\000E\000\016@$8\000\"\000\205\000\002\000\bH\002(\000\130\001!\128\001\016\006h\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\128\000\000\000\002\000\b\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\004\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000 \000\004\000\000\018\000\000\000\000\b\000 \000\000\b\000\000\000\000B@\017@\004\016\t\012\000\b\1283@\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000`\000\012\000\000\024\184@\000 \000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\024\000\003\000\000\006.\016\000\b\000\000\000\000\000\000@ \000\000\004\016\000\000\000@\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\0000\000\006\000\000\012\\ \000\016\000\000\000\000\000B\192\017@\004\016)\012\000\b\1283@\000\128\002\022\002\138\000 \193H`\000D\001\154\000\004\000\016\144\004P\001\004\002C\000\002 \012\208\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000<\001\023\128\193\006>\144\000\136\003\004\000\b\000! \b\160\002\b\000\132\000\004\000\025\160\000@\000\002\000\000\000\128\000\000\b\000\000\000\000\000\000\b\000\016\000\000\004\000\000\000@\000\000\000\000\000\000\000\000\128\000\000\000\000\000\002\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\144\004P\001\004\016C\000\002\000\012\209\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000 \000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\001\t\000E\000\016A\0040\000 \000\205\016\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\192\002\000 \000\000\002\000\000\000\000\000\000\000\000\012\000\016\000\000\000\000\016\000\000\000\000\000\000\000\000`\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\016\000\n\000\004\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\t\000E\000\016A\0040\000 \000\205\016\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000 \b\b\000\004\024 \000\000\002\000\000\000\000\000\196\128\"\128\b0\002\028\000\016\000f\128\001\000$$\001\020\000A\000\016\128\000\128\0034\000\b\001\000\192\000\000\000\000\000\001\000\000\000\000\000\000\000\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\128 \000\016`\128\000\000\b\000\000\000\000\003\018\000\138\000 \192\bp\000@\001\154\000\004\000\144\144\004P\001\004\000B\000\002\000\012\208\000 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\004\000\000\128\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\000!\128\001\000\006h\128\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\001\001\000\000\131\004\000\000\000@\000\000\000\000\024\144\004P\001\006\000C\128\002\000\012\208\000 \000\132\128\"\128\b \002\024\000\016\000f\128\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\004\004\004\002\012\016@\000\001\000\000\000\000\000\000\128 \000\016`\130\000\000\b\000\000\000\000\000\004\001\001\000\000\131\004\000\000\000@\000\000\000\000\024\144\004P\001\006\000C\128\002\000\012\208\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\000\000\002\000\004\0000\000\000\004\000\000\000\000\000H\000\000\000\000 \001\128\000\000 \000\000\000\000\002@\000\000\000\001\000\004\000\000\001\000\000\000\000\bH\002(\000\194\000!\192\001\000\006h\0000\000\000\144\000\000\000\000@\001\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000D\000\000\002\000\002\0000\000\000\000\000\000\000\000\002\000\000\000\016\000\016\001\128\000\000\000\000\000\000\000\016\000\000\000\000\000\128\012\000\000\000\000\000\000\000\000\128\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\b\000\000\000\000\000\000\000\000@\000\004\144\000\128\000\000\016\000\000\000\000\000\128\000\000\002\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\016\000\004\000 \005\016 \000\000\000\000\000\000\000B\000\000@\000\001A\n\002\000\000\001\000@\000\002\016\000\002\000\000\n\b@\016\000\000\b\002\000\000\000`\000\014\002\000\024\184@\000 \000\000\000\000\000\000\000\b\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000!\000\000 \000\000\128\132\001\000\000\000\128 \000\000\016\000\000\000\000\128\128\b\000\000\000\000\000\000\000\000\128\000\000\000\004\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\006\000\000\224 \001\139\132\000\002\000\000\000\000\000\b@\000\b\000\000 !\192@\000\000 \b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000 \000\001\000\016\000\000\000\000\000\000\000\001\000\000\001\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\012\000\001\192@\003\023\b\000\004\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\001\000\000\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\004 \000\004\000\000\016\016\224`\000\000\144\004\000\000!\000\000 \000\000\128\134\001\000\000\000\128 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b@\000\b\000\000 !\192\192\000\001 \b\000\000\000\128\000 \001\000(\131\000\000\000\000\000\000\000\000\004\000\001\000\b\001D\b\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\004\000\000\000\000\000\000\004\000\b\000\000\000\000\000\000 \000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\016\000\000\000\016\000\004\000 \005\016 \000\000\000\000\000\000\000\001\128\0008\b\000b\225\000\000\128\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\128\000\000 \000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\024\000\003\128\128\006.\016\000\b\000\000\000\000\000\000\000\000\128\000\000\000\001\000\000\000\000\000\b\000\000\000\000\004\000\000\000\000\b\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\018\000\170\000 \136Hp\016D\001\218\002\004\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000@\000\000\000@\000\016\000\128\020@\128\000\000\000\000\000\000\001\t\000U\000\016D$8\b\"\000\237\001\002\000H@\000\b\000\000 !\192@\000\000 \b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\000\001\192@\003\023\024\000\004\000\000\000\000\000\000`\000\014\002\000\024\184@\000 \000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000\000\000\000\024\000\003\128\128\006.\016\000\b\000\000\000\000\000!\000\000 \000\000\128\135\003\000\000\000\128 \000\001\b\000\001\000\000\004\0040\b\000\000\004\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\128\000\002\002\024\004\000\000\002\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\b\000\001\000\000\004\004 \b\000\000\004\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000B@\017@\004\016\t\014\000\b\1283@\000\128\018\018\000\138\000 \128H@\000D\001\154\000\004\000\129\000\000\000\000\000\b\000\192\000\000\000\000\000\000\000\b\000\000\000\000\000@\002\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\016\000\004\000 \005\016 \000\000\000\000\000\000\000B@\017@\004\016\t\014\000\b\1283@\000\128\018\018\000\138\000 \128H@\000D\001\154\000\004\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\002\0000\000\000\000\000\000\000\000\002\000\000\000\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\128\004\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\012\000\001\192H\003W\b\000\004\000\000\000\000\000\016\176\021P\001\006\bC\128\002 \014\208\000`\004\003\000\000`\000\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\192\000\028\004\1285p\128\000@\000\000\000\000\000\006\000\000\224 \001\139\132\000\002\000\000\000\000\020\000\000\000 \000\000\000\000@\000\000\000\000\002\000\128\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\012\000\001\192H\003W\b\000\004\000\000\000\000\000\000`\000\012\000\000\024\184@\000 \000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\024\000\003\128\144\006\174\016\000\b\000\000\000\000\000!`*\160\002\012\016\135\000\004@\029\160\000@\t\011\001U\000\016`\1328\000\"\000\237\000\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000B@\021@\004\016\001\014\000\b\000;@\000\128\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \002\024\000\016\000f\128\001\000$$\001\020\000A\000\016\128\000\128\0034\000\b\001\002\000\000\000\000\000\016\001\128\000\000\000\000\000\000\000\016\000\000\000\000\000\128\004\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000 \000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000`\000\014\002@\026\184@\000 \000\000\000\000\000\132\128\"\128\b \002\024\000\016\000f\128\001\000$$\001\020\000A\000\016\128\000\128\0034\000\b\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000B@\017@\004\016\001\b\000\b\0003@\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\000!\128\001\000\006h\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\018\000\138\000 \128\b@\000@\001\154\000\004\000\128@\000\004\144\000\152\000\128\016\000\000\000\000\000\128\002\000\000$\128\004\192\000\000\128\000\000\000\000\004\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000! \b\160\002\b\004\134\000\004@\029\160 @\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\001!\128\001\016\006h\b\016\002B@\017@\004\016\t\b\000\b\1283@\000\128\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \002\016\000\016\000f\128\001\000 \016\000\001$\000&\000 \004\000\000\000\000\000 \000\128\000\t \0010\000\000 \000\000\000\000\001\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\001\144\000<\b\000b\225@\000\128@\b\000\004\000\012\000\t\192@\003\023\b\000\004\000\000\000\000(\000\000\000\000\000\b\b\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\011@E\000\016A$4\000\"\001\205\001\002\000HH\002(\000\194\001!\192\001\016\006h\b0\130B@\017@\004\016\t\014\000\b\1283@@\132\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\144\004P\001\004\002C\000\002 \012\208\016!\004\001 \000\000\000\000\128\002\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\t\000E\000\016@\0040\000 \000\205\001\002\000HH\002(\000\130\000!\000\001\000\006h\000\016\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \018\028\000\017\000v\128\129\000 \t\000\000@\000\004\000\020\000\000\004\000\128\000@\000H\000\000\000\000 \000\160\000\000 \004\000\002\000\000\000\000\000\000\128\128\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\012 \018\028\000\017\000f\128\131\b$$\001\020\000A\000\144\224\000\136\0034\004\bA\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\128\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\128\000\000\000\000\000\000\000\b\128\000\000@\000@\006\000\000\000\000\000\000\000\000@\000\000\000\000\002\0000\000\000\000\000\000\000\000\002\000\000\000\000\000\016\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\128\004\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\001\148\128(H\002`\145X\000\128\200\000\001A\000\004\000\001\000\b\003D\b\000\000\016\000\000\000\000\016\128\000\016\000\000PB\129\128\000\000@\016\000\000\132\000\000\128\000\002\130\016\012\000\000\002\000\128\000\004 \000\004\000\000\016\016\128`\000\000\016\004\000\000\002\000\000\000\000\016\016\001\000\000\000\000\000\000\001\000\000\000\000\000\000\128\128\b\000\000\000\000\000\000\000\000\000\000\000\000\004\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000H\000\004l \b\176Q\190$z\000\129\240\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\b\216@\017`\163|H\244\001\003\224\000\0001\192\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b@\000\b\000\000 !\128\192\000\000 \b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\001\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\001\128\0008\b\000b\225\000\000\128\000\000\000\000\002\016\000\002\000\000\b\bp0\000\000\b\002\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\018\000\001\027\b\002,\020o\137\030\128 |\000\000\0068\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\0026\016\004X(\223\018=\000@\248\000\000\012p\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000 \000\001\000\016\000\000\000\000\000\000\016\000\000\000\001\000\000\b\000\128\000\000\000\000\000\000\000\000\000\000\b\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\006R\000\161 \t\130E`\002\003 \000\005\004\0008\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000`\000\014\002\000\024\184@\000 \000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000\000\000\001\027\b\002,\020o\137\030\128 |\000\000\0068\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\0026\016\004X(\223\018=\000@\248\000\000\012p\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\128\000\016\000\000@C\001\128\000\000@\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000@\000\002\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\003\000\000p\016\000\197\194\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\006R\000\161 \t\130E`\002\003 \000\005\004\0008\000\007\001\000\012\\ \000\016\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000`\000\014\002\000\024\184@\000 \000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\016\000\000\000\001\027\b\002,\020o\137\030\128 |\000\000\0068\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\0026\016\004X(\223\018=\000@\248\000\000\012p\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004l \b\176Q\190$\250\000\129\240\000\000\024\224#a\000E\130\141\241#\208\004\015\128\000\000\199\004 \000\004\000\000\016\016\192`\000\000\016\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\128\004\001\162\012\000\000\b\000\000\000\b\000\016\000\004\000 \r\016`\000\000@\000\000\000\000\000\128\000 \001\000h\129\000\000\002\000\000\000\000\000\004\000\001\000\b\003D\b\000\000\016\000\000\000\000\000d \136\025\000\152$\218\000 0\000\000\016@}\246D\b/\227P\000L\028\030\227E\129A\160\025\b\"\004\000&\t6\128\b\012\000\000\004\016\000\200A\016 \0010H\180\000@`\000\000 \128\006B\000\129\000\t\130E\160\002\003\000\000\001\004\000\000\000\000\000\000\000\000\128\000\128\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\016\000\000\000\000\000\000\016\000 \000\000\000\000\000\000\128\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000@\000\000\000@\000\016\000\1284@\128\000\001\000\000\000\000\000\006\000\000\224 \001\139\132\000\002\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\002\000\000\000\128\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000e \n\018\000\152$\214\000 0\000\000\016@\003)\000P\144\004\193\"\176\001\001\128\000\000\130\000\025H\002\132\128\166\t\021\128\b\012\000\000\004\016\000@\000\016\000\1284@\128\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000@\016\000\004\000 \r\016 \000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\022\164\171Pb\139L\254\240D\007\154\002\015\026\144\181%Z\131\020Zg\247\130 <\208\016x\212\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004$\001T\000A\016\144\224`\136\0034\004\024\005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002\168\000\130!!\192\193\016\006h\b0\n\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\144\005P\001\004BC\129\130 \012\208\016`\020\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000@\000\000\000@\000\016\000\1284@\128\000\001\000\000\000\000\001\t\000U\000\016D$8\024\"\000\205\001\006\001@2\016D\b\000L\018-\000\016\024\000\000\b \001\144\128 @\002`\145h\000\128\192\000\000A\000\000\000\000\000\000\000\000 \000 \000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\b\000\000\000\000\004\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\000\000\224$\001\171\132\000\002\000\000\000\000\000\b\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\128\000\016\000\000@C\129\128\000\000@\016\000\016\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000!\000\000 \000\000\128\134\003\000\000\000\128 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\004\000 \r\016 \000\000@\000\000\000\000B\000\000@\000\001\001\014\006\000\000\001\000@\000B\016\000\002\000\000\b\b`0\000\000\b\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\000\000p\016\000\197\198\000\001\000\000\000\000\000\000\024\000\003\128\128\006.\016\000\b\000\000\000\000\000!\000\000 \000\000\128\134\003\000\000\000\128 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\128\000\016\000\000@C\001\128\000\000@\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000!\000\000 \000\000\128\132\003\000\000\000\128 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\001!\192\001\016\006h\000\016\002\001\128\0008\t\000j\225\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000 \000\b\000@\026 @\000\000\128\000\000\000\000\132\128\"\128\b \018\028\000\017\000f\128\001\000 \025H\002\132\128&\t\021\128\b\012\128\000\020\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\t\000E\000\016@$0\000\"\000\205\000\002\000HH\002(\000\130\001!\000\001\016\006h\000\016\002\004\000\000\000\000\000 \003\000\000\000\000\000\000\000\000 \000\000\000\000\001\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000@\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\025H\002\132\128&\t\021\128\b\012\128\000\020\016! \b\160\002\b\004\134\000\004@\025\160\000@\t\t\000E\000\016@$ \000\"\000\205\000\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\144\004P\001\004\002B\000\002\000\012\208\000 \000\003!\004@\192\004\193&\208\001\001\128\000\000\130\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\144\004P\001\004\002B\000\002 \012\208\000 \004\132\128\"\128\b \018\024\000\017\000f\128\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000! \b\160\002\b\004\132\000\004@\025\160\000@\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\144\004P\001\004\002C\000\002\000\012\208\000 \000\132\128\"\128\b \018\016\000\016\000f\128\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000B@\017@\004\016\t\b\000\012\1283@\000\128\016\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\128\"\128\b \018\024\000\016\000f\128\001\000\004$\001\020\000A\000\144\128\000\128\0034\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\024\144\005P\001\006\018C\128\002 \014\208\002 \004\192\000\b\000\000\016\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\b\000\000\000\000\000L\017\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\128\0008\b\000b\225\000\000\128\000\000\000\000\000\000\000 \000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\128\000\002\002\016\012\000\000\002\000\128\000\004\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\b\016\002\002\000\004\b \000\000\128\000\000\000\000\000@\128\016\000\000 A\000\000\004\000\000\000\000\000\002\004\000\128\000\001\002\000\000\000 \000\000\000\000\000\000\000\128\000\000\b\000@\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\004\001\001\000\000\131\004\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\b\000\000\016\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\002\000\000\000\000\000\000\000\000\000\000\004\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\131!\000@\128\004\193\"\208\001\001\160\128\000\138\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0001%.\224\250\015\133\135\003\254X\029\241o\206\030\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000$\000\001\000\000\016\000@\000\000\016\000\000\001\000\001 \000\000\000\000\128\002\000\000\000\128\000\000\b\000\t\000\000\000\000\004\000\016\000\000\004\000\000\000\000! \b\160\003\b\004\135\000\004@\029\160\000\194\000\002@\000\000\000\001\000\004\000\000\001\000\000\000\000\bH\002(\000\130\001!\192\001\016\006h\000\016\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\018\000\138\000 \128H`\000D\001\154\000\004 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\018\000\138\0000\128Hp\000D\001\218\000\012 \000$\000\000\000\000\016\000@\000\000\016\000\000\000\000\132\128\"\128\b \018\028\000\017\000f\128\001\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\016\000\000\000\000\000\000\000\000\001\t\000E\004\016@$0\000\"\000\237\001\002\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000B@\017@\004\016\t\012\000\b\1283@@\128\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\001 \000\b\000\000\128\002\000\000\000\128\000\000\b\000\t\000\000\000\000\004\000\016\000\000\004\000\000\000@! \b\160\002\b\004\134\000\004@\025\160\000B\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\016\000\000\128\000\000\000\000\000\000\002\000\000\000\000\000\000\000\004\000\000\000\000\000\003\000\000`\000\000\197\198\000\001 \000\016\000\000\000\024\000\003\000\000\006.\016\000\t\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\001\000\000\000\004\000\000\000\018\000\000\000\000\000\001\128\0000\000\000b\225\000\000\144\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\006\000\000\224 \001\139\132\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\016\000\000\004\000\000\000\000\001\000\000\000\004\000\000\000\000\000\000 \000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\192\000\028\004\0001p\128\000@\000\000\000\000\000\000\000\016\000\000\000\000\b\000\000\000\000\000@\000\000\000\000\128\000\000\000\000@\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\000\001\192@\003\023\b\000\004\000\000\000\000\000\000\000\001\000\000\000\000\000\128\000\000\000\000\004\000\000\000\000\000\000\000@@\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bH\002(\000\130\001!\192\001\016\006h\b\016\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000d\000\015\002\000\024\184P\000 \016\002\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004$\001\020\000A\000\016\192\000\128\0034\004\b\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\018\000\000\128\000\b\000 \000\000\b\000\000\000\128\000\144\000\000\000\000@\001\000\000\000@\000\000\004\002\018\000\138\000 \128\b`\000@\001\154\000\004 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\128\000\000\000\000\000\000\000\000\bH\002( \130\000!\128\001\000\007h\b\144\002\001\144\000<\b\000b\225@\000\128@\b\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\144\004P\001\004\000C\000\002\000\012\208\016 \004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000H\000\002\000\000 \000\128\000\000 \000\000\002\000\002@\000\000\000\001\000\004\000\000\001\000\000\000\016\bH\002(\000\130\000!\128\001\000\006h\000\016\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\000\000@\000\000\128\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\t\000E\000\016@$8\000\"\000\205\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004l \b\176Q\190$z\000\129\240\000\000\024\224\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\001\027\b\002,\020o\137\030\128 |\000\000\0068\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\144\004\016\001\004\000B\000\002\000\012\144\000 \000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002@\000\000\000\001\128\004\000\000\001\000\000\000\000\b\000\b\128~\002\194@\000>\"\001\002\000\193E\128\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000@\000\000\000@\000\000\000\0000\000\000\000\000\000\000\000\000\001\000\001\000\015\192XH\000\007\196@ @\024(\176\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\144\000\000\000\000@\001\000\000\000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\024\000\003\128\128\006.\016\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\176\128\"\193F\248\145\232\002\007\192\000\000c\128\000\000\000\000\000\000\000\000\000\000\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\b\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\129\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\144\128 @\002`\145h\000\128\208@\000A\000\000\000\000\000\000\000\000\016\000\000\000\016\000\144\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\004\000\000\000\000\003\000\000\000\000\000\000\000\000\000\004\252$\024\177U\190fz\002\161\252\144\0008\224\001\000\000\000\000\000@\000\000\000\000\000\000\000\000\000-\t\004\000A\006\144\128\128\136\007$\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\144\004\016\001\004\002B\000\002 \012\145\000 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000H\002\b\000\130\001!\000\001\000\006\b\000\016\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\128\000\000\000\000 \000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000O\194A\139\021[\230g\160*\031\201\000\003\142\002~\018\012X\170\2233=\001P\254H\000\028p\002@\016@\004\016\t\b\000\b\1282@\000\128\000\018\000\130\000 \128H@\000D\001\146\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000$\001\004\000A\000\144\192\000\136\003$\000\b\000\001 \b \002\b\004\132\000\004@\025 \000@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\018\000\130\000 \128H`\000D\001\146\000\004\000\000\144\004\016\001\004\002B\000\002 \012\144\000 \000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000") and start = 13 and action = - ((16, "C\170P\226Ff\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\021HFf\000\000\000\000\020XFfC\170\020\182\000-\000[\\(\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\132\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\021\238\006\168\000\218\000\000\003\188\t|\000\000\001\208\003\232\nt\000\000\000\244\004\198\011l\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\220\000\000\000\000\000\000\0046T\016\000\000\000\000\000\000\005.\000\000\000\000\000\000\005\022\005\b\000\000\000\000T\016H\254\020X\021\178^\128\020X\\\142P\226\020XR,\000\000\007\168\000\000Dp\007\214\000\000C\146\000\000\027\158\000\000\000\000\004\246\000\000\005.\000\000\000\000\000\000\002J\000\000C\146\000\000\006&v\246]\160d\194\000\000\132l\134\028\000\000LP_\014\000\000X\\\026\206K\200\005.p\026FfC\170\000\000\000\000P\226\020XS\148Dp\007\012v\246\000\000\128\178FfC\170P\226\020X\000\000\000\000\016x\023\022\001N\b\004\000\000\002\138\b\022\000\000\000\000\000\000\000\000\000\000\020X\000\000A\206i\164C\170\000\000\000\000P\206\020XZ\024W\200\000\000\004\002\000\000\000\000\005\242\000\000\000\000H\166\004\002\024\138\003\130\0020\000\000\000\000\003\172\000\000\021\178\006\212\006\160\020X\028\254\020XC\170C\170\000\000M\\M\\\020X\028\254A\248\020X\000\000\000\000\000\000P\226\020X\000\000\000\248\000\000W\200y\188zJ\000\000\b\004\000\000\n\196\000\000\000\000A\214T\016\134h\000\000h\142\134h\000\000h\142h\142\000b\006:\0008\000\000\020\190\000\000\007b\000\000\000\000\b\198\000\000\000\000\000\000h\142\005.\000\000\000\000V\222T\016T\132_\014\000\000\000\000N*\000b\000\000\000\000_\014\007\162T\016\000\000O _\014P\022\000\000\000\000\000\000\011\190\000\000h\142\000\000\001\000\1310\000\000T\016\005\216T\016\000\000\022\\\b\150\005.\000\000\000\000\023\224\000\000\006\208\000\000Y\128\011\230\000\000\b\162h\142\012\182\000\000\012\222\000\000\007\200\000\000\000\000\004\184\000\000\000\000\000\000\021 4W\200P\206\020XW\200\000\000\000b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000M:\027v\000\000\000\000\000\000\001\244&\174t<\000\000\000\000P\206\020XW\200\000\000\000\000{hW\200\136.zJ\000\000\136v\000\000W\200\000\000\000\000X\180\000\000\000\000\000\000\n.\000\000\022\168\000\000\000\000z\214\000\000\136\208{\030\000\000\137\018\t\002\000\000\000\000z\214\000\000\004\024\000\000\000\000DHt\200\000\000\000\000\000\000Bn\023|\019\252\023\174\000\000\000\000\000\000\000\000\004\250\000\000\000\000Z\204\b\254\011F\000\017T\016\002\204\011\148\000\000\000\000\t\156\011F\006\172\000\000i\186P\234M\\\020X\028\254\000-\000\018\0020\000\000\n\240\021\178\021\178\000-\000\018\000\018\021\178\000\000jL\0050Dp\b\004\000\236\137`\000\000T\016ebT\016_ f\002T\016\000\144T\016f\156\000\000\000\000\020d\0008_\192\b\022\0008`\024\000\000j\230\0050\000\000\021\178k\128\000\000\b*\t\014`\184\000\000\000\000\000\000\000\000\000\000\000\000\001B\000\000\000\000\003\144\000\000\007r\028\254\000\000\\\192A\248\000\000\031\138\000\000\000\000\021\178\002\152\000\000\000\000\000\000\000\000[\132\000\000\001\200\000\000UP\001\130\005\"\000\000\0226V\170P\226\020XG,P\226\020X\016x\016x\000\000\000\000\000\000\000\000\001\240\024&B\188\000\000Q\150RJM\\\020X\028\254\b`\021\178\000\000\004*\000\000R\254S\178{\182I~T\016\002\128\000\000P\226\020X\000\000u\016\020Xy\188W\200E\178\000\000P\226\020Xw\\\004~\000\000W\200A\012T\016\003x\006\172\011\196\000\000\000\000\000\000H\166\003\138\003\138\000\000\012\154p\156\000\000P\206\020XW\200\025R\000\000P\226\020X\016x\0226\016x\002\232\023\240\000\000\000\000\016x\012\148\000\000\r\000\000\000\016x\003\224\rX\000\000'\166\000\000\b\196\000\000\000\000\026\022\000\000\017p\023.\000\000\000\000\000\000\000\000\b\020\000\000\000\000\027\014\000\000\028\006\000\000\028\254\000\000\018h\024&\000\000\000\000\000\000Ff\000\000\000\000\000\000\000\000\029\246\000\000\030\238\000\000\031\230\000\000 \222\000\000!\214\000\000\"\206\000\000#\198\000\000$\190\000\000%\182\000\000&\174\000\000'\166\000\000(\158\000\000)\150\000\000*\142\000\000+\134\000\000,~\000\000-v\000\000.n\000\000/f\000\0000^\020XW\200ZJI\146\003\138\014,l\012W\200\000\000\000\000\000\000h\142\000\000\028\018\134\028\000\000\026\"T\016\029\220\r\198\000\000\000\000\000\000\000\000l\012\000\000\000\000\005\242\014\208\000\000B\170\000\000\000\000\135\176\000\000\bB\000\000\000\000K\200\003\138\014\140T\016\b`\000\000\000\000\007\006\005.\000\000T\016\n\146\000\000\000\000\014\244\000\000\000\000\000\000I\190T\016\0118\000\000\000\000\030*\000\000\000\000{\254\000\000\031\"|\138\000\000 \026|\210\000\000!\018\t\250\000\000\000\000\000\000\000\000\"\nW\200#\002p\234p\234\000\000\000\000\000\0001V\000\000\t\188\000\000\000\000\000\000q\140\000\000\000\000\002\138\023\248\000\000\b\226\000\000\000\000]bKl\000\000\000\000\n\180\000\000\000\000\000\000\rh\000\000\000\000\000\000\016x\004\216\024\232\000\000\t\218\000\000\005\208\000\0002N\000\000\012\142\000\000\006\200\000\0003F\000\000\015\138\007\192\000\0004>lt\000\000(\158\000\000\n\"\b\184\000\00056\000\000\r\178\t\176\000\0006.\000\000q\150\n\168\000\0007&\005\180\025\016\000\000\nX\011\160\000\0008\030\000\000\r\200\012\152\000\0009\022\000\000\r\172\r\144\000\000:\014\014\136\000\000;\006\015\128\019`\000\000\000\000\000\000\n\210\000\000\000\000\014`\000\000\000\000\015\156\000\000\011\002\000\000\000\000\000\000\015\028\000\000\015*\000\000\000\000J~\003\138\015\218p\156_\014\000b\000\000\000\000p\156\000\000\000\000\000\000p\156\000\000\015\208\000\000\000\000\000\000\000\000\000\000\000\000;\254W\200\000\000\000\000\016\014\000\000<\246\000\000=\238\000\000#\250\000\000\000\000\n\130\000\000\000\000W\200\000\000\000\000}j\011P\000\000\000\000G,\000\000\014\148\000\000\000\000V\020\000\000\014~\000\000\000\000\001\130\011\254\000\000\000\000\0226\022\028\b\004\000\000B>\000\000!,\023\176\021\220\000\000\000\000\014\002\000\000\000\000\001\238\025\030V\180\000\000\025\030\000\000\tX\000\000\000\000\014\142\000\000\000\000g>\t\004\004H\000\000\000\000\012H\000\000\000\000\014\192\000\000\000\000\000\000\020X\028\254\005\168\000\000\000\000\023&\003\130\0020\003\136\028\254w\228\021\178\001B\028\254xb\015\146\000\000\000\000\003\136\000\000H\232\019\248\021\204\000\000\007X\016\"\000\000\016$\000V_\014\006\196\000\000\016\n\015\170K\200\n|T\016\030\128\020F\r\018\004\248\000\000\031x\016\\\000\000\006\196\000\000\000\000\016\130_\014aX\000\000g\144_\014\016Z_\014m\012a\248\001N\016*\000\000\000\000\000\000\020X\128\252\000\000W\200p\234\000\000\000\000\016\156\000\000\000\000\000\000>\230\016\196y\188?\222h<\000\000\000\000HJ\000\000\005\128\000\000L\136\000\000\020X\000\000\021\178\006\026\000\000\128\178\000\000\020X\028\254\128\178\000\000\025D\023\022\001N\005.\130\144\021\178}\248p\234\000\000\005r\t\168\0020\003\136p\234\132\224\003\130\0020\003\136p\234\132\224\000\000\000\000\003\136p\234\000\000FfC\170W\200\027B\000\000\000\000FfC\170M\\\020X\028\254\128\178\000\000\020\182\000-\000[\015\240T\016\0120\016\190\131P\000\000p\234\000\000H\232\019\248\021\204x\186\023\228\0118~,\nZ\016\b\020Xp\234\000\000\020Xp\234\000\000h\142ff\019\134\002\222\001N\0008N\234\000\000\001N\0008N\234\000\000\025D\005r\n\160\0212\bZ\000\000N\234\000\000\0020\016\016\021\178p\234\134\222\003\130\0020\016 \021\178p\234\134\222\000\000\000\000\tX\000\000O\224\000\000\021\178\131\132N\234\000\000\b\242\000\000H\254\020X\021\178p\234\000\000H\232\019\248\021\204rFB\138\026\222\019\170\002\142\000\000\011vC\146\000\017\000\000\016\176\016b\024\196\020XT\184T\016\0120\000\000W\150\001N\005\204\r\216\000\000\n\024\000\000\016\188\016FT\016O(\000\000\0032\004\212\r\218\000\000\n\236\000\000\016\192\016JK\200\r\028T\016K\182O(\000\000UP\020X\024\196\016\232\011\028\001N\000\000\014\012\024\196T\016\012\208\000b\000\000T\016\n$\n\218\000\000\000\000mf\000\000\000\000\014b\024\196m\228O(\000\000\020XT\016\012\226T\016V\\O(\000\000\014\144\000\000\000\000O(\000\000\000\000W\150\000\000p\234\132\238\019\170\002\142\011v\016\218\016\140\024\196p\234\132\238\000\000\000\000\019\170\002\142\011v\016\230\016\138M\252LZ_\014\017\016M\252h\142\020\184\017\030M\252_\014\017 M\252n\132o\004\000\000\129\140\000\000\000\000p\234\134\236\019\170\002\142\011v\017\022\016\162M\252p\234\134\236\000\000\000\000\000\000ff\000\000\000\000\000\000\000\000\000\000\000\000N\234\000\000\133\128\020XDp\017 v\246\000\000\128\178\133\128\000\000\000\000\1358\020XDp\017*\016\188]\160\135\176\006\196\017l\000\000\000\000o\130rF\020X\000\000~\200\021\204\000\000\000\000\128\178\1358\000\000\000\000\000\000y6D\228I\154\006\196\017v\000\000\000\000\000\000rF\020X\000\000\006\196\017z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\014\168B\138\019\170\002\142\011v\017Xr\182\023\204\020XZ\024j\190\020(\001N\006\196\017Z\011l\000\000\000\000\017\b\000\000\000\000a\152\000\000\007\188\r\230\000\000\r\140\000\000\017`\016\244T\016d\240\017r\011\150\000\000\000\000\017\"\000\000\000\000\020F\0032\014\210\000\000\017~s8\137\172\003\138\017\028T\016\014 \000\000\000\000\017<\000\000\000\000\000\000a\152\000\000\0070\014\246\000\000\r\212\000\000\017\168\0176K\200\000\000\017\180s\186\137\248\003\138\017RT\016\015\024\000\000\000\000\017d\000\000\000\000\000\000\020X\000\000a\152\000\000\020z\020X\023\204\023\204u\168Ff\020X\128\252W\200\021\162\000\000\012V\001N\000\000\014\220\023\204T\016\014\186\b\004\000\000\020XW\200r\182\023\204\rh\023\204\000\000D\142Et\000\000bR\000\000\000\000b\238\000\000\000\000c\138\000\000\014\238\023\204d&\128\252W\200\021\162\000\000\000\"\000\000\000\000M\252\r\026\000\000\000\000d.\017\186\000\000a\152\000\000\023\204d.a\152\000\000\020XT\016a\152\000\000\015\136\000\000\000\000a\152\000\000\000\000j\190\000\000\129\192M\252\017r\023\204\130\\r\182\000\000p\234\133\142\019\170\002\142\011v\017\210r\182p\234\133\142\000\000\000\000\000\000\135\248P\206\000\000\000\000\000\000\000\000\000\000\000\000\132\022p\234\000\000\133\128\000\000\000\000\000\000\000\000p\234\135\248\000\000\018\014\000\000\000\000\132\022\018\020\000\000p\234\135\248\000\000\000\000\015\222\000\000\000\000i4\0032\000\000\000\000DH\000\000T\016\015\n\000\000j\190\015\240\000\000\000\000\000\000\015\156\000\000\000\000\000\000M\\\020X\028\254\006\178\000\000Z8\000\000\007p\000\000\000*\000\000\000\000\0184\000\000\018\\y\188\000\000@\214\018@\000\000\000\000\0182\026R\028B\021\204v0\023\228\020X\000\000\128\178\000\000\000\000\000\000\000\000\000\000\000\000\000\000v8\023\228\020X\000\000\015\190v\246\000\000\128\178\000\000\0184\026R\028B\128\178\000\000\018H\000\000\000\238\014\140\020X`\226\000\000\000\000\028\190y\242\000\000\000\000\017\214\000\000\018.T\016\000\000\015\170\012\166\000b\000\000\000\000T\016\004R\006B\000\000T\016\012\018\006\196\018\\\000\000\000\000\127\"\000\000\000\000]\160\000\000\128\178\000\000\018V\026R\029:N\234\000\000\000\000\000\000\000\000\015\214\127\188]\160\000\000\128\178\000\000\018`\026R\029:N\234\000\000\016\026\000\000\000\000\b\n\000\000p\234\000\000\018t\000\000\000\000\017\230\000\000\017\236\000\000\017\252\000\000\000\000\\\142\018\000\000\000\000\000%\182\\(\018\158\000\000\000\000\000\000\014z\011D]\232\018\164\000\000\000\000\000\000\000\000\000\000\000\000\018\022\000\000\023\228\000\000\018\030\000\000T\016\000\000\t\b\000\000\000\000\018 \000\000\000\000\0008\000\000\003\210\000\000\000\000\000\000\001\214\000\000\016\030\000\000\0180\000\000W\200\022\168\000\000\000\000\012<\018H\000\000\000\000\018B\r$G,\005.\128:\000\000\000\000\000\000\000\000\000\000YL\000\000\000\000\018\234\000\000\138<\000\000\016p\018\236\000\000\018\238\000\000G\224G\224[\190[\190\000\000\000\000p\234[\190\000\000\000\000\000\000p\234[\190\018Z\000\000\018f\000\000"), (16, "\t)\t)\000\006\001\002\001\190\t)\002\186\002\190\t)\002\234\002\130\t)\003\145\t)\018\158\002\246\t)\023\158\t)\t)\t)\025F\t)\t)\t)\001\210\004A\004A\004F\002\250\t)\003>\003B\t\242\t)\001\206\t)\023\162\003F\000\238\002\254\025J\t)\t)\003\214\003\218\t)\003\222\0032\003\234\003\242\006\214\007\018\t)\t)\002\178\001\206\006\242\003:\t)\t)\t)\b\026\b\030\b*\b>\001*\005v\t)\t)\t)\t)\t)\t)\t)\t)\t)\b\178\000\238\t)\015\154\t)\t)\003\145\b\190\b\214\t*\005\130\005\134\t)\t)\t)\r\190\t)\t)\t)\t)\002j\002\154\r\238\t)\006\178\t)\t)\0035\t)\t)\t)\t)\t)\t)\005\138\b2\t)\t)\t)\bJ\004r\t>\0035\t)\t)\t)\t)\012\245\012\245\023\166\n\206\004\154\012\245\n\218\012\245\012\245\000\238\012\245\012\245\012\245\012\245\004A\012\245\012\245\001f\012\245\012\245\012\245\003i\012\245\012\245\012\245\012\245\004A\012\245\015\250\012\245\012\245\012\245\012\245\012\245\012\245\012\245\012\245\007\190\007\030\007R\012\245\004\226\012\245\012\245\012\245\012\245\012\245\004A\012\245\012\245\004A\012\245\003\238\012\245\012\245\012\245\000\238\007\194\012\245\012\245\012\245\012\245\012\245\012\245\012\245\000\238\012\245\012\245\012\245\012\245\012\245\012\245\012\245\012\245\012\245\012\245\012\245\004A\012\245\012\245\007\138\012\245\012\245\001j\004A\007.\004A\012\245\012\245\012\245\012\245\012\245\004A\012\245\012\245\012\245\012\245\012\245\000\238\012\245\012\245\0076\012\245\012\245\000\238\012\245\012\245\012\245\012\245\012\245\012\245\012\245\012\245\012\245\012\245\012\245\012\245\012\245\b\"\004A\012\245\012\245\012\245\012\245\001\181\001\181\001\181\001f\015Z\001\181\003i\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\015\006\001\181\007\222\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\003\134\003\138\001\181\000\238\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\006\246\001\181\001\181\001\181\b\022\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\002f\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\027\187\001\181\001\181\018\142\007\250\007\030\007n\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\014\202\bb\001\181\005\186\001\181\001\181\007\254\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\182\001\181\001\181\001\181\001\181\001\181\n]\n]\002\225\007\138\r\025\n]\003\149\n]\n]\000\238\n]\n]\n]\n]\001\186\n]\n]\r\025\n]\n]\n]\000\238\n]\n]\n]\n]\002j\n]\000\n\n]\n]\n]\n]\n]\n]\n]\n]\024\222\007\030\b\174\n]\004A\n]\n]\n]\n]\n]\000\238\n]\n]\012\"\n]\003\018\n]\n]\n]\002\225\024\226\n]\n]\n]\n]\n]\n]\n]\004A\n]\n]\n]\n]\n]\n]\n]\n]\n]\n]\n]\003\149\n]\n]\007\138\n]\n]\004A\004A\007\030\004A\n]\n]\n]\n]\n]\004\001\n]\n]\n]\n]\tV\000\238\t\134\n]\005\241\n]\n]\007\202\n]\n]\n]\n]\n]\n]\n]\n]\n]\n]\n]\n]\n]\003\146\n]\n]\n]\n]\n]\003\173\003\173\001r\007\138\006\242\003\173\t\022\003\173\003\173\000\238\003\173\003\173\003\173\003\173\000\238\003\173\003\173\006\137\003\173\003\173\003\173\000\238\003\173\003\173\003\173\003\173\001\130\003\173\006Z\003\173\003\173\003\173\003\173\003\173\003\173\003\173\003\173\006\137\007\030\004\001\003\173\004B\003\173\003\173\003\173\003\173\003\173\015J\003\173\003\173\006^\003\173\t\005\003\173\003\173\003\173\005\241\b\146\003\173\003\173\003\173\003\173\003\173\003\173\003\173\015R\003\173\003\173\003\173\003\173\003\173\003\173\003\173\003\173\003\173\003\173\003\173\b\213\tN\t~\007\138\003\173\003\173\003\150\003^\b\230\027\171\003\173\003\173\003\173\003\173\003\173\004R\003\173\003\173\003\173\003\173\tV\000\238\t\134\003\173\b\"\003\173\003\173\003b\003\173\003\173\003\173\003\173\003\173\003\173\003\173\003\173\003\173\003\173\003\173\003\173\003\173\000\238\003\173\003\173\003\173\003\173\003\173\003\161\003\161\018\250\b\234\t\006\003\161\005R\003\161\003\161\t\005\003\161\003\161\003\161\003\161\001\146\003\161\003\161\006\154\003\161\003\161\003\161\002N\003\161\003\161\003\161\003\161\019\002\003\161\001\198\003\161\003\161\003\161\003\161\003\161\003\161\003\161\003\161\006\237\b\213\004A\003\161\002R\003\161\003\161\003\161\003\161\003\161\b\029\003\161\003\161\001\218\003\161\007\"\003\161\003\161\003\161\006\237\004A\003\161\003\161\003\161\003\161\003\161\003\161\003\161\004A\003\161\003\161\003\161\003\161\003\161\003\161\003\161\003\161\003\161\003\161\003\161\000\238\tN\t~\001\234\003\161\003\161\004A\004A\007\030\007^\003\161\003\161\003\161\003\161\003\161\001\222\003\161\003\161\003\161\003\161\tV\004A\t\134\003\161\004r\003\161\003\161\016v\003\161\003\161\003\161\003\161\003\161\003\161\003\161\003\161\003\161\003\161\003\161\003\161\003\161\006\237\003\161\003\161\003\161\003\161\003\161\t\217\t\217\018\206\007\138\b&\t\217\006\158\t\217\t\217\001\238\t\217\t\217\t\217\t\217\000\238\t\217\t\217\006\149\t\217\t\217\t\217\000\238\t\217\t\217\t\217\t\217\004A\t\217\007\222\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\006\149\007\030\018\214\t\217\000\238\t\217\t\217\t\217\t\217\t\217\005\217\t\217\t\217\001\206\t\217\012\130\t\217\t\217\t\217\0152\016\146\t\217\t\217\t\217\t\217\t\217\t\217\t\217\000\238\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\026N\t\217\t\217\007\138\t\217\t\217\r\002\003j\003\018\004A\t\217\t\217\t\217\t\217\t\217\002v\t\217\t\217\t\217\t\217\t\217\000\238\t\217\t\217\004B\t\217\t\217\003n\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\t\217\000\238\004A\t\217\t\217\t\217\t\217\t\209\t\209\004\242\001f\003i\t\209\007\005\t\209\t\209\025.\t\209\t\209\t\209\t\209\003\158\t\209\t\209\003\162\t\209\t\209\t\209\003\137\t\209\t\209\t\209\t\209\b\241\t\209\004^\t\209\t\209\t\209\t\209\t\209\t\209\t\209\t\209\007\222\026R\015\162\t\209\001\206\t\209\t\209\t\209\t\209\t\209\005\209\t\209\t\209\000\238\t\209\012\154\t\209\t\209\t\209\022\130\011Z\t\209\t\209\t\209\t\209\t\209\t\209\t\209\000\238\t\209\t\209\t\209\t\209\t\209\t\209\t\209\t\209\t\209\t\209\t\209\006\210\t\209\t\209\022\138\t\209\t\209\002\214\004V\007\030\b\241\t\209\t\209\t\209\t\209\t\209\002\142\t\209\t\209\t\209\t\209\t\209\0252\t\209\t\209\b\021\t\209\t\209\025>\t\209\t\209\t\209\t\209\t\209\t\209\t\209\t\209\t\209\t\209\t\209\t\209\t\209\012\185\b\241\t\209\t\209\t\209\t\209\t\225\t\225\021\246\007\138\007\210\t\225\011b\t\225\t\225\006\242\t\225\t\225\t\225\t\225\012\185\t\225\t\225\012\189\t\225\t\225\t\225\000\238\t\225\t\225\t\225\t\225\005F\t\225\004\174\t\225\t\225\t\225\t\225\t\225\t\225\t\225\t\225\012\189\007\030\021\254\t\225\002\190\t\225\t\225\t\225\t\225\t\225\005\209\t\225\t\225\003\022\t\225\012\174\t\225\t\225\t\225\015\138\026\226\t\225\t\225\t\225\t\225\t\225\t\225\t\225\0112\t\225\t\225\t\225\t\225\t\225\t\225\t\225\t\225\t\225\t\225\t\225\017\242\t\225\t\225\007\138\t\225\t\225\003\n\001\206\0116\005J\t\225\t\225\t\225\t\225\t\225\003\026\t\225\t\225\t\225\t\225\t\225\000\238\t\225\t\225\004B\t\225\t\225\002&\t\225\t\225\t\225\t\225\t\225\t\225\t\225\t\225\t\225\t\225\t\225\t\225\t\225\t\190\004\214\t\225\t\225\t\225\t\225\t\193\t\193\000\238\0022\007\222\t\193\t\146\t\193\t\193\005\002\t\193\t\193\t\193\t\193\004V\t\193\t\193\000\238\t\193\t\193\t\193\012.\t\193\t\193\t\193\t\193\t\150\t\193\007\154\t\193\t\193\t\193\t\193\t\193\t\193\t\193\t\193\006F\t\001\n\162\t\193\0122\t\193\t\193\t\193\t\193\t\193\011N\t\193\t\193\007\158\t\193\012\206\t\193\t\193\t\193\004b\014\254\t\193\t\193\t\193\t\193\t\193\t\193\t\193\b\134\t\193\t\193\t\193\t\193\t\193\t\193\t\193\t\193\t\193\t\193\t\193\006\242\t\193\t\193\014\226\t\193\t\193\006\170\006\194\001\002\001\190\t\193\t\193\t\193\t\193\t\193\001\222\t\193\t\193\t\193\t\193\t\193\006U\t\193\t\193\000\238\t\193\t\193\005.\t\193\t\193\t\193\t\193\t\193\t\193\t\193\t\193\t\193\t\193\t\193\t\193\t\193\006U\t\001\t\193\t\193\t\193\t\193\t\201\t\201\003\134\003\138\006\242\t\201\012\006\t\201\t\201\027\139\t\201\t\201\t\201\t\201\018B\t\201\t\201\016\218\t\201\t\201\t\201\012z\t\201\t\201\t\201\t\201\001v\t\201\012\n\t\201\t\201\t\201\t\201\t\201\t\201\t\201\t\201\011\202\006\202\016F\t\201\012~\t\201\t\201\t\201\t\201\t\201\0186\t\201\t\201\014\230\t\201\012\226\t\201\t\201\t\201\018\218\t\146\t\201\t\201\t\201\t\201\t\201\t\201\t\201\018B\t\201\t\201\t\201\t\201\t\201\t\201\t\201\t\201\t\201\t\201\t\201\012\202\t\201\t\201\b\193\t\201\t\201\006\026\012.\001\002\001\190\t\201\t\201\t\201\t\201\t\201\003\022\t\201\t\201\t\201\t\201\t\201\006]\t\201\t\201\005\221\t\201\t\201\r\014\t\201\t\201\t\201\t\201\t\201\t\201\t\201\t\201\t\201\t\201\t\201\t\201\t\201\006]\000\238\t\201\t\201\t\201\t\201\n\001\n\001\003\134\017\234\011Z\n\001\012J\n\001\n\001\017\146\n\001\n\001\n\001\n\001\004\014\n\001\n\001\017\254\n\001\n\001\n\001\012z\n\001\n\001\n\001\n\001\001\134\n\001\012N\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\004\018\019\006\b\193\n\001\rf\n\001\n\001\n\001\n\001\n\001\b\189\n\001\n\001\000\238\n\001\012\246\n\001\n\001\n\001\r\134\0142\n\001\n\001\n\001\n\001\n\001\n\001\n\001\004A\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\015\182\n\001\n\001\011j\n\001\n\001\b!\014N\007\158\000\238\n\001\n\001\n\001\n\001\n\001\002\142\n\001\n\001\n\001\n\001\n\001\006e\n\001\n\001\014:\n\001\n\001\014R\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\006e\000\238\n\001\n\001\n\001\n\001\t\241\t\241\027F\001\222\006\174\t\241\b\189\t\241\t\241\000\238\t\241\t\241\t\241\t\241\006\190\t\241\t\241\r\138\t\241\t\241\t\241\006\254\t\241\t\241\t\241\t\241\001\150\t\241\002\253\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\004\210\t\002\011\142\t\241\018\150\t\241\t\241\t\241\t\241\t\241\014\134\t\241\t\241\019>\t\241\r\018\t\241\t\241\t\241\011\018\005&\t\241\t\241\t\241\t\241\t\241\t\241\t\241\021\214\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\b\217\t\241\t\241\n\206\t\241\t\241\n\218\015\014\002\190\022\030\t\241\t\241\t\241\t\241\t\241\018\190\t\241\t\241\t\241\t\241\t\241\004A\t\241\t\241\n\206\t\241\t\241\n\218\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\000\238\012\146\t\241\t\241\t\241\t\241\t\233\t\233\001\002\001\190\014\138\t\233\004\214\t\233\t\233\000\238\t\233\t\233\t\233\t\233\001\206\t\233\t\233\012\150\t\233\t\233\t\233\t\"\t\233\t\233\t\233\t\233\b\237\t\233\000\238\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\0056\b\217\017^\t\233\015\018\t\233\t\233\t\233\t\233\t\233\tj\t\233\t\233\019V\t\233\r&\t\233\t\233\t\233\002\154\005>\t\233\t\233\t\233\t\233\t\233\t\233\t\233\023\174\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\003\022\t\233\t\233\015\198\t\233\t\233\023\022\003}\023\178\0266\t\233\t\233\t\233\t\233\t\233\011Z\t\233\t\233\t\233\t\233\t\233\000\238\t\233\t\233\tr\t\233\t\233\012Z\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\001\002\001\190\t\233\t\233\t\233\t\233\t\249\t\249\022\002\012^\019\158\t\249\004\214\t\249\t\249\019^\t\249\t\249\t\249\t\249\012Z\t\249\t\249\012\006\t\249\t\249\t\249\t\130\t\249\t\249\t\249\t\249\004\214\t\249\012J\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\r6\022\142\012\222\t\249\019\026\t\249\t\249\t\249\t\249\t\249\005\213\t\249\t\249\r\"\t\249\r:\t\249\t\249\t\249\023J\014\190\t\249\t\249\t\249\t\249\t\249\t\249\t\249\018\254\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\018\210\t\249\t\249\014\194\t\249\t\249\b\025\021\250\005\225\b%\t\249\t\249\t\249\t\249\t\249\r!\t\249\t\249\t\249\t\249\t\249\n\186\t\249\t\249\n\162\t\249\t\249\012\146\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\n\242\014v\t\249\t\249\t\249\t\249\nI\nI\rr\014\238\019\178\nI\014b\nI\nI\000\238\nI\nI\nI\nI\019J\nI\nI\014z\nI\nI\nI\025\250\nI\nI\nI\nI\014\242\nI\015\026\nI\nI\nI\nI\nI\nI\nI\nI\007n\007\241\022^\nI\004B\nI\nI\nI\nI\nI\023.\nI\nI\015\030\nI\rF\nI\nI\nI\011\022\019\130\nI\nI\nI\nI\nI\nI\nI\022>\nI\nI\nI\nI\nI\nI\nI\nI\nI\nI\nI\000\238\nI\nI\007n\nI\nI\022\134\004\213\024\246\b\021\nI\nI\nI\nI\nI\027B\nI\nI\nI\nI\nI\019\182\nI\nI\011F\nI\nI\r-\nI\nI\nI\nI\nI\nI\nI\nI\nI\nI\nI\nI\nI\023\"\014f\nI\nI\nI\nI\003\157\003\157\000\238\023\130\023\238\003\157\019^\003\157\003\157\000\238\003\157\003\157\003\157\003\157\025\018\003\157\003\157\007n\003\157\003\157\003\157\011v\003\157\003\157\003\157\003\157\007n\003\157\012\170\003\157\003\157\003\157\003\157\003\157\003\157\003\157\003\157\r~\001\206\022\190\003\157\0262\003\157\003\157\003\157\003\157\003\157\024\206\003\157\003\157\001\206\003\157\r\150\003\157\003\157\003\157\025\002\r\158\003\157\003\157\003\157\003\157\003\157\003\157\003\157\r\178\003\157\003\157\003\157\003\157\003\157\003\157\003\157\003\157\003\157\003\157\003\157\026\214\tN\t~\025\198\003\157\003\157\r\226\014\014\015f\002\006\003\157\003\157\003\157\003\157\003\157\026\170\003\157\003\157\003\157\003\157\tV\023\242\t\134\003\157\015\142\003\157\003\157\003\254\003\157\003\157\003\157\003\157\003\157\003\157\003\157\003\157\003\157\003\157\003\157\003\157\003\157\015\170\003\157\003\157\003\157\003\157\003\157\001\237\001\237\026B\025\022\001\222\001\237\015\174\002\190\001\237\015\214\002\130\001\237\tf\001\237\004Y\002\246\001\237\024\210\001\237\001\237\001\237\015\234\001\237\001\237\001\237\001\210\025\006\tn\016\002\002\250\001\237\001\237\001\237\001\237\001\237\tv\001\237\016\022\016B\016V\002\254\017V\001\237\001\237\001\237\001\237\001\237\026\218\0032\001\190\017b\001\237\006\022\001\237\001\237\002\178\002\226\018\006\003:\001\237\001\237\001\237\b\026\b\030\b*\018\030\012f\005v\001\237\001\237\001\237\001\237\001\237\001\237\001\237\001\237\001\237\018\166\tN\t~\018\170\001\237\001\237\018\226\018\230\019\014\019\018\005\130\005\134\001\237\001\237\001\237\019:\001\237\001\237\001\237\001\237\012n\019\230\012\190\001\237\019\234\001\237\001\237\020\014\001\237\001\237\001\237\001\237\001\237\001\237\005\138\b2\001\237\001\237\001\237\bJ\004r\020\018\020\"\001\237\001\237\001\237\001\237\n1\n1\0202\020>\020r\n1\020v\002\190\n1\020\194\002\130\n1\n1\n1\020\234\002\246\n1\020\238\n1\n1\n1\020\254\n1\n1\n1\001\210\021N\n1\021n\002\250\n1\n1\n1\n1\n1\n1\n1\021\174\021\210\021\226\002\254\022\n\n1\n1\n1\n1\n1\022\014\0032\001\190\022\026\n1\022*\n1\n1\002\178\022F\022V\003:\n1\n1\n1\b\026\b\030\b*\022j\n1\005v\n1\n1\n1\n1\n1\n1\n1\n1\n1\022\150\n1\n1\022\154\n1\n1\022\166\022\182\022\202\023\190\005\130\005\134\n1\n1\n1\024\022\n1\n1\n1\n1\n1\024>\n1\n1\024\166\n1\n1\024\182\n1\n1\n1\n1\n1\n1\005\138\b2\n1\n1\n1\bJ\004r\025R\025Z\n1\n1\n1\n1\n-\n-\025j\025v\025\218\n-\025\238\002\190\n-\026\030\002\130\n-\n-\n-\026&\002\246\n-\026b\n-\n-\n-\026\138\n-\n-\n-\001\210\026\194\n-\026\242\002\250\n-\n-\n-\n-\n-\n-\n-\026\254\027\006\027\015\002\254\027\031\n-\n-\n-\n-\n-\0272\0032\001\190\027N\n-\027k\n-\n-\002\178\027{\027\151\003:\n-\n-\n-\b\026\b\030\b*\027\203\n-\005v\n-\n-\n-\n-\n-\n-\n-\n-\n-\027\231\n-\n-\027\242\n-\n-\028'\028;\028C\028\127\005\130\005\134\n-\n-\n-\028\135\n-\n-\n-\n-\n-\000\000\n-\n-\000\000\n-\n-\000\000\n-\n-\n-\n-\n-\n-\005\138\b2\n-\n-\n-\bJ\004r\000\000\000\000\n-\n-\n-\n-\0029\0029\000\000\000\000\000\000\0029\000\000\002\190\0029\000\000\002\130\0029\tf\0029\000\000\002\246\0029\000\000\0029\0029\0029\000\000\0029\0029\0029\001\210\002\225\tn\000\000\002\250\0029\0029\0029\0029\0029\tv\0029\000\000\000\000\000\000\002\254\004A\0029\0029\0029\0029\0029\000\000\0032\001\190\000\000\0029\000\n\0029\0029\002\178\000\000\000\000\003:\0029\0029\0029\b\026\b\030\b*\000\000\012f\005v\0029\0029\0029\0029\0029\0029\0029\0029\0029\000\000\004\173\0029\002\225\0029\0029\004A\006\130\002\190\004A\005\130\005\134\0029\0029\0029\000\000\0029\0029\0029\0029\000\000\000\238\004A\0029\004\173\0029\0029\004A\0029\0029\0029\0029\0029\0029\005\138\b2\0029\0029\0029\bJ\004r\000\000\004A\0029\0029\0029\0029\004A\007\030\004A\003\n\004A\004A\004A\004A\004A\004A\004A\017\186\004A\000\238\004A\004A\000\000\004A\004A\004A\016\134\004A\004A\004A\004A\004A\004A\004A\004A\004A\000\000\004A\004A\000\000\000\000\004A\004A\000\238\004A\004A\004A\004A\004A\007\138\004A\004A\004A\004A\004A\004A\004A\004A\000\238\004A\004A\004A\004A\004A\004A\004A\004A\000\238\004A\004A\004A\004A\004A\004A\004A\004A\b\189\004N\004A\000\000\000\000\004A\004A\004A\000\238\004A\000\n\000\000\004A\004A\004A\004A\004A\004A\004A\004A\004A\000\000\021\198\004A\004A\002\225\002\225\007f\004A\004B\006\233\000\000\004A\004A\000\000\007n\016\138\0226\002\225\000\238\004A\004A\004A\007r\000\000\004A\004A\004A\004A\006\233\000\161\004A\000\161\006\233\000\161\000\161\000\161\000\161\000\161\000\161\000\161\000\000\000\161\022\234\000\161\000\161\000\000\000\161\000\161\000\000\000\000\000\161\000\161\000\000\000\161\000\161\000\161\000\161\000\000\000\161\004R\000\161\000\161\b\189\000\000\000\161\000\161\005\141\000\161\000\161\000\161\000\238\000\161\b\241\000\161\000\161\000\161\000\161\000\161\000\161\000\161\000\161\000\000\b\138\000\161\000\161\000\000\000\000\000\161\000\161\002\006\000\161\000\161\000\161\000\161\000\161\000\161\000\161\000\161\000\161\002\n\006\233\000\161\015\130\t\029\000\161\002\130\000\161\001\210\000\161\005\141\002\190\000\000\000\161\000\161\000\161\000\161\000\161\000\161\000\161\000\161\000\000\000\000\000\000\000\161\003\154\017\238\t\029\005\141\000\222\000\000\007\002\001\222\000\161\000\000\002\226\000\000\014\150\002\178\000\161\000\161\000\161\000\161\000\000\015\134\000\161\000\161\000\161\000\161\002)\002)\004Y\000\000\003\n\002)\000\000\002\190\002)\015\146\002\130\002)\001b\002)\000\000\002\246\002)\007\006\002)\002)\002)\000\000\002)\002)\002)\001\210\001z\000\000\001\138\002\250\002)\002)\002)\002)\002)\005\134\002)\000\000\000\000\000\000\002\254\b\169\002)\002)\002)\002)\002)\004Y\0032\b.\000\000\002)\000\000\002)\002)\002\178\000\000\006\"\003:\002)\002)\002)\b\026\b\030\b*\tN\t~\005v\002)\002)\002)\002)\002)\002)\002)\002)\002)\006&\tN\t~\b\169\002)\002)\000\000\tV\000\000\t\134\005\130\005\134\002)\002)\002)\000\000\002)\002)\002)\002)\tV\000\000\t\134\002)\b\169\002)\002)\000\000\002)\002)\002)\002)\002)\002)\005\138\b2\002)\002)\002)\bJ\004r\000\238\002\225\002)\002)\002)\002)\002E\002E\002\225\002\225\000\000\002E\000\000\000\000\002E\000\000\b\169\002E\000\000\002E\004\254\000\000\002E\b\169\002E\002E\002E\000\n\002E\002E\002E\000\000\027\215\000\000\000\000\000\n\002E\002E\002E\002E\002E\000\000\002E\002\225\006*\004\169\000\000\005\234\002E\002E\002E\002E\002E\000\000\0066\002\225\000\000\002E\006B\002E\002E\000\000\000\000\002\225\006~\002E\002E\002E\004\169\000\000\006\213\t\025\000\000\000\000\002E\002E\002E\002E\002E\002E\002E\002E\002E\000\000\tN\t~\000\000\002E\002E\006\134\014\174\000\000\002\190\006\213\t\025\002E\002E\002E\000\000\002E\002E\002E\002E\tV\002\190\t\134\002E\002\130\002E\002E\001\210\002E\002E\002E\002E\002E\002E\b\165\000\000\002E\002E\002E\000\000\021\182\000\000\000\000\002E\002E\002E\002E\002A\002A\000\000\022\242\003\n\002A\022\246\003\022\002A\000\000\002\178\002A\000\000\002A\000\000\017\134\002A\023&\002A\002A\002A\tZ\002A\002A\002A\012&\b\165\000\000\000\000\015\146\002A\002A\002A\002A\002A\rj\002A\rv\000\000\012B\0236\012R\002A\002A\002A\002A\002A\b\165\bf\001\190\001*\002A\000\000\002A\002A\005\134\002\225\002\225\014V\002A\002A\002A\014j\014~\014\142\000\000\000\000\000\000\002A\002A\002A\002A\002A\002A\002A\002A\002A\000\000\tN\t~\b\165\002A\002A\000\n\004\254\000\000\001\206\b\165\000\000\002A\002A\002A\000\000\002A\002A\002A\002A\tV\000\000\t\134\002A\000\000\002A\002A\001\210\002A\002A\002A\002A\002A\002A\002\225\000\000\002A\002A\002A\000\000\018\174\000\000\000\000\002A\002A\002A\002A\002-\002-\000\000\000\000\002\154\002-\0196\003\022\002-\000\000\002\178\002-\000\000\002-\000\000\000\000\002-\019N\002-\002-\002-\012r\002-\002-\002-\002\225\002\225\016\178\000\000\000\000\002-\002-\002-\002-\002-\012\138\002-\012\162\000\000\000\000\002\225\r\006\002-\002-\002-\002-\002-\000\000\bf\014\206\000\000\002-\000\n\002-\002-\r\026\000\000\r.\014V\002-\002-\002-\014j\014~\014\142\000\000\000\000\000\000\002-\002-\002-\002-\002-\002-\002-\002-\002-\000\000\tN\t~\002\225\002-\002-\000\000\000\000\000\000\000\000\000\238\000\000\002-\002-\002-\000\000\002-\002-\002-\002-\tV\000\000\t\134\002-\000\000\002-\002-\000\000\002-\002-\002-\002-\002-\002-\000\000\000\000\002-\002-\002-\000\000\t:\000\000\000\000\002-\002-\002-\002-\002=\002=\000\000\000\000\000\000\002=\012}\006*\002=\000\000\005\234\002=\000\000\002=\000\000\000\000\002=\0066\002=\002=\002=\006B\002=\002=\002=\012}\012}\000\000\000\000\012}\002=\002=\002=\002=\002=\000\000\002=\b\021\000\000\000\000\b\021\000\000\002=\002=\002=\002=\002=\000\000\000\000\000\000\000\000\002=\000\000\002=\002=\000\000\000\000\000\000\022>\002=\002=\002=\000\000\000\000\000\000\000\000\000\000\000\238\002=\002=\002=\002=\002=\002=\002=\002=\002=\000\000\b\021\002=\000\000\002=\002=\000\000\000\000\000\000\000\000\000\000\000\000\002=\002=\002=\b\021\002=\002=\002=\002=\012}\000\000\004\253\002=\000\000\002=\002=\002\225\t\158\002=\002=\002=\002=\002=\004\253\n\230\002=\002=\002=\000\000\000\000\b\021\000\000\002=\002=\002=\002=\t%\t%\000\000\000\000\000\000\t%\000\000\000\000\t%\000\n\000\000\t%\000\000\t%\000\000\000\000\t\202\004\253\t%\t\238\t%\b\021\t%\t%\t%\002\225\000\000\000\000\000\000\017\"\n\002\n\026\n\"\n\n\n*\000\000\t%\002\225\002\225\000\000\000\000\000\000\t%\t%\n2\n:\t%\004\253\007\245\000\000\004\253\t%\000\000\nB\t%\000\000\000\000\000\000\000\000\t%\t%\000\238\000\000\000\000\000\000\000\000\000\000\002\246\t%\t%\t\210\n\018\nJ\nR\nb\t%\t%\002\166\012\193\t%\000\000\t%\nj\000\000\003Z\000\000\000\000\000\238\000\000\t%\t%\nr\000\000\t%\t%\t%\t%\003f\012\193\000\000\t%\000\000\t%\t%\002B\n\146\t%\n\154\nZ\t%\t%\000\000\000\000\t%\nz\t%\000\000\002F\000\000\005v\t%\t%\n\130\n\138\002q\002q\000\000\000\000\000\000\002q\012\133\006*\002q\000\000\005\234\002q\000\000\002q\000\000\005\130\002q\0066\002q\002q\002q\006B\002q\002q\002q\012\133\012\133\000\000\000\000\012\133\002q\002q\002q\002q\002q\000\000\002q\015\130\000\000\005\138\002\130\000\000\002q\002q\002q\002q\002q\000\000\000\000\000\000\000\000\002q\000\000\002q\002q\000\000\000\000\000\000\000\000\002q\002q\002q\000\000\000\000\000\000\000\000\000\000\000\238\002q\002q\t\210\002q\002q\002q\002q\002q\002q\000\000\015\134\002q\000\000\002q\002q\000\000\000\000\000\000\000\000\000\000\000\000\002q\002q\002q\015\146\002q\002q\002q\002q\012\133\000\000\001\206\002q\000\000\002q\002q\000\000\002q\002q\002q\002q\002q\002q\026\014\000\000\002q\002q\002q\000\000\000\000\005\134\000\000\002q\002q\002q\002q\002Y\002Y\000\000\000\000\000\000\002Y\000\000\002\190\002Y\000\000\000\000\002Y\000\000\002Y\003\170\000\000\002Y\002\154\002Y\002Y\002Y\025~\002Y\002Y\002Y\001\210\000\000\000\000\000\000\000\000\002Y\002Y\002Y\002Y\002Y\000\000\002Y\015\130\000\000\000\000\002\130\000\000\002Y\002Y\002Y\002Y\002Y\004\154\003\202\000\000\004\217\002Y\000\000\002Y\002Y\002\178\000\000\000\000\000\000\002Y\002Y\002Y\000\000\000\000\000\000\000\000\000\000\000\000\002Y\002Y\t\210\002Y\002Y\002Y\002Y\002Y\002Y\000\000\015\134\002Y\000\000\002Y\002Y\006\234\000\000\000\000\000\000\000\000\000\000\002Y\002Y\002Y\015\146\002Y\002Y\002Y\002Y\000\000\000\000\000\000\002Y\000\000\002Y\002Y\000\000\002Y\002Y\002Y\002Y\002Y\002Y\012\129\000\000\002Y\002Y\002Y\000\000\000\000\005\134\000\000\002Y\002Y\002Y\002Y\002e\002e\000\000\000\000\000\000\002e\012\129\012\129\002e\000\000\012\129\002e\000\000\002e\000\000\000\000\t\202\000\000\002e\002e\002e\021\026\002e\002e\002e\000\000\000\000\000\000\000\000\000\000\002e\002e\002e\n\n\002e\000\000\002e\000\000\000\000\000\000\000\000\000\000\002e\002e\002e\002e\002e\000\000\000\238\000\000\000\000\002e\000\000\002e\002e\000\000\000\000\000\000\000\000\002e\002e\002e\000\000\000\000\000\000\000\000\000\000\000\000\002e\002e\t\210\n\018\002e\002e\002e\002e\002e\000\000\012\129\002e\000\000\002e\002e\000\000\000\000\000\000\000\000\000\238\b\t\002e\002e\002e\b\t\002e\002e\002e\002e\000\000\000\000\000\000\002e\000\000\002e\002e\000\000\002e\002e\002e\002e\002e\002e\000\000\000\000\002e\002e\002e\000\000\011\154\000\000\000\000\002e\002e\002e\002e\002u\002u\000\000\000\000\000\000\002u\b\t\011\162\002u\000\000\011\174\002u\000\000\002u\000\000\000\000\002u\011\186\002u\002u\002u\011\198\002u\002u\002u\000\000\000\000\b\t\000\000\000\000\002u\002u\002u\002u\002u\000\000\002u\000\000\000\000\000\000\000\000\000\000\002u\002u\002u\002u\002u\000\000\000\000\000\000\000\000\002u\000\000\002u\002u\000\000\000\000\000\000\000\000\002u\002u\002u\000\000\000\000\004\254\000\000\000\000\000\000\002u\002u\t\210\002u\002u\002u\002u\002u\002u\000\000\007\234\002u\000\000\002u\002u\000\000\000\000\000\000\000\000\000\238\b\005\002u\002u\002u\b\005\002u\002u\002u\002u\000\000\007\238\000\000\002u\000\000\002u\002u\000\000\002u\002u\002u\002u\002u\002u\000\000\000\000\002u\002u\002u\000\000\007\165\000\000\000\000\002u\002u\002u\002u\002U\002U\007\222\000\000\000\000\002U\b\005\007\165\002U\000\000\005\234\002U\000\000\002U\000\000\000\238\002U\007\165\002U\002U\002U\007\165\002U\002U\002U\000\000\000\000\b\005\000\000\000\000\002U\002U\002U\002U\002U\000\000\002U\000\000\000\000\006\253\000\000\000\000\002U\002U\002U\002U\002U\000\000\000\000\000\000\000\000\002U\000\000\002U\002U\000\000\000\000\000\000\006\253\002U\002U\002U\006\253\007\242\004\254\000\000\000\000\000\000\002U\002U\t\210\002U\002U\002U\002U\002U\002U\000\000\000\000\002U\000\000\002U\002U\000\000\000\000\000\000\000\000\007\189\000\000\002U\002U\002U\000\000\002U\002U\002U\002U\000\000\000\000\000\000\002U\000\000\002U\002U\000\000\002U\002U\002U\002U\002U\002U\000\000\000\000\002U\002U\002U\000\000\007\189\000\000\000\000\002U\002U\002U\002U\002a\002a\000\000\000\000\000\000\002a\005f\007\189\002a\000\000\005\234\002a\000\000\002a\000\000\000\000\t\202\007\189\002a\002a\002a\007\189\002a\002a\002a\000\000\000\000\000\000\000\000\000\000\002a\002a\002a\n\n\002a\000\000\002a\000\000\000\000\006\237\000\000\000\000\002a\002a\002a\002a\002a\000\000\000\000\000\000\000\000\002a\000\000\002a\002a\000\000\000\000\000\000\006\237\002a\002a\002a\006\237\000\000\000\000\000\000\000\000\000\000\002a\002a\t\210\n\018\002a\002a\002a\002a\002a\000\000\000\000\002a\000\000\002a\002a\000\000\000\000\000\000\000\000\000\238\000\000\002a\002a\002a\000\000\002a\002a\002a\002a\000\000\000\000\000\000\002a\000\000\002a\002a\000\000\002a\002a\002a\002a\002a\002a\000\000\000\000\002a\002a\002a\000\000\007\217\000\000\000\000\002a\002a\002a\002a\002]\002]\000\000\000\000\000\000\002]\b&\006*\002]\000\000\005\234\002]\000\000\002]\000\000\000\000\t\202\007\217\002]\002]\002]\007\217\002]\002]\002]\000\000\000\000\000\000\000\000\000\000\002]\002]\002]\n\n\002]\000\000\002]\000\000\000\000\000\000\000\000\000\000\002]\002]\002]\002]\002]\000\000\000\000\000\000\000\000\002]\000\000\002]\002]\000\000\000\000\000\000\000\000\002]\002]\002]\000\000\000\000\000\000\000\000\000\000\000\000\002]\002]\t\210\n\018\002]\002]\002]\002]\002]\000\000\000\000\002]\000\000\002]\002]\000\000\000\000\000\000\000\000\007\209\000\000\002]\002]\002]\000\000\002]\002]\002]\002]\000\000\000\000\000\000\002]\000\000\002]\002]\000\000\002]\002]\002]\002]\002]\002]\000\000\000\000\002]\002]\002]\000\000\007\209\000\000\000\000\002]\002]\002]\002]\002\133\002\133\000\000\000\000\000\000\002\133\000\000\011\222\002\133\000\000\007\209\002\133\000\000\002\133\000\000\000\000\t\202\007\209\002\133\002\133\002\133\007\209\002\133\002\133\002\133\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\133\000\000\000\000\000\000\000\000\000\000\002\133\002\133\n2\n:\002\133\000\000\000\000\000\000\000\000\002\133\000\000\nB\002\133\000\000\000\000\000\000\000\000\002\133\002\133\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\133\002\133\t\210\n\018\nJ\nR\nb\002\133\002\133\000\000\000\000\002\133\000\000\002\133\nj\000\000\000\000\000\000\000\000\000\238\000\000\002\133\002\133\nr\000\000\002\133\002\133\002\133\002\133\000\000\000\000\000\000\002\133\000\000\002\133\002\133\000\000\002\133\002\133\002\133\nZ\002\133\002\133\000\000\000\000\002\133\nz\002\133\000\000\007\161\000\000\000\000\002\133\002\133\n\130\n\138\002m\002m\000\000\000\000\000\000\002m\000\000\007\161\002m\000\000\005\234\002m\000\000\002m\000\000\000\000\t\202\007\161\002m\002m\002m\007\161\002m\002m\002m\000\000\000\000\000\000\000\000\000\000\002m\002m\002m\n\n\002m\000\000\002m\000\000\000\000\000\000\000\000\000\000\002m\002m\002m\002m\002m\000\000\000\000\000\000\000\000\002m\000\000\002m\002m\000\000\000\000\000\000\000\000\002m\002m\002m\000\000\000\000\000\000\000\000\000\000\000\000\002m\002m\t\210\n\018\002m\002m\002m\002m\002m\000\000\000\000\002m\000\000\002m\002m\000\000\000\000\000\000\000\000\000\238\000\000\002m\002m\002m\000\000\002m\002m\002m\002m\000\000\000\000\000\000\002m\000\000\002m\002m\000\000\002m\002m\002m\002m\002m\002m\000\000\000\000\002m\002m\002m\000\000\014&\000\000\000\000\002m\002m\002m\002m\002i\002i\000\000\000\000\000\000\002i\000\000\011\162\002i\000\000\011\174\002i\000\000\002i\000\000\000\000\t\202\011\186\002i\002i\002i\011\198\002i\002i\002i\000\000\000\000\000\000\000\000\000\000\002i\002i\002i\n\n\002i\000\000\002i\000\000\000\000\000\000\000\000\000\000\002i\002i\002i\002i\002i\000\000\000\000\000\000\000\000\002i\000\000\002i\002i\000\000\000\000\000\000\000\000\002i\002i\002i\000\000\000\000\000\000\000\000\000\000\000\000\002i\002i\t\210\n\018\002i\002i\002i\002i\002i\000\000\000\000\002i\000\000\002i\002i\000\000\000\000\000\000\000\000\000\000\000\000\002i\002i\002i\000\000\002i\002i\002i\002i\000\000\000\000\000\000\002i\000\000\002i\002i\000\000\002i\002i\002i\002i\002i\002i\000\000\000\000\002i\002i\002i\000\000\000\000\000\000\000\000\002i\002i\002i\002i\002}\002}\000\000\000\000\000\000\002}\000\000\002\006\002}\000\000\002\130\002}\000\000\002}\000\000\000\000\t\202\000\000\002}\002}\002}\000\000\002}\002}\002}\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\002}\000\000\002}\000\000\000\000\000\000\000\000\000\000\002}\002}\n2\n:\002}\000\000\027*\001\222\000\000\002}\000\000\002}\002}\000\000\000\000\000\000\000\000\002}\002}\000\238\015\146\000\000\000\000\000\000\000\000\000\000\002}\002}\t\210\n\018\nJ\nR\002}\002}\002}\000\000\000\000\002}\000\000\002}\002}\000\000\000\000\000\000\000\000\000\000\005\134\002}\002}\002}\000\000\002}\002}\002}\002}\000\000\000\000\000\000\002}\000\000\002}\002}\000\000\002}\002}\002}\nZ\002}\002}\000\000\000\000\002}\002}\002}\000\000\000\000\000\000\000\000\002}\002}\002}\002}\002Q\002Q\000\000\000\000\000\000\002Q\000\000\003\022\002Q\000\000\000\000\002Q\000\000\002Q\000\000\000\000\t\202\000\000\002Q\002Q\002Q\000\000\002Q\002Q\002Q\000\000\000\000\000\000\000\000\000\000\002Q\002Q\002Q\n\n\002Q\000\000\002Q\000\000\000\000\000\000\000\000\000\000\002Q\002Q\002Q\002Q\002Q\000\000\005\190\000\000\000\000\002Q\000\000\002Q\002Q\000\000\000\000\000\000\003\246\002Q\002Q\002Q\006N\000\000\004\002\000\000\000\000\000\000\002Q\002Q\t\210\n\018\002Q\002Q\002Q\002Q\002Q\000\000\000\000\002Q\000\000\002Q\002Q\000\000\000\000\000\000\000\000\000\000\000\000\002Q\002Q\002Q\000\000\002Q\002Q\002Q\002Q\000\000\000\000\000\000\002Q\000\000\002Q\002Q\000\000\002Q\002Q\002Q\002Q\002Q\002Q\000\000\000\000\002Q\002Q\002Q\000\000\000\000\000\000\000\000\002Q\002Q\002Q\002Q\002M\002M\000\000\000\000\000\000\002M\000\000\002\190\002M\000\000\000\000\002M\000\000\002M\000\000\000\000\t\202\000\000\002M\002M\002M\000\000\002M\002M\002M\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\002M\000\000\002M\000\000\000\000\000\000\000\000\000\000\002M\002M\n2\n:\002M\000\000\t\138\003\n\000\000\002M\000\000\002M\002M\000\000\000\000\000\000\000\000\002M\002M\000\238\011\254\000\000\012\014\000\000\000\000\000\000\002M\002M\t\210\n\018\nJ\nR\002M\002M\002M\000\000\000\000\002M\000\000\002M\002M\000\000\000\000\000\000\000\000\000\000\000\000\002M\002M\002M\000\000\002M\002M\002M\002M\000\000\000\000\000\000\002M\000\000\002M\002M\000\000\002M\002M\002M\nZ\002M\002M\000\000\000\000\002M\002M\002M\000\000\000\000\000\000\000\000\002M\002M\002M\002M\002\169\002\169\000\000\000\000\000\000\002\169\000\000\002\190\002\169\000\000\000\000\002\169\000\000\002\169\000\000\000\000\t\202\000\000\002\169\002\169\002\169\000\000\002\169\002\169\002\169\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\002\169\000\000\002\169\000\000\000\000\000\000\000\000\000\000\002\169\002\169\n2\n:\002\169\000\000\012\194\003\n\000\000\002\169\000\000\002\169\002\169\000\000\000\000\000\000\000\000\002\169\002\169\002\169\012\214\000\000\012\234\000\000\000\000\000\000\002\169\002\169\t\210\n\018\nJ\002\169\002\169\002\169\002\169\000\000\000\000\002\169\000\000\002\169\002\169\000\000\000\000\000\000\000\000\000\000\000\000\002\169\002\169\002\169\000\000\002\169\002\169\002\169\002\169\000\000\000\000\000\000\002\169\000\000\002\169\002\169\000\000\002\169\002\169\002\169\nZ\002\169\002\169\000\000\000\000\002\169\002\169\002\169\000\000\000\000\000\000\000\000\002\169\002\169\002\169\002\169\002I\002I\000\000\000\000\000\000\002I\000\000\000\000\002I\000\000\000\000\002I\000\000\002I\000\000\000\000\t\202\000\000\002I\002I\002I\000\000\002I\002I\002I\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\002I\000\000\002I\000\000\000\000\000\000\000\000\000\000\002I\002I\n2\n:\002I\000\000\000\000\000\000\000\000\002I\000\000\002I\002I\000\000\000\000\000\000\000\000\002I\002I\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002I\002I\t\210\n\018\nJ\nR\002I\002I\002I\000\000\000\000\002I\000\000\002I\002I\000\000\000\000\000\000\000\000\000\000\000\000\002I\002I\002I\000\000\002I\002I\002I\002I\000\000\000\000\000\000\002I\000\000\002I\002I\000\000\002I\002I\002I\nZ\002I\002I\000\000\000\000\002I\002I\002I\000\000\000\000\000\000\000\000\002I\002I\002I\002I\002\129\002\129\000\000\000\000\000\000\002\129\000\000\000\000\002\129\000\000\000\000\002\129\000\000\002\129\000\000\000\000\t\202\000\000\002\129\002\129\002\129\000\000\002\129\002\129\002\129\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\002\129\000\000\002\129\000\000\000\000\000\000\000\000\000\000\002\129\002\129\n2\n:\002\129\000\000\000\000\000\000\000\000\002\129\000\000\002\129\002\129\000\000\000\000\000\000\000\000\002\129\002\129\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\129\002\129\t\210\n\018\nJ\nR\002\129\002\129\002\129\000\000\000\000\002\129\000\000\002\129\002\129\000\000\000\000\000\000\000\000\000\000\000\000\002\129\002\129\002\129\000\000\002\129\002\129\002\129\002\129\000\000\000\000\000\000\002\129\000\000\002\129\002\129\000\000\002\129\002\129\002\129\nZ\002\129\002\129\000\000\000\000\002\129\002\129\002\129\000\000\000\000\000\000\000\000\002\129\002\129\002\129\002\129\002y\002y\000\000\000\000\000\000\002y\000\000\000\000\002y\000\000\000\000\002y\000\000\002y\000\000\000\000\t\202\000\000\002y\002y\002y\000\000\002y\002y\002y\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\002y\000\000\002y\000\000\000\000\000\000\000\000\000\000\002y\002y\n2\n:\002y\000\000\000\000\000\000\000\000\002y\000\000\002y\002y\000\000\000\000\000\000\000\000\002y\002y\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002y\002y\t\210\n\018\nJ\nR\002y\002y\002y\000\000\000\000\002y\000\000\002y\002y\000\000\000\000\000\000\000\000\000\000\000\000\002y\002y\002y\000\000\002y\002y\002y\002y\000\000\000\000\000\000\002y\000\000\002y\002y\000\000\002y\002y\002y\nZ\002y\002y\000\000\000\000\002y\002y\002y\000\000\000\000\000\000\000\000\002y\002y\002y\002y\002\137\002\137\000\000\000\000\000\000\002\137\000\000\000\000\002\137\000\000\000\000\002\137\000\000\002\137\000\000\000\000\t\202\000\000\002\137\002\137\002\137\000\000\002\137\002\137\002\137\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\137\000\000\000\000\000\000\000\000\000\000\002\137\002\137\n2\n:\002\137\000\000\000\000\000\000\000\000\002\137\000\000\nB\002\137\000\000\000\000\000\000\000\000\002\137\002\137\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\137\002\137\t\210\n\018\nJ\nR\nb\002\137\002\137\000\000\000\000\002\137\000\000\002\137\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\137\002\137\nr\000\000\002\137\002\137\002\137\002\137\000\000\000\000\000\000\002\137\000\000\002\137\002\137\000\000\002\137\002\137\002\137\nZ\002\137\002\137\000\000\000\000\002\137\nz\002\137\000\000\000\000\000\000\000\000\002\137\002\137\n\130\n\138\002\141\002\141\000\000\000\000\000\000\002\141\000\000\000\000\002\141\000\000\000\000\002\141\000\000\002\141\000\000\000\000\t\202\000\000\002\141\002\141\002\141\000\000\002\141\002\141\002\141\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\002\141\000\000\002\141\000\000\000\000\000\000\000\000\000\000\002\141\002\141\n2\n:\002\141\000\000\000\000\000\000\000\000\002\141\000\000\nB\002\141\000\000\000\000\000\000\000\000\002\141\002\141\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\141\002\141\t\210\n\018\nJ\nR\nb\002\141\002\141\000\000\000\000\002\141\000\000\002\141\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\141\002\141\nr\000\000\002\141\002\141\002\141\002\141\000\000\000\000\000\000\002\141\000\000\002\141\002\141\000\000\002\141\002\141\002\141\nZ\002\141\002\141\000\000\000\000\002\141\002\141\002\141\000\000\000\000\000\000\000\000\002\141\002\141\n\130\n\138\002\145\002\145\000\000\000\000\000\000\002\145\000\000\000\000\002\145\000\000\000\000\002\145\000\000\002\145\000\000\000\000\t\202\000\000\002\145\002\145\002\145\000\000\002\145\002\145\002\145\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\002\145\000\000\002\145\000\000\000\000\000\000\000\000\000\000\002\145\002\145\n2\n:\002\145\000\000\000\000\000\000\000\000\002\145\000\000\nB\002\145\000\000\000\000\000\000\000\000\002\145\002\145\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\145\002\145\t\210\n\018\nJ\nR\nb\002\145\002\145\000\000\000\000\002\145\000\000\002\145\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\145\002\145\nr\000\000\002\145\002\145\002\145\002\145\000\000\000\000\000\000\002\145\000\000\002\145\002\145\000\000\002\145\002\145\002\145\nZ\002\145\002\145\000\000\000\000\002\145\002\145\002\145\000\000\000\000\000\000\000\000\002\145\002\145\n\130\n\138\b\225\b\225\000\000\000\000\000\000\b\225\000\000\000\000\b\225\000\000\000\000\b\225\000\000\b\225\000\000\000\000\t\202\000\000\b\225\b\225\b\225\000\000\b\225\b\225\b\225\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\b\225\000\000\000\000\000\000\000\000\000\000\b\225\b\225\n2\n:\b\225\000\000\000\000\000\000\000\000\b\225\000\000\nB\b\225\000\000\000\000\000\000\000\000\b\225\b\225\000\238\000\000\000\000\000\000\000\000\000\000\000\000\b\225\b\225\t\210\n\018\nJ\nR\nb\b\225\b\225\000\000\000\000\b\225\000\000\b\225\nj\000\000\000\000\000\000\000\000\000\000\000\000\b\225\b\225\nr\000\000\b\225\b\225\b\225\b\225\000\000\000\000\000\000\b\225\000\000\b\225\b\225\000\000\b\225\b\225\b\225\nZ\b\225\b\225\000\000\000\000\b\225\nz\b\225\000\000\000\000\000\000\000\000\b\225\b\225\n\130\n\138\002\149\002\149\000\000\000\000\000\000\002\149\000\000\000\000\002\149\000\000\000\000\002\149\000\000\002\149\000\000\000\000\t\202\000\000\002\149\002\149\002\149\000\000\002\149\002\149\002\149\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\149\000\000\000\000\000\000\000\000\000\000\002\149\002\149\n2\n:\002\149\000\000\000\000\000\000\000\000\002\149\000\000\nB\002\149\000\000\000\000\000\000\000\000\002\149\002\149\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\149\002\149\t\210\n\018\nJ\nR\nb\002\149\002\149\000\000\000\000\002\149\000\000\002\149\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\149\002\149\nr\000\000\002\149\002\149\002\149\002\149\000\000\000\000\000\000\002\149\000\000\002\149\002\149\000\000\n\146\002\149\n\154\nZ\002\149\002\149\000\000\000\000\002\149\nz\002\149\000\000\000\000\000\000\000\000\002\149\002\149\n\130\n\138\b\221\b\221\000\000\000\000\000\000\b\221\000\000\000\000\b\221\000\000\000\000\b\221\000\000\b\221\000\000\000\000\t\202\000\000\b\221\b\221\b\221\000\000\b\221\b\221\b\221\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\b\221\000\000\000\000\000\000\000\000\000\000\b\221\b\221\n2\n:\b\221\000\000\000\000\000\000\000\000\b\221\000\000\nB\b\221\000\000\000\000\000\000\000\000\b\221\b\221\000\238\000\000\000\000\000\000\000\000\000\000\000\000\b\221\b\221\t\210\n\018\nJ\nR\nb\b\221\b\221\000\000\000\000\b\221\000\000\b\221\nj\000\000\000\000\000\000\000\000\000\000\000\000\b\221\b\221\nr\000\000\b\221\b\221\b\221\b\221\000\000\000\000\000\000\b\221\000\000\b\221\b\221\000\000\b\221\b\221\b\221\nZ\b\221\b\221\000\000\000\000\b\221\nz\b\221\000\000\000\000\000\000\000\000\b\221\b\221\n\130\n\138\002\197\002\197\000\000\000\000\000\000\002\197\000\000\000\000\002\197\000\000\000\000\002\197\000\000\002\197\000\000\000\000\t\202\000\000\002\197\002\197\002\197\000\000\002\197\002\197\002\197\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\197\000\000\000\000\000\000\000\000\000\000\002\197\002\197\n2\n:\002\197\000\000\000\000\000\000\000\000\002\197\000\000\nB\002\197\000\000\000\000\000\000\000\000\002\197\002\197\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\197\002\197\t\210\n\018\nJ\nR\nb\002\197\002\197\000\000\000\000\002\197\000\000\002\197\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\197\002\197\nr\000\000\002\197\002\197\002\197\002\197\000\000\000\000\000\000\002\197\000\000\002\197\002\197\000\000\n\146\002\197\n\154\nZ\002\197\002\197\000\000\000\000\002\197\nz\002\197\000\000\000\000\000\000\000\000\002\197\002\197\n\130\n\138\002\193\002\193\000\000\000\000\000\000\002\193\000\000\000\000\002\193\000\000\000\000\002\193\000\000\002\193\000\000\000\000\t\202\000\000\002\193\002\193\002\193\000\000\002\193\002\193\002\193\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\193\000\000\000\000\000\000\000\000\000\000\002\193\002\193\n2\n:\002\193\000\000\000\000\000\000\000\000\002\193\000\000\nB\002\193\000\000\000\000\000\000\000\000\002\193\002\193\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\193\002\193\t\210\n\018\nJ\nR\nb\002\193\002\193\000\000\000\000\002\193\000\000\002\193\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\193\002\193\nr\000\000\002\193\002\193\002\193\002\193\000\000\000\000\000\000\002\193\000\000\002\193\002\193\000\000\n\146\002\193\n\154\nZ\002\193\002\193\000\000\000\000\002\193\nz\002\193\000\000\000\000\000\000\000\000\002\193\002\193\n\130\n\138\002\201\002\201\000\000\000\000\000\000\002\201\000\000\000\000\002\201\000\000\000\000\002\201\000\000\002\201\000\000\000\000\t\202\000\000\002\201\002\201\002\201\000\000\002\201\002\201\002\201\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\201\000\000\000\000\000\000\000\000\000\000\002\201\002\201\n2\n:\002\201\000\000\000\000\000\000\000\000\002\201\000\000\nB\002\201\000\000\000\000\000\000\000\000\002\201\002\201\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\201\002\201\t\210\n\018\nJ\nR\nb\002\201\002\201\000\000\000\000\002\201\000\000\002\201\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\201\002\201\nr\000\000\002\201\002\201\002\201\002\201\000\000\000\000\000\000\002\201\000\000\002\201\002\201\000\000\n\146\002\201\n\154\nZ\002\201\002\201\000\000\000\000\002\201\nz\002\201\000\000\000\000\000\000\000\000\002\201\002\201\n\130\n\138\002\181\002\181\000\000\000\000\000\000\002\181\000\000\000\000\002\181\000\000\000\000\002\181\000\000\002\181\000\000\000\000\t\202\000\000\002\181\002\181\002\181\000\000\002\181\002\181\002\181\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\181\000\000\000\000\000\000\000\000\000\000\002\181\002\181\n2\n:\002\181\000\000\000\000\000\000\000\000\002\181\000\000\nB\002\181\000\000\000\000\000\000\000\000\002\181\002\181\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\181\002\181\t\210\n\018\nJ\nR\nb\002\181\002\181\000\000\000\000\002\181\000\000\002\181\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\181\002\181\nr\000\000\002\181\002\181\002\181\002\181\000\000\000\000\000\000\002\181\000\000\002\181\002\181\000\000\n\146\002\181\n\154\nZ\002\181\002\181\000\000\000\000\002\181\nz\002\181\000\000\000\000\000\000\000\000\002\181\002\181\n\130\n\138\002\185\002\185\000\000\000\000\000\000\002\185\000\000\000\000\002\185\000\000\000\000\002\185\000\000\002\185\000\000\000\000\t\202\000\000\002\185\002\185\002\185\000\000\002\185\002\185\002\185\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\185\000\000\000\000\000\000\000\000\000\000\002\185\002\185\n2\n:\002\185\000\000\000\000\000\000\000\000\002\185\000\000\nB\002\185\000\000\000\000\000\000\000\000\002\185\002\185\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\185\002\185\t\210\n\018\nJ\nR\nb\002\185\002\185\000\000\000\000\002\185\000\000\002\185\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\185\002\185\nr\000\000\002\185\002\185\002\185\002\185\000\000\000\000\000\000\002\185\000\000\002\185\002\185\000\000\n\146\002\185\n\154\nZ\002\185\002\185\000\000\000\000\002\185\nz\002\185\000\000\000\000\000\000\000\000\002\185\002\185\n\130\n\138\002\189\002\189\000\000\000\000\000\000\002\189\000\000\000\000\002\189\000\000\000\000\002\189\000\000\002\189\000\000\000\000\t\202\000\000\002\189\002\189\002\189\000\000\002\189\002\189\002\189\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\189\000\000\000\000\000\000\000\000\000\000\002\189\002\189\n2\n:\002\189\000\000\000\000\000\000\000\000\002\189\000\000\nB\002\189\000\000\000\000\000\000\000\000\002\189\002\189\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\189\002\189\t\210\n\018\nJ\nR\nb\002\189\002\189\000\000\000\000\002\189\000\000\002\189\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\189\002\189\nr\000\000\002\189\002\189\002\189\002\189\000\000\000\000\000\000\002\189\000\000\002\189\002\189\000\000\n\146\002\189\n\154\nZ\002\189\002\189\000\000\000\000\002\189\nz\002\189\000\000\000\000\000\000\000\000\002\189\002\189\n\130\n\138\002\209\002\209\000\000\000\000\000\000\002\209\000\000\000\000\002\209\000\000\000\000\002\209\000\000\002\209\000\000\000\000\t\202\000\000\002\209\002\209\002\209\000\000\002\209\002\209\002\209\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\209\000\000\000\000\000\000\000\000\000\000\002\209\002\209\n2\n:\002\209\000\000\000\000\000\000\000\000\002\209\000\000\nB\002\209\000\000\000\000\000\000\000\000\002\209\002\209\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\209\002\209\t\210\n\018\nJ\nR\nb\002\209\002\209\000\000\000\000\002\209\000\000\002\209\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\209\002\209\nr\000\000\002\209\002\209\002\209\002\209\000\000\000\000\000\000\002\209\000\000\002\209\002\209\000\000\n\146\002\209\n\154\nZ\002\209\002\209\000\000\000\000\002\209\nz\002\209\000\000\000\000\000\000\000\000\002\209\002\209\n\130\n\138\002\205\002\205\000\000\000\000\000\000\002\205\000\000\000\000\002\205\000\000\000\000\002\205\000\000\002\205\000\000\000\000\t\202\000\000\002\205\002\205\002\205\000\000\002\205\002\205\002\205\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\205\000\000\000\000\000\000\000\000\000\000\002\205\002\205\n2\n:\002\205\000\000\000\000\000\000\000\000\002\205\000\000\nB\002\205\000\000\000\000\000\000\000\000\002\205\002\205\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\205\002\205\t\210\n\018\nJ\nR\nb\002\205\002\205\000\000\000\000\002\205\000\000\002\205\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\205\002\205\nr\000\000\002\205\002\205\002\205\002\205\000\000\000\000\000\000\002\205\000\000\002\205\002\205\000\000\n\146\002\205\n\154\nZ\002\205\002\205\000\000\000\000\002\205\nz\002\205\000\000\000\000\000\000\000\000\002\205\002\205\n\130\n\138\002\213\002\213\000\000\000\000\000\000\002\213\000\000\000\000\002\213\000\000\000\000\002\213\000\000\002\213\000\000\000\000\t\202\000\000\002\213\002\213\002\213\000\000\002\213\002\213\002\213\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\213\000\000\000\000\000\000\000\000\000\000\002\213\002\213\n2\n:\002\213\000\000\000\000\000\000\000\000\002\213\000\000\nB\002\213\000\000\000\000\000\000\000\000\002\213\002\213\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\213\002\213\t\210\n\018\nJ\nR\nb\002\213\002\213\000\000\000\000\002\213\000\000\002\213\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\213\002\213\nr\000\000\002\213\002\213\002\213\002\213\000\000\000\000\000\000\002\213\000\000\002\213\002\213\000\000\n\146\002\213\n\154\nZ\002\213\002\213\000\000\000\000\002\213\nz\002\213\000\000\000\000\000\000\000\000\002\213\002\213\n\130\n\138\002\177\002\177\000\000\000\000\000\000\002\177\000\000\000\000\002\177\000\000\000\000\002\177\000\000\002\177\000\000\000\000\t\202\000\000\002\177\002\177\002\177\000\000\002\177\002\177\002\177\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\177\000\000\000\000\000\000\000\000\000\000\002\177\002\177\n2\n:\002\177\000\000\000\000\000\000\000\000\002\177\000\000\nB\002\177\000\000\000\000\000\000\000\000\002\177\002\177\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\177\002\177\t\210\n\018\nJ\nR\nb\002\177\002\177\000\000\000\000\002\177\000\000\002\177\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\177\002\177\nr\000\000\002\177\002\177\002\177\002\177\000\000\000\000\000\000\002\177\000\000\002\177\002\177\000\000\n\146\002\177\n\154\nZ\002\177\002\177\000\000\000\000\002\177\nz\002\177\000\000\000\000\000\000\000\000\002\177\002\177\n\130\n\138\002\001\002\001\000\000\000\000\000\000\002\001\000\000\000\000\002\001\000\000\000\000\002\001\000\000\002\001\000\000\000\000\002\001\000\000\002\001\002\001\002\001\000\000\002\001\002\001\002\001\000\000\000\000\000\000\000\000\000\000\002\001\002\001\002\001\002\001\002\001\000\000\002\001\000\000\000\000\000\000\000\000\000\000\002\001\002\001\002\001\002\001\002\001\000\000\000\000\000\000\000\000\002\001\000\000\002\001\002\001\000\000\000\000\000\000\000\000\002\001\002\001\002\001\000\000\000\000\000\000\000\000\000\000\000\000\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\002\001\000\000\000\000\002\001\000\000\002\001\002\001\000\000\000\000\000\000\000\000\000\000\000\000\002\001\002\001\002\001\000\000\002\001\002\001\002\001\002\001\000\000\000\000\000\000\002\001\000\000\002\001\002\001\000\000\002\001\002\001\002\001\002\001\002\001\002\001\000\000\000\000\002\001\002\001\r\254\000\000\000\000\000\000\000\000\002\001\002\001\002\001\002\001\002\029\002\029\000\000\000\000\000\000\002\029\000\000\000\000\002\029\000\000\000\000\002\029\000\000\002\029\000\000\000\000\t\202\000\000\002\029\002\029\002\029\000\000\002\029\002\029\002\029\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\029\000\000\000\000\000\000\000\000\000\000\002\029\002\029\n2\n:\002\029\000\000\000\000\000\000\000\000\002\029\000\000\nB\002\029\000\000\000\000\000\000\000\000\002\029\002\029\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\029\002\029\t\210\n\018\nJ\nR\nb\002\029\002\029\000\000\000\000\002\029\000\000\002\029\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\029\002\029\nr\000\000\002\029\002\029\014\022\002\029\000\000\000\000\000\000\002\029\000\000\002\029\002\029\000\000\n\146\002\029\n\154\nZ\002\029\002\029\000\000\000\000\002\029\nz\002\029\000\000\000\000\000\000\000\000\002\029\002\029\n\130\n\138\002\025\002\025\000\000\000\000\000\000\002\025\000\000\000\000\002\025\000\000\000\000\002\025\000\000\002\025\000\000\000\000\t\202\000\000\002\025\002\025\002\025\000\000\002\025\002\025\002\025\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\025\000\000\000\000\000\000\000\000\000\000\002\025\002\025\n2\n:\002\025\000\000\000\000\000\000\000\000\002\025\000\000\nB\002\025\000\000\000\000\000\000\000\000\002\025\002\025\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\025\002\025\t\210\n\018\nJ\nR\nb\002\025\002\025\000\000\000\000\002\025\000\000\002\025\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\025\002\025\nr\000\000\002\025\002\025\002\025\002\025\000\000\000\000\000\000\002\025\000\000\002\025\002\025\000\000\n\146\002\025\n\154\nZ\002\025\002\025\000\000\000\000\002\025\nz\002\025\000\000\000\000\000\000\000\000\002\025\002\025\n\130\n\138\002\173\002\173\000\000\000\000\000\000\002\173\000\000\000\000\002\173\000\000\000\000\002\173\000\000\002\173\000\000\000\000\t\202\000\000\002\173\002\173\002\173\000\000\002\173\002\173\002\173\000\000\000\000\000\000\000\000\000\000\n\002\n\026\n\"\n\n\n*\000\000\002\173\000\000\000\000\000\000\000\000\000\000\002\173\002\173\n2\n:\002\173\000\000\000\000\000\000\000\000\002\173\000\000\nB\002\173\000\000\000\000\000\000\000\000\002\173\002\173\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\173\002\173\t\210\n\018\nJ\nR\nb\002\173\002\173\000\000\000\000\002\173\000\000\002\173\nj\000\000\000\000\000\000\000\000\000\000\000\000\002\173\002\173\nr\000\000\002\173\002\173\002\173\002\173\000\000\000\000\000\000\002\173\000\000\002\173\002\173\000\000\n\146\002\173\n\154\nZ\002\173\002\173\000\000\000\000\002\173\nz\002\173\000\000\000\000\000\000\000\000\002\173\002\173\n\130\n\138\002\r\002\r\000\000\000\000\000\000\002\r\000\000\000\000\002\r\000\000\000\000\002\r\000\000\002\r\000\000\000\000\002\r\000\000\002\r\002\r\002\r\000\000\002\r\002\r\002\r\000\000\000\000\000\000\000\000\000\000\002\r\002\r\002\r\002\r\002\r\000\000\002\r\000\000\000\000\000\000\000\000\000\000\002\r\002\r\002\r\002\r\002\r\000\000\000\000\000\000\000\000\002\r\000\000\002\r\002\r\000\000\000\000\000\000\000\000\002\r\002\r\002\r\000\000\000\000\000\000\000\000\000\000\000\000\002\r\002\r\002\r\002\r\002\r\002\r\002\r\002\r\002\r\000\000\000\000\002\r\000\000\002\r\002\r\000\000\000\000\000\000\000\000\000\000\000\000\002\r\002\r\002\r\000\000\002\r\002\r\002\r\002\r\000\000\000\000\000\000\002\r\000\000\002\r\002\r\000\000\002\r\002\r\002\r\002\r\002\r\002\r\000\000\000\000\002\r\002\r\r\254\000\000\000\000\000\000\000\000\002\r\002\r\002\r\002\r\002\017\002\017\000\000\000\000\000\000\002\017\000\000\000\000\002\017\000\000\000\000\002\017\000\000\002\017\000\000\000\000\002\017\000\000\002\017\002\017\002\017\000\000\002\017\002\017\002\017\000\000\000\000\000\000\000\000\000\000\002\017\002\017\002\017\002\017\002\017\000\000\002\017\000\000\000\000\000\000\000\000\000\000\002\017\002\017\002\017\002\017\002\017\003\253\000\000\000\000\000\000\002\017\000\000\002\017\002\017\000\000\000\000\000\000\000\000\002\017\002\017\002\017\000\000\000\000\000\000\000\000\000\000\000\000\002\017\002\017\002\017\002\017\002\017\002\017\002\017\002\017\002\017\000\000\000\000\002\017\000\000\002\017\002\017\000\000\000\000\000\000\000\000\000\000\000\238\002\017\002\017\002\017\000\000\002\017\002\017\002\017\002\017\000\000\000\000\000\000\002\017\000\000\002\017\002\017\000\000\002\017\002\017\002\017\002\017\002\017\002\017\000\000\000\000\002\017\002\017\r\254\000\000\000\000\003\253\000\000\002\017\002\017\002\017\002\017\001\006\000\000\000\006\000\000\006\229\000\000\002\186\002\190\006*\002\234\002\130\005\234\b\242\000\000\000\000\002\246\001\n\000\000\0066\000\000\002\142\000\000\006B\006\229\000\000\001\210\003\206\006\229\002\190\0036\001\018\bn\br\001\030\001\"\003\170\000\000\000\000\003F\000\000\002\254\007\226\025\030\000\000\b\150\b\154\001\210\003\222\0032\003\234\b\158\006\214\000\000\001:\000\000\002\178\007\r\000\000\003:\000\000\000\000\000\000\b\026\b\030\b*\b>\000\000\005v\000\000\003\202\001>\001B\001F\001J\001N\007\r\002\178\b\178\001R\007\r\007\001\000\000\001V\000\000\b\190\b\214\t*\005\130\005\134\000\000\000\000\001Z\000\000\000\000\000\000\006\229\000\000\001^\002\225\007\001\000\000\000\000\018\130\007\001\006\234\000\000\000\000\001\154\011\018\000\000\011\030\005\138\b2\004\026\001\158\000\000\014F\004r\t>\001\006\001\166\000\006\001\170\001\174\000\000\002\186\002\190\000\n\002\234\002\130\011\"\000\000\000\000\000\000\002\246\001\n\000\000\000\000\000\000\bj\000\000\000\238\000\000\002\225\001\210\000\000\000\000\007\r\0036\001\018\bn\br\001\030\001\"\000\000\002\225\002\225\003F\000\000\002\254\000\000\bv\n\206\b\150\b\154\n\218\003\222\0032\003\234\b\158\006\214\000\238\001:\000\000\002\178\000\000\000\000\003:\000\000\000\000\000\000\b\026\b\030\b*\b>\006*\005v\000\000\005\234\001>\001B\001F\001J\001N\000\000\0066\b\178\001R\000\000\006B\000\000\001V\000\000\b\190\b\214\t*\005\130\005\134\000\000\000\000\001Z\000\000\000\000\000\000\000\000\006*\001^\000\000\005\234\011&\000\000\000\000\000\000\000\000\000\000\0066\001\154\006\022\000\000\006B\005\138\b2\012\181\001\158\000\000\014F\004r\t>\004m\001\166\000\006\001\170\001\174\000\246\002\186\002\190\002\194\002\234\002\130\000\000\000\000\000\000\012\181\002\246\000\000\002\030\003\178\000\000\002\"\000\000\004m\000\000\003\182\001\210\000\000\017\026\000\000\002\250\000\000\003>\003B\002.\000\000\000\000\003\186\000\000\003F\000\000\002\254\000\000\016\174\000\000\003\214\003\218\000\000\003\222\0032\003\234\003\242\006\214\000\000\000\000\017\018\002\178\000\000\000\000\003:\017*\002:\000\000\b\026\b\030\b*\b>\000\000\005v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0172\000\000\b\178\000\000\t\r\000\000\000\000\000\000\000\000\b\190\b\214\t*\005\130\005\134\017F\017r\000\000\000\000\004m\004m\000\000\000\000\000\000\006f\024\234\000\000\t\r\000\000\000\000\002>\012\181\012\161\000\000\000\000\017\174\021\154\005\138\b2\025\n\000\173\000\000\bJ\004r\t>\000\173\000\000\002\190\000\173\000\000\002\130\012\181\tf\000\000\002\030\002\246\000\000\002\"\000\173\000\000\000\173\000\000\000\173\000\000\000\173\001\210\000\238\tn\000\000\002\250\002.\000\000\000\000\0026\012\161\tv\000\173\000\000\000\000\000\000\002\254\000\000\000\173\000\000\000\000\000\000\000\173\000\000\0032\001\190\015\130\000\173\000\000\002\130\000\173\002\178\000\000\002:\003:\000\173\000\173\000\173\b\026\b\030\b*\000\000\012f\005v\000\173\000\173\006*\021B\000\000\005\234\024\238\000\173\000\000\000\000\t\r\000\173\0066\000\000\000\000\000\000\006B\000\000\000\000\005\130\005\134\000\173\000\173\015\134\000\000\000\173\000\173\000\000\000\000\000\000\000\000\000\000\000\000\002>\000\000\000\173\000\000\015\146\000\000\021f\000\000\000\173\000\173\005\138\b2\000\000\000\000\000\197\bJ\004r\000\000\000\173\000\197\000\173\002\190\000\197\000\000\002\130\000\000\tf\000\000\000\000\002\246\005\134\000\000\000\197\000\000\000\197\000\000\000\197\000\000\000\197\001\210\021r\tn\000\000\002\250\000\000\000\000\000\000\000\000\b\210\tv\000\197\000\000\000\000\000\000\002\254\000\000\000\197\021\006\000\000\000\000\000\197\000\000\0032\001\190\000\000\000\197\000\000\000\000\000\197\002\178\000\000\000\000\003:\000\197\000\197\000\197\b\026\b\030\b*\000\000\012f\005v\000\197\000\197\000\000\000\000\000\000\000\000\r\234\000\197\000\000\000\000\000\000\000\197\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\130\005\134\000\197\000\197\000\000\000\238\000\197\000\197\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\197\000\000\000\000\000\000\000\000\000\000\000\197\000\197\005\138\b2\000\000\000\000\000\000\bJ\004r\000\000\000\197\000\000\000\197\000\014\000\018\000\022\000\026\000\030\000\000\000\"\000&\000*\000.\0002\000\000\0006\000:\006*\000\000\000>\005\234\000\000\000\000\000B\000\000\000\000\000\000\0066\000\000\000\000\000F\006B\000\000\000\000\000\000\000\000\000J\000\000\000N\000R\000V\000Z\000^\000b\000f\000\000\000\000\000\000\000j\000n\000\000\000r\000\000\000v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000z\000\000\000\000\000~\000\130\000\000\000\000\000\000\000\000\000\000\000\134\000\138\000\142\000\000\000\000\000\000\000\000\000\000\000\146\000\150\000\154\000\158\000\000\000\162\000\166\000\170\000\000\000\000\000\000\000\174\000\178\000\182\000\000\000\000\000\000\000\186\000\006\000\190\000\194\000\246\002\186\002\190\002\194\002\234\002\130\000\198\000\000\000\202\000\000\002\246\000\000\000\000\004\141\000\206\000\210\000\000\000\214\000\000\003\182\001\210\000\000\000\000\000\000\002\250\000\000\003>\003B\000\000\000\000\000\000\003\186\000\000\003F\000\000\002\254\000\000\016\174\000\000\003\214\003\218\000\000\003\222\0032\003\234\003\242\006\214\000\000\000\000\017\018\002\178\000\000\000\000\003:\017*\000\000\000\000\b\026\b\030\b*\b>\000\000\005v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0172\000\000\b\178\000\000\027\250\000\000\000\000\000\000\000\000\b\190\b\214\t*\005\130\005\134\017F\017r\000\000\000\006\028\027\014\218\000\246\002\186\002\190\002\194\002\234\002\130\000\000\000\000\000\000\000\000\002\246\000\000\000\000\028J\000\000\021\154\005\138\b2\014Z\003\182\001\210\bJ\004r\t>\002\250\000\000\003>\003B\000\000\000\000\000\000\003\186\000\000\003F\000\000\002\254\000\000\016\174\000\000\003\214\003\218\000\000\003\222\0032\003\234\003\242\006\214\000\000\016n\017\018\002\178\000\000\000\000\003:\017*\002\006\000\000\b\026\b\030\b*\b>\000\000\005v\000\000\000\000\002\n\000\000\000\000\000\000\000\000\0172\000\000\b\178\001\210\027\250\000\000\000\000\000\000\000\000\b\190\b\214\t*\005\130\005\134\017F\017r\000\000\000\000\004\149\000\000\003\154\000\000\000\000\000\000\001\006\000\000\007\002\001\222\000\000\000\000\003V\002\190\t\018\002\178\002\130\021\154\005\138\b2\000\000\002\246\001\n\bJ\004r\t>\002\142\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000\000\001\014\001\018\001\022\003v\001\030\001\"\000\000\000\000\007\006\000\000\000\000\002\225\000\000\003z\002\225\001.\011\014\000\000\000\000\003r\001\190\0016\002\225\000\000\001:\000\000\002\178\000\000\000\000\003\246\000\000\000\000\002\225\003\250\000\000\004\002\005j\000\n\005v\000\000\002\225\001>\001B\001F\001J\001N\000\000\000\000\000\n\001R\005z\000\000\002\225\001V\000\000\000\000\000\000\002\225\005\130\005\134\000\000\005\202\001Z\002\225\002\225\002\225\002\225\000\000\001^\000\000\002\225\000\000\000\000\000\000\000\000\000\000\002\225\000\000\001\154\011\018\000\000\000\000\005\138\000\000\000\000\001\158\000\000\001\162\004r\001\006\000\000\001\166\002\225\001\170\001\174\003V\002\190\n\178\002\225\002\130\015\130\000\000\000\000\002\130\002\246\001\n\000\000\000\000\000\000\002\142\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000\000\001\014\001\018\001\022\003v\001\030\001\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003z\000\000\001.\011\014\000\000\000\000\003r\001\190\0016\007\173\015\134\001:\000\000\002\178\000\000\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\005j\015\146\005v\021F\000\000\001>\001B\001F\001J\001N\000\000\000\000\000\000\001R\005z\000\000\007\173\001V\n\181\000\000\000\000\000\000\005\130\005\134\000\000\005\202\001Z\005\134\000\000\000\000\007\173\000\000\001^\007\173\b\166\000\000\000\000\021R\000\000\000\000\007\173\000\000\001\154\011\018\007\173\000\000\005\138\000\000\n\181\001\158\000\000\001\162\004r\001\006\021\006\001\166\000\000\001\170\001\174\003V\002\190\r\170\n\181\002\130\000\000\n\181\011\134\000\000\002\246\001\n\000\000\000\000\n\181\002\142\000\000\000\000\n\181\000\000\001\210\000\000\000\000\000\000\001\014\001\018\001\022\003v\001\030\001\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003z\000\000\001.\011\014\000\000\000\000\003r\001\190\0016\000\000\000\000\001:\000\000\002\178\000\000\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\005j\000\000\005v\000\000\000\000\001>\001B\001F\001J\001N\000\000\000\000\000\000\001R\005z\000\000\000\000\001V\000\000\000\000\000\000\000\000\005\130\005\134\000\000\005\202\001Z\000\000\000\000\000\000\000\000\000\000\001^\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\154\011\018\000\000\000\000\005\138\000\000\000\000\001\158\000\000\001\162\004r\000\000\b\249\001\166\000\006\001\170\001\174\000\000\002\186\002\190\000\000\002\234\002\130\000\000\000\000\000\000\000\000\002\246\000\000\000\000\000\000\000\000\b\249\000\000\b\249\b\249\000\000\001\210\000\000\000\000\000\000\002\250\000\000\003>\003B\000\000\000\000\000\000\000\000\b\001\003F\000\000\002\254\000\000\b\001\000\000\003\214\003\218\n\222\003\222\0032\003\234\003\242\006\214\001\202\001\206\011>\002\178\000\000\000\000\003:\000\000\000\000\b\001\b\026\b\030\b*\b>\000\000\005v\000\000\000\000\000\000\001\210\002\170\001\230\000\000\000\000\000\000\b\178\000\000\000\000\000\000\001\242\000\000\b\001\b\190\b\214\t*\005\130\005\134\000\000\000\000\b\001\000\000\000\000\001\246\002\146\b\001\b\001\000\238\002\158\000\000\002\178\004\030\004*\000\000\b\001\b\001\000\000\0046\000\000\000\000\005\138\b2\b\249\004\253\004\253\bJ\004r\t>\004\253\000\000\004\253\004\253\000\000\004\253\004:\004\253\004\253\b\001\000\000\004\253\b\001\004\253\004\253\004\253\004\253\004\253\004\253\004\253\004\253\b\001\004\253\016~\004\253\000\000\000\000\000\000\000\000\000\000\002\006\004\253\000\000\000\000\000\000\000\000\004\253\004\253\004\253\000\000\002\n\004\253\004\253\004\253\004\253\000\000\004\253\000\000\001\210\004\253\000\000\000\000\000\000\000\000\004\253\004\253\004\253\000\000\000\000\004\253\004\253\004\253\000\000\004\253\004\253\003\154\000\000\000\000\000\000\000\000\004\253\007\002\001\222\000\000\004\253\004\253\000\000\004\253\002\178\004\253\000\000\000\000\000\000\000\000\004\253\004\253\004\253\000\000\004\253\004\253\004\253\004\253\000\000\004\253\004\253\000\000\000\000\000\000\004\253\000\000\004\253\004\253\000\000\000\000\002\150\004\253\007\006\000\000\000\000\020\026\004\253\000\000\n\205\000\000\004\253\n\205\004\253\004\253\n\205\n\205\000\000\004\253\n\205\000\000\n\205\000\000\000\000\n\205\000\000\001*\000\000\n\205\n\205\000\000\n\205\n\205\002\225\n\205\000\000\n\205\000\000\000\000\000\000\002\225\n\205\000\000\000\000\n\205\000\000\000\000\000\000\000\000\000\000\000\000\002\225\n\205\000\000\n\205\000\000\000\000\n\205\n\205\000\n\000\000\000\000\000\000\000\000\n\205\000\000\000\000\n\205\000\000\000\000\n\205\n\205\000\000\n\205\002\225\n\205\n\205\000\000\000\000\000\000\000\000\002\225\000\000\000\000\000\000\000\000\000\000\002\225\n\205\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\205\n\205\000\000\000\000\n\205\000\000\n\205\000\000\000\000\000\000\000\000\005\166\000\000\002\225\000\000\000\000\001\202\001\206\n\205\n\205\000\000\n\205\n\205\000\000\n\205\000\000\n\205\000\000\n\205\000\000\n\205\000\000\n\205\b\229\b\229\001\210\001\214\001\230\b\229\000\000\001\206\b\229\000\000\000\000\000\000\001\242\003\190\000\000\018\174\b\229\000\000\b\229\b\229\b\229\000\000\b\229\b\229\b\229\001\246\020\022\000\000\0196\000\000\002\158\000\000\002\178\004\030\004*\000\000\b\229\000\000\000\000\020&\000\000\000\000\b\229\b\229\000\000\000\000\b\229\000\000\000\000\002\154\000\000\b\229\000\000\000\000\b\229\000\000\004:\000\000\000\000\b\229\b\229\b\229\000\000\000\000\000\000\000\000\000\000\000\000\b\229\b\229\000\000\000\000\000\000\000\000\000\000\b\229\000\000\000\000\000\000\004\154\000\000\000\000\b\229\000\000\000\000\000\000\000\000\000\000\000\000\b\229\b\229\b\229\000\000\b\229\b\229\000\000\004Y\000\000\000\000\000\000\000\000\004Y\000\000\b\229\004Y\b\229\b\229\000\000\000\000\000\000\b\229\000\000\000\000\000\000\004Y\b\229\000\000\000\000\004Y\b\229\004Y\b\229\b\229\012u\012u\000\000\000\000\004Y\012u\000\000\001\206\012u\004Y\000\000\000\000\000\000\000\000\000\000\004Y\004\186\000\000\012u\012u\012u\004B\012u\012u\012u\000\000\000\000\004Y\004Y\000\000\000\000\000\000\004Y\002\226\000\000\000\000\012u\000\000\000\000\000\000\000\000\000\000\012u\012u\000\000\000\000\012u\000\000\004Y\002\154\004Y\012u\000\000\000\000\012u\000\000\000\000\000\000\004Y\012u\012u\012u\004Y\004Y\002\226\000\238\004Y\004Y\012u\012u\000\000\000\000\004R\004Y\000\000\012u\000\000\000\000\000\000\004\154\000\000\000\000\012u\004Y\000\000\000\000\000\000\000\000\021\026\012u\012u\012u\000\000\012u\012u\000\000\004Y\000\000\004Y\000\000\000\000\004Y\000\000\012u\004Y\012u\012u\004Y\000\000\000\000\012u\000\000\000\000\000\000\004Y\012u\000\000\000\000\004Y\012u\004Y\012u\012u\b\233\b\233\000\000\000\000\000\000\b\233\000\000\001\206\b\233\004Y\000\000\000\000\000\000\000\000\000\000\004Y\b\233\000\000\b\233\b\233\b\233\000\000\b\233\b\233\b\233\000\000\000\000\004Y\000\000\000\000\000\000\000\000\004Y\002\226\000\000\000\000\b\233\000\000\000\000\000\000\000\000\000\000\b\233\b\233\000\000\000\000\b\233\000\000\004Y\002\154\000\000\b\233\000\000\000\000\b\233\000\000\000\000\000\000\000\000\b\233\b\233\b\233\004Y\004Y\000\000\000\000\004Y\004Y\b\233\b\233\000\000\000\000\007n\000\000\000\000\b\233\000\000\000\000\000\000\004\154\000\000\000\000\b\233\004Y\000\000\000\000\000\000\000\000\000\000\b\233\b\233\b\233\002\225\b\233\b\233\000\000\000\000\002\225\002\225\002\225\000\000\000\000\002\225\b\233\002\225\b\233\b\233\002\225\002\225\002\225\b\233\002\225\002\225\002\225\002\225\b\233\002\225\002\225\000\000\b\233\002\225\b\233\b\233\000\000\002\225\000\n\000\000\002\225\002\225\002\225\000\000\002\225\000\000\002\225\002\225\000\n\000\000\002\225\002\225\000\n\002\225\002\225\002\225\000\000\000\000\000\000\002\225\002\225\000\000\002\225\002\225\002\225\002\225\002\225\002\225\000\000\002\225\002\225\000\000\002\225\002\225\002\225\000\000\002\225\002\225\002\225\002\225\002\225\002\225\002\225\000\000\002\225\000\000\000\000\002\225\000\000\000\000\000\000\000\000\002\225\002\225\002\225\002\225\000\000\000\000\000\000\002\225\002\225\002\225\002\225\002\225\000\000\006\141\000\000\0009\002\225\002\225\000\000\0009\0009\000\000\0009\0009\002\225\000\000\000\000\000\000\0009\000\000\002\225\000\000\000\000\006\141\002\225\002\225\000\000\000\000\0009\002\225\002\225\002\225\0009\006\222\0009\0009\000\000\000\000\000\000\000\000\000\000\0009\000\000\0009\000\000\000\000\000\000\0009\0009\000\000\0009\0009\0009\0009\0009\000\000\000\000\000\000\0009\000\000\000\000\0009\000\000\000\000\000\000\0009\0009\0009\0009\000\000\0009\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0009\000\000\000\000\000\000\012\181\012\161\000\000\0009\0009\0009\0009\0009\000\000\006\137\000\000\0005\000\000\000\000\000\000\0005\0005\000\000\0005\0005\012\181\000\000\000\000\002\030\0005\000\000\002\"\000\000\000\000\006\137\0009\0009\000\000\002*\0005\0009\0009\0009\0005\002.\0005\0005\0026\012\161\000\000\000\000\000\000\0005\000\000\0005\000\000\000\000\000\000\0005\0005\000\000\0005\0005\0005\0005\0005\000\000\000\000\000\000\0005\000\000\002:\0005\000\000\000\000\000\000\0005\0005\0005\0005\000\000\0005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0005\000\000\000\000\000\000\000\000\000\000\000\000\0005\0005\0005\0005\0005\000\000\006\153\000\000\012=\000\000\000\000\000\000\012=\012=\000\000\012=\012=\002>\000\000\000\000\000\000\012=\000\000\000\000\000\000\000\000\006\153\0005\0005\000\000\000\000\012=\0005\0005\0005\012=\000\000\012=\012=\000\000\000\000\000\000\000\000\000\000\012=\000\000\012=\000\000\000\000\000\000\012=\012=\000\000\012=\012=\012=\012=\012=\000\000\000\000\000\000\012=\000\000\000\000\012=\000\000\000\000\000\000\012=\012=\012=\012=\000\000\012=\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012=\000\000\000\000\000\000\012\181\012\161\000\000\012=\012=\012=\012=\012=\000\000\006\149\000\000\0129\000\000\000\000\000\000\0129\0129\000\000\0129\0129\012\181\000\000\000\000\002\030\0129\000\000\002\"\000\000\000\000\006\149\012=\012=\000\000\002\206\0129\012=\012=\012=\0129\002.\0129\0129\0026\012\161\000\000\000\000\000\000\0129\000\000\0129\000\000\000\000\000\000\0129\0129\000\000\0129\0129\0129\0129\0129\000\000\001\202\001\206\0129\000\000\002:\0129\000\000\000\000\000\000\0129\0129\0129\0129\000\000\0129\000\000\000\000\000\000\000\000\001\210\001\214\001\230\000\000\000\000\0129\000\000\000\000\000\000\000\000\001\242\000\000\0129\0129\0129\0129\0129\001\250\000\000\000\000\000\000\000\000\000\000\001\246\002\146\000\000\000\000\000\000\002\158\002>\002\178\004\030\004*\012y\012y\000\000\000\000\0046\012y\0129\0129\012y\000\000\000\000\0129\0129\0129\000\000\000\000\004\138\000\000\012y\012y\012y\004:\012y\012y\012y\000\000\001\021\000\000\000\000\000\000\000\000\001\021\000\000\000\000\000\000\000\000\012y\000\000\000\000\000\000\000\000\000\000\012y\012y\000\000\000\000\012y\000\000\000\000\000\000\001\021\012y\000\000\000\000\012y\000\000\000\000\000\000\000\000\012y\012y\012y\000\000\000\000\000\000\000\000\000\000\000\000\012y\012y\000\000\000\000\001\021\000\000\018\182\012y\000\000\000\000\000\000\012y\001\021\000\000\012y\000\000\000\000\001\021\000\000\000\000\000\000\012y\012y\012y\000\000\012y\012y\001\021\000\000\000\000\000\000\000\000\000\000\000\000\007\253\012y\000\006\012y\012y\007\253\002\186\002\190\012y\002\234\002\130\000\000\000\000\012y\000\000\002\246\000\000\012y\001\021\012y\012y\000\000\003\254\000\000\007\253\001\210\000\000\001\021\000\000\002\250\000\000\003>\003B\000\000\000\000\000\000\000\000\000\000\003F\000\000\002\254\000\000\000\000\000\000\003\214\003\218\007\253\003\222\0032\003\234\003\242\006\214\000\000\000\000\007\253\002\178\000\000\000\000\003:\007\253\007\253\000\238\b\026\b\030\b*\b>\000\000\005v\007\253\007\253\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\178\000\000\000\000\000\000\000\000\000\000\000\000\b\190\b\214\t*\005\130\005\134\000\000\000\000\007\253\000\000\000\000\007\253\000\000\000\000\000\000\000\000\000\000\000\006\000\000\000\000\007\253\002\186\002\190\000\000\002\234\002\130\000\000\000\000\005\138\b2\002\246\000\000\000\000\bJ\004r\t>\000\000\014n\000\000\000\000\001\210\000\000\000\000\000\000\002\250\000\000\003>\003B\000\000\000\000\000\000\001\197\000\000\003F\000\000\002\254\001\197\000\000\000\000\003\214\003\218\000\000\003\222\0032\003\234\003\242\006\214\000\000\000\000\000\000\002\178\000\000\000\000\003:\000\000\001\197\000\000\b\026\b\030\b*\b>\000\000\005v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005-\012\245\b\178\000\000\000\000\0051\012\245\001\197\000\000\b\190\b\214\t*\005\130\005\134\000\000\001\197\000\000\000\000\000\000\005-\001\197\001\197\000\238\005-\0051\000\000\003\029\003\029\0051\001\197\001\197\003\029\000\000\000\000\003\029\000\000\005\138\b2\000\000\000\000\000\000\bJ\004r\t>\003\029\003\029\003\029\000\000\003\029\003\029\003\029\000\000\000\000\000\000\000\000\001\197\000\000\000\000\000\000\000\000\000\000\000\000\003\029\000\000\001\197\000\000\000\000\000\000\003\029\004\130\000\000\000\000\003\029\000\000\000\000\000\000\000\000\003\029\012\245\012\245\003\029\000\000\000\000\012\245\012\245\003\029\003\029\003\029\000\000\000\000\000\000\005-\000\000\000\000\003\029\003\029\0051\012\245\000\000\012\245\000\000\003\029\012\245\000\000\012\245\003\029\005-\000\000\003\029\005-\000\000\0051\000\000\000\000\0051\003\029\003\029\003\029\004}\003\029\003\029\000\000\000\000\018\198\000\000\000\000\000\000\000\000\000\000\003\029\000\000\003\029\003\029\000\000\000\000\000\000\003\029\000\000\000\000\000\000\000\000\003\029\003\182\n\217\000\000\003\029\n\217\003\029\003\029\003V\002\190\000\000\000\000\002\130\000\000\006\166\000\000\000\000\002\246\000\000\000\000\000\000\n\217\n\217\018\242\n\217\n\217\000\000\001\210\000\000\006\198\000\000\017\018\000\000\000\000\003Z\000\000\017*\b\226\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\217\019.\003f\000\000\000\000\003r\001\190\000\000\000\000\000\000\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\n\217\003\250\000\000\004\002\005j\n\190\005v\000\000\004}\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\019\146\005z\001\202\001\206\000\000\000\000\000\000\000\000\000\000\005\130\005\134\000\000\005\202\n\217\000\000\n\217\000\000\000\000\000\000\000\000\000\000\001\210\001\214\000\000\000\000\000\000\000\000\n\217\000\000\000\000\n\217\n\217\000\000\005\138\000\000\n\217\000\000\n\217\000\000\004r\n\213\n\217\000\000\n\213\001\246\002\162\003V\002\190\000\000\002\158\002\130\002\178\004\030\004*\000\000\002\246\000\000\000\000\0046\n\213\n\213\000\000\n\213\n\213\000\000\001\210\000\000\000\000\000\000\000\000\000\000\000\000\003Z\000\000\000\000\004:\000\000\000\000\026\022\000\000\000\000\000\000\000\000\n\213\000\000\003f\000\000\000\000\003r\001\190\000\000\000\000\000\000\000\000\026\002\002\178\000\000\000\000\003\246\000\000\000\000\n\213\003\250\000\000\004\002\005j\000\000\005v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005z\000\000\012Y\000\000\000\000\012Y\000\000\000\000\005\130\005\134\000\000\005\202\n\213\000\000\n\213\012Y\000\000\000\000\000\000\000\000\000\000\012Y\000\000\001\221\001\221\000\000\n\213\000\000\001\221\n\213\n\213\001\221\005\138\012Y\n\213\000\000\n\213\000\000\004r\012Y\n\213\001\221\001\221\001\221\000\000\001\221\001\221\001\221\012Y\000\000\000\000\012Y\000\000\000\000\000\000\000\000\012Y\000\000\000\000\001\221\000\000\000\000\000\000\000\000\000\000\001\221\001\221\000\000\000\000\001\221\000\000\000\000\012Y\000\000\001\221\000\000\012Y\001\221\000\000\000\000\000\000\000\000\001\221\001\221\001\221\000\000\012Y\012Y\000\000\000\000\012Y\001\221\001\221\000\000\000\000\000\000\027\242\000\000\001\221\001\r\000\000\000\000\001\221\000\000\001\r\001\221\000\000\012Y\000\000\000\000\000\000\000\000\001\221\001\221\001\221\0256\001\221\001\221\000\000\000\000\000\000\000\000\002\006\001\r\000\000\000\000\001\221\000\000\001\221\001\221\003V\002\190\002\n\001\221\002\130\000\000\006\166\000\000\001\221\002\246\001\210\000\000\004\254\000\000\001\221\001\r\000\000\003R\000\000\001\210\000\000\006\198\000\000\001\r\000\000\000\000\003Z\003\154\001\r\b\226\000\000\000\000\000\000\007\002\001\222\000\000\000\000\001\r\001\r\003f\002\178\000\000\n\174\001\190\000\000\000\000\000\000\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\n\177\003\250\000\000\004\002\000\000\n\190\005v\000\000\001\r\000\000\003V\002\190\000\000\007\006\002\130\000\000\006\166\001\r\005z\002\246\000\000\000\000\000\000\000\000\000\000\000\000\005\130\005\134\000\000\001\210\n\198\006\198\000\000\000\000\000\000\000\000\003Z\000\000\000\000\b\226\000\000\000\000\000\000\000\000\n\177\n\206\000\000\n\177\011:\003f\005\138\000\000\n\174\001\190\n\177\000\000\004r\000\000\n\177\002\178\000\000\000\000\003\246\000\000\000\000\n\177\003\250\000\000\004\002\000\000\n\190\005v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\130\005\134\000\000\000\000\n\198\005}\005}\000\000\000\000\000\000\005}\000\000\000\000\005}\000\000\000\000\000\000\000\000\n\177\000\000\000\000\n\177\n\177\005}\005\138\005}\000\000\005}\n\177\005}\004r\000\000\n\177\000\000\000\000\000\000\000\000\000\000\000\000\000\246\000\000\005}\002\194\000\000\000\000\000\000\000\000\005}\005}\000\000\000\000\000\000\028J\005}\000\000\000\000\005}\000\000\003\182\005}\000\000\000\000\000\000\000\000\005}\005}\005}\000\000\000\000\000\000\003\186\000\000\000\000\000\000\000\000\000\000\016\174\000\000\000\000\000\000\005}\005}\000\000\000\000\005}\024Z\000\000\001\006\017\018\000\000\000\000\000\000\000\000\017*\005}\005}\005}\000\000\005}\005}\000\000\000\000\000\000\001\n\007n\000\000\000\000\002\142\000\000\0172\000\000\005}\000\000\027\250\005}\005}\001\014\001\018\001\022\001\026\001\030\001\"\000\000\017F\017r\000\000\005}\004\149\000\000\001&\000\000\001.\0012\000\000\000\000\000\000\000\000\0016\004a\000\000\001:\000\000\000\000\000\246\021\154\000\000\002\018\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017\178\001>\001B\001F\001J\001N\003\182\005q\005q\001R\000\000\000\000\005q\001V\000\000\005q\000\000\000\000\017\182\000\000\000\000\000\000\001Z\000\000\017\222\005q\000\000\005q\001^\005q\000\000\005q\000\000\000\000\000\000\000\000\017\018\000\000\001\154\027.\000\000\017*\000\000\005q\000\000\001\158\000\000\001\162\000\000\005q\005q\001\166\000\000\001\170\001\174\007\222\000\000\018Z\005q\000\000\000\000\005q\000\000\000\000\000\000\000\000\005q\005q\000\238\000\000\000\000\017F\018n\000\000\000\000\004a\004a\000\000\000\000\000\000\000\000\000\000\005q\005q\000\000\000\000\005q\000\000\b\245\000\000\000\000\000\000\018~\000\000\000\000\000\000\005q\005q\005q\000\000\005q\005q\000\000\000\000\t\202\000\000\000\000\012:\b\245\000\000\b\245\b\245\000\000\005q\000\000\000\000\005q\005q\n\002\n\026\n\"\n\n\n*\000\000\000\000\001\202\002~\000\000\005q\002\130\000\000\000\000\n2\n:\000\000\000\000\000\000\000\000\000\000\000\000\000\000\nB\000\000\000\000\001\210\001\214\001\230\002\134\000\000\000\238\000\000\000\000\000\000\000\000\001\242\001\006\000\000\000\000\t\210\n\018\nJ\nR\nb\000\000\000\000\000\000\000\000\002\138\002\146\000\000\nj\001\n\002\158\000\000\002\178\004\030\004*\000\000\000\000\nr\000\000\020\242\000\000\020\246\001\014\001\018\001\022\001\026\001\030\001\"\000\000\000\000\000\000\n\146\000\000\n\154\nZ\001&\004:\001.\0012\b\245\nz\000\000\000\000\0016\000\000\005\134\001:\000\000\n\130\n\138\000\000\000\000\000\000\000\000\000\000\021\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001>\001B\001F\001J\001N\000\000\003]\003]\001R\021\006\000\000\003]\001V\000\000\003]\000\000\000\000\000\000\000\000\000\000\000\000\001Z\000\000\000\000\003]\000\000\003]\001^\003]\000\000\003]\000\000\000\000\000\000\000\000\000\000\000\000\001\154\027J\000\000\000\000\000\000\003]\000\000\001\158\000\000\001\162\000\000\003]\003]\001\166\000\000\001\170\001\174\005\005\000\000\000\000\003]\000\000\000\000\003]\000\000\000\000\000\000\000\000\003]\003]\003]\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003]\000\000\001\202\001\206\003]\bq\bq\000\000\000\000\000\000\bq\000\000\000\000\bq\003]\003]\003]\000\000\003]\003]\000\000\001\210\001\214\bq\005\005\bq\000\000\bq\000\000\bq\000\000\003]\000\000\000\000\000\000\003]\000\000\000\000\000\000\000\000\000\000\bq\000\000\000\000\001\246\002\154\003]\bq\bq\002\158\000\000\002\178\004\030\004*\000\000\000\000\bq\000\000\0046\bq\015\158\000\000\000\000\000\000\bq\bq\bq\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004:\000\000\000\000\000\000\000\000\bq\000\000\000\000\000\000\bq\rA\rA\000\000\000\000\000\000\rA\000\000\000\000\rA\bq\bq\bq\000\000\bq\bq\000\000\000\000\000\000\rA\000\000\rA\000\000\rA\bq\rA\000\000\bq\000\000\000\000\000\000\bq\000\000\000\000\000\000\000\000\000\000\rA\000\000\000\000\004\254\000\000\bq\rA\rA\rE\rE\000\000\000\000\004B\rE\000\000\rA\rE\000\000\rA\000\000\000\000\000\000\000\000\rA\rA\rA\rE\000\000\rE\000\000\rE\000\000\rE\000\000\000\000\000\000\000\000\000\000\000\000\rA\000\000\000\000\000\000\rA\rE\000\000\000\000\000\000\000\000\000\000\rE\rE\000\000\rA\rA\rA\004B\rA\rA\rE\000\000\000\000\rE\004R\000\000\000\000\000\000\rE\rE\rE\rA\000\000\000\000\000\000\rA\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\rE\000\000\rA\000\000\rE\003]\003]\000\000\000\000\000\000\003]\000\000\000\000\003]\rE\rE\rE\000\000\rE\rE\000\000\000\000\000\000\003]\004R\003]\000\000\003]\000\000\003]\000\000\rE\001\202\001\206\000\000\rE\000\000\000\000\000\000\000\000\000\000\003]\000\000\000\000\000\000\000\000\rE\003]\003]\000\000\000\000\001\210\001\214\005\t\000\000\000\000\003]\000\000\000\000\003]\000\000\000\000\000\000\000\000\003]\003]\003]\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\246\002\162\000\000\000\000\000\000\002\158\003]\002\178\004\030\004*\003]\001\205\000\000\000\000\0046\000\000\001\205\000\000\001\206\001\205\003]\003]\003]\000\000\003]\003]\000\000\b\209\000\000\001\205\005\t\004:\000\000\001\205\004\205\001\205\000\000\003]\000\000\000\000\000\000\003]\000\000\004Y\000\000\000\000\000\000\001\205\004Y\000\000\026\002\000\000\003]\001\205\001\205\000\000\000\000\000\000\000\000\000\000\002\154\000\000\001\205\000\000\000\000\001\205\000\000\004Y\000\000\000\000\001\205\001\205\001\205\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\205\001\205\000\000\004Y\004\154\003A\000\000\000\000\000\000\000\000\003A\004Y\001\206\003A\001\205\001\205\004Y\002\226\001\205\001\205\000\000\b\205\000\000\003A\000\000\004Y\004Y\003A\001\205\003A\000\000\000\000\000\000\000\000\000\000\001\205\000\000\000\000\000\000\000\000\001\205\003A\000\000\000\000\000\000\000\000\001\205\003A\001\201\000\000\000\181\004Y\000\000\000\000\002\154\000\181\003A\000\000\000\181\003A\004Y\000\000\000\000\000\000\003A\003A\003A\000\000\000\181\000\000\000\181\000\000\000\181\000\000\000\181\000\000\000\000\000\000\000\000\000\000\003A\003A\000\000\000\000\004\154\000\000\000\181\000\000\000\000\000\000\000\000\000\000\000\181\000\000\003A\003A\000\181\000\000\003A\003A\000\000\000\181\000\000\000\000\000\181\000\000\000\000\000\000\003A\000\181\000\181\000\238\000\000\000\000\000\000\003A\000\000\000\000\000\181\000\181\003A\000\000\000\000\000\000\000\000\000\181\003A\000\000\000\249\000\181\000\000\000\000\000\000\000\249\000\000\000\000\000\249\000\000\000\000\000\181\000\181\000\000\000\000\000\181\000\181\000\000\000\249\000\000\000\249\000\000\000\249\000\000\000\249\000\181\000\000\000\000\000\000\000\000\000\000\000\181\000\181\000\000\000\000\000\000\000\249\000\000\000\000\000\000\000\000\000\181\000\249\000\181\000\000\000\000\000\249\000\000\000\000\000\000\000\000\000\249\000\000\000\000\000\249\000\000\000\000\000\000\000\000\000\249\000\249\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\249\000\249\000\000\000\000\000\000\000\000\000\000\000\249\000\000\000\000\000\189\000\249\000\000\000\000\000\000\000\189\000\000\000\000\000\189\000\000\000\000\000\249\000\249\000\000\000\000\000\249\000\249\000\000\000\189\000\000\000\189\000\000\000\189\000\000\000\189\000\249\000\000\000\000\000\000\000\000\000\000\000\249\000\249\000\000\000\000\000\000\000\189\000\000\000\000\000\000\000\000\000\249\000\189\000\249\000\000\000\000\000\189\000\000\000\000\000\000\000\000\000\189\000\000\000\000\000\189\000\000\000\000\000\000\000\000\000\189\000\189\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\189\000\189\000\000\000\000\000\000\000\000\000\000\000\189\000\000\000\000\000\185\000\189\000\000\000\000\006\221\000\185\000\000\000\000\000\185\006\221\000\000\000\189\000\189\000\000\000\000\000\189\000\189\000\000\000\185\000\000\000\185\000\000\000\185\000\000\000\185\000\189\000\000\000\000\006\221\000\000\000\000\000\189\000\189\000\000\000\000\000\000\000\185\000\000\000\000\000\000\000\000\000\189\000\185\000\189\000\000\000\000\000\185\000\000\000\000\000\000\006\221\000\185\000\000\000\000\000\185\000\000\000\000\000\000\006\221\000\185\000\185\000\238\000\000\006\221\006\221\000\238\000\000\000\000\000\185\000\185\000\000\000\000\006\221\006\221\000\000\000\185\000\000\000\000\001\169\000\185\000\000\000\000\000\000\001\169\000\000\000\000\001\169\000\000\000\000\000\185\000\185\000\000\000\000\000\185\000\185\000\000\001\169\000\000\006\221\000\000\001\169\r\001\001\169\000\185\000\000\000\000\r\001\006\221\000\000\000\185\000\185\000\000\000\000\000\000\001\169\001\169\000\000\000\000\000\000\000\185\001\169\000\185\000\000\023\186\000\000\r\001\005\005\000\000\000\000\001\169\000\000\000\000\001\169\000\000\000\000\000\000\000\000\001\169\001\169\001\169\000\000\000\000\000\000\000\000\000\000\000\000\000\000\r\001\000\000\000\000\000\000\000\000\000\000\001\169\000\000\r\001\000\000\001\169\r=\r=\r\001\r\001\000\238\r=\000\000\000\000\r=\001\169\001\169\r\001\r\001\001\169\001\169\000\000\000\000\000\000\r=\005\005\r=\000\000\r=\001\169\r=\000\000\000\000\000\000\000\000\001\169\001\169\000\000\000\000\000\000\000\000\001\169\r=\r\001\000\000\000\000\000\000\001\169\r=\r=\000\000\000\000\r\001\000\000\000\000\000\000\000\000\r=\000\000\000\000\r=\000\000\000\000\000\000\000\000\r=\r=\r=\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\r=\000\000\000\000\000\000\r=\r9\r9\000\000\000\000\000\000\r9\000\000\000\000\r9\r=\r=\r=\000\000\r=\r=\000\000\000\000\000\000\r9\000\000\r9\000\000\r9\000\000\r9\000\000\r=\000\000\000\000\000\000\r=\000\000\000\000\000\000\000\000\000\000\r9\000\000\000\000\004\254\000\000\r=\r9\r9\000\000\000\000\000\000\000\000\000\000\000\000\004a\r9\000\000\000\000\r9\000\246\000\000\000\000\002\018\r9\r9\r9\000\000\000\000\000\000\000\000\000\000\000\000\017\178\000\000\000\000\000\000\004a\000\000\003\182\r9\000\000\bu\bu\r9\000\000\000\000\bu\000\000\000\000\bu\017\182\000\000\000\000\r9\r9\r9\017\222\r9\r9\bu\000\000\bu\000\000\bu\000\000\bu\000\000\007J\017\018\000\000\r9\000\000\000\000\017*\r9\000\000\000\000\bu\000\000\000\000\000\000\000\000\000\000\bu\bu\r9\000\000\000\000\000\000\018Z\000\000\000\000\bu\000\000\000\000\bu\000\000\000\000\000\000\000\000\bu\bu\000\238\017F\018n\000\000\000\000\004a\004a\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bu\000\000\000\000\000\000\bu\000\000\006\241\000\000\018~\000\000\000\000\000\000\000\000\000\000\bu\bu\bu\000\000\bu\bu\000\000\000\000\t\202\000\000\000\000\006\241\000\000\000\000\bu\006\241\000\000\bu\000\000\000\000\000\000\bu\n\002\n\026\n\"\n\n\n*\000\000\000\000\000\000\000\000\000\000\bu\001\201\000\000\000\000\n2\n:\001\201\000\000\001\206\001\201\000\000\000\000\000\000\nB\000\000\000\000\000\000\b\205\000\000\001\201\000\000\000\238\000\000\001\201\000\000\001\201\000\000\000\000\000\000\000\000\t\210\n\018\nJ\nR\nb\000\000\000\000\001\201\000\000\000\000\000\000\006\241\nj\001\201\000\000\000\000\000\000\000\000\000\000\000\000\002\154\nr\001\201\000\000\000\000\001\201\000\000\000\000\000\000\000\000\001\201\001\201\001\201\000\000\000\000\n\146\000\000\n\154\nZ\000\000\000\000\000\000\000\000\000\000\nz\000\000\001\201\001\201\000\000\000\000\004\154\000\000\n\130\n\138\000\000\000\000\000\000\016b\000\000\000\000\001\201\001\201\000\000\000\000\001\201\001\201\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\202\001\201\000\000\000\000\016f\000\000\000\000\000\000\001\201\000\000\000\000\000\000\000\000\001\201\n\002\n\026\n\"\n\n\n*\001\201\000\000\000\000\000\000\000\000\000\000\n\210\000\000\000\000\n2\n:\000\246\001\202\001\206\002\018\000\000\000\000\000\000\nB\000\000\000\000\000\000\000\000\000\000\017\178\000\000\000\238\000\000\004a\000\000\003\182\001\210\001\214\001\230\000\000\t\210\n\018\nJ\nR\nb\000\000\001\242\017\182\000\000\000\000\000\000\000\000\nj\017\222\000\000\000\000\000\000\000\000\000\000\001\246\002\146\nr\000\000\000\000\002\158\017\018\002\178\004\030\004*\000\000\017*\000\000\000\000\0046\000\000\n\146\016j\n\154\nZ\016z\000\000\000\000\000\000\000\000\nz\000\000\018Z\000\000\000\000\000\000\004:\000\000\n\130\n\138\005\169\005\169\000\000\000\000\000\000\005\169\017F\018n\005\169\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\169\000\000\005\169\000\000\005\169\000\000\005\169\000\000\000\000\018~\000\000\000\000\000\000\000\000\004n\000\000\004r\000\000\005\169\000\000\000\000\000\000\000\000\000\000\005\169\005\169\000\000\000\000\000\000\000\000\007\222\000\000\000\000\005\169\000\000\000\000\005\169\000\000\006I\000\000\000\000\005\169\005\169\000\238\000\000\002\190\000\000\000\000\002\130\000\000\000\000\000\000\000\000\002\246\000\000\002\225\002\225\005\169\006I\002\225\000\000\005\169\000\000\001\210\002\225\000\000\000\000\002\250\000\000\000\000\002\225\005\169\005\169\005\169\002\225\005\169\005\169\000\000\002\254\000\000\000\000\002\225\000\n\000\000\000\000\006\218\0032\001\190\005\169\000\000\000\000\015:\005\169\002\178\002\225\000\000\003:\002\225\002\225\000\000\b\026\b\030\b*\005\169\002\225\005v\000\000\002\225\000\000\000\000\002\225\002\225\000\000\002\225\002\225\000\000\002\225\000\000\000\000\000\000\000\000\000\000\005\165\007\030\000\000\005\130\005\134\005\165\002\225\000\000\005\165\000\000\000\000\000\000\000\000\000\000\002\225\002\225\000\000\015v\005\165\000\000\005\165\000\000\005\165\000\000\005\165\000\000\000\000\005\138\b2\000\000\000\000\000\000\bJ\004r\000\000\000\000\005\165\000\000\002\225\000\000\000\000\000\000\005\165\007\138\002\225\000\000\000\000\000\000\000\000\000\000\000\000\005\165\000\000\000\000\005\165\000\000\000\000\004\133\000\000\005\165\005\165\000\238\021\194\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\165\000\000\005\193\005\193\005\165\000\000\003\182\005\193\000\000\000\000\005\193\000\000\000\000\000\000\005\165\005\165\005\165\000\000\005\165\005\165\005\193\000\000\005\193\000\000\005\193\000\000\005\193\000\000\0222\000\000\000\000\005\165\000\000\000\000\000\000\005\165\017\018\000\000\005\193\000\000\000\000\017*\000\000\000\000\005\193\005\193\005\165\000\000\000\000\000\000\022\214\022\230\000\000\005\193\000\000\000\000\005\193\000\000\000\000\000\000\000\000\005\193\005\193\005\193\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\133\005\193\000\000\005\189\007\030\005\193\000\000\000\000\005\189\023\218\000\000\005\189\000\000\000\000\000\000\005\193\005\193\005\193\000\000\005\193\005\193\005\189\000\000\005\189\000\000\005\189\000\000\005\189\000\000\000\000\000\000\000\000\005\193\000\000\000\000\000\000\005\193\000\000\000\000\005\189\000\000\000\000\000\000\000\000\000\000\005\189\007\138\007\130\000\000\000\000\000\000\000\000\000\000\000\000\005\189\000\000\000\000\005\189\000\000\000\000\000\000\000\000\005\189\005\189\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\189\003V\002\190\000\000\005\189\002\130\000\000\006\166\000\000\000\000\002\246\000\000\000\000\000\000\005\189\005\189\005\189\000\000\005\189\005\189\001\210\000\000\006\198\000\000\000\000\000\000\000\000\003Z\000\000\000\000\b\226\005\189\000\000\000\000\000\000\005\189\000\000\000\000\000\000\000\000\003f\000\000\000\000\n\174\001\190\000\000\005\189\012\186\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\000\000\n\190\005v\t\202\000\000\000\000\012:\000\000\000\000\000\000\b\245\000\000\000\000\000\000\005z\000\000\000\000\n\002\n\026\n\"\n\n\n*\005\130\005\134\000\000\000\000\n\198\000\000\000\000\000\000\000\000\n2\n:\000\000\000\000\000\000\000\000\000\000\000\000\000\000\nB\n\206\000\000\000\000\n\218\000\000\005\138\000\000\000\238\000\000\000\000\000\000\004r\000\000\000\000\000\000\000\000\t\210\n\018\nJ\nR\nb\000\000\003=\000\000\000\000\000\000\000\000\003=\nj\001\206\003=\000\000\000\000\000\000\000\000\000\000\000\000\nr\000\000\000\000\003=\000\000\000\000\000\000\003=\000\000\003=\000\000\000\000\000\000\000\000\n\146\000\000\n\154\nZ\000\000\000\000\000\000\003=\000\000\nz\000\000\000\000\000\000\003=\000\000\000\000\001M\n\130\n\138\000\000\002\154\001M\003=\000\000\001M\003=\000\000\000\000\000\000\000\000\003=\003=\003=\000\000\001M\000\000\001M\000\000\001M\000\000\001M\000\000\000\000\000\000\000\000\000\000\003=\003=\000\000\000\000\004\154\000\000\001M\000\000\000\000\000\000\000\000\000\000\001M\000\000\003=\003=\001M\000\000\003=\003=\000\000\001M\000\000\000\000\001M\000\000\000\000\000\000\003=\001M\001M\000\238\000\000\001I\000\000\003=\000\000\000\000\001I\001M\003=\001I\000\000\000\000\000\000\001M\003=\000\000\000\000\001M\000\000\001I\000\000\001I\000\000\001I\000\000\001I\000\000\001M\001M\001M\000\000\001M\001M\000\000\000\000\000\000\000\000\001I\000\000\000\000\000\000\001M\000\000\001I\000\000\000\000\000\000\001I\001M\000\000\000\000\000\000\001I\000\000\000\000\001I\000\000\000\000\000\000\001M\001I\001I\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001I\000\000\000\000\000\000\000\000\000\000\001I\000\000\000\000\000\000\001I\001\133\000\000\000\000\000\000\000\000\001\133\000\000\012\153\001\133\001I\001I\001I\000\000\001I\001I\000\000\012\153\000\000\001\133\000\000\001\133\000\000\001\133\001I\001\133\000\000\000\000\000\000\000\000\000\000\001I\000\000\000\000\000\000\000\000\000\000\001\133\000\000\000\000\000\000\000\000\001I\001\133\012\153\000\000\000\000\000\000\000\000\000\000\012\153\000\000\000\000\000\000\000\000\001\133\000\000\000\000\000\000\000\000\001\133\001\133\001\133\000\000\000\000\0019\000\000\000\000\000\000\000\000\0019\000\000\000\157\0019\000\000\000\000\001\133\000\000\000\000\000\000\012\153\000\157\000\000\0019\000\000\0019\000\000\0019\000\000\0019\001\133\001\133\001\133\000\000\001\133\001\133\000\000\000\000\000\000\000\000\000\000\0019\000\000\000\000\000\000\000\000\000\000\0019\000\157\000\000\000\000\001\133\000\000\000\000\000\157\000\000\000\000\000\000\000\000\0019\000\000\000\000\001\133\000\000\0019\0019\0019\000\000\001\213\000\000\000\000\000\000\000\000\001\213\000\000\015\130\001\213\000\000\002\130\000\000\0019\000\000\000\000\000\000\000\157\000\000\001\213\000\000\000\000\000\000\001\213\000\000\001\213\000\000\0019\0019\0019\000\000\0019\0019\000\000\000\000\000\000\000\000\001\213\000\000\000\000\000\000\000\000\000\000\001\213\000\000\000\000\000\000\000\000\0019\015\134\000\000\000\000\001\213\000\000\000\000\001\213\000\000\000\000\000\000\0019\001\213\001\213\000\000\015\146\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\213\000Y\000\000\000\000\001\213\000\000\000Y\000\000\000Y\000\000\000\000\000\000\000\000\005\134\001\213\001\213\000\000\000Y\001\213\001\213\000Y\000\000\000\000\000\000\000Y\000Y\000\000\b\145\001\213\000\000\000\000\000\000\000\000\000\000\000\000\001\213\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000Y\000\000\001\213\000Y\000\000\000\000\000Y\000\000\000\000\000\000\000\000\000Y\000\000\000\000\000\000\000\000\000Y\000Y\000Y\000\000\000\000\000\000\000\000\000\000\000\000\000Y\000Y\000\000\003V\002\190\000\000\000\000\002\130\000\000\006\166\000\000\000Y\002\246\000\000\000Y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\210\000Y\006\198\000\000\000Y\000\000\000\000\003Z\000\000\b\145\b\226\000\000\000\000\000Y\004Y\007\030\000Y\000\000\t&\004Y\003f\000\000\004Y\r\166\001\190\000\000\000\000\000\000\000\000\000Y\002\178\000\000\004Y\003\246\000\000\000\000\004Y\003\250\004Y\004\002\000\000\n\190\005v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004Y\000\000\000\000\000\000\005z\000\000\004Y\007\138\000\000\000\000\004Y\000\000\005\130\005\134\000\000\004Y\000\000\000\000\004Y\000\000\000\000\000\000\000\000\004Y\002\226\000\238\000\000\000\000\000\000\000\000\000\000\000\000\004Y\004Y\r\182\000\000\005\138\000\000\000\000\004Y\004Y\000\000\004r\004Y\000\000\012\022\000\000\000\000\000\000\000\000\012\022\000\000\000\000\004Y\004Y\000\000\000\000\004Y\004Y\000\000\000\000\t\202\000\000\000\000\000\000\000\000\t\202\004Y\012\026\000\000\000\000\000\000\000\000\012\242\004Y\n\002\n\026\n\"\n\n\n*\n\002\n\026\n\"\n\n\n*\004Y\000\000\000\000\000\000\n2\n:\000\000\000\000\000\000\n2\n:\000\000\000\000\nB\000\000\000\000\000\000\000\000\nB\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\238\000\000\000\000\000\000\t\210\n\018\nJ\nR\nb\t\210\n\018\nJ\nR\nb\000\000\000\000\nj\000\000\000\000\000\000\000\000\nj\000\000\000\000\000\000\nr\000\000\0035\000\000\000\000\nr\000\000\0035\000\000\000\000\0035\000\000\000\000\000\000\n\146\000\000\n\154\nZ\000\000\n\146\0035\n\154\nZ\nz\0035\000\000\0035\000\000\nz\000\000\000\000\n\130\n\138\000\000\000\000\000\000\n\130\n\138\0035\015\154\000\000\000\000\000\000\000\000\0035\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0035\000\000\000\000\0035\000\000\000\000\000\000\000\000\0035\0035\0035\003V\002\190\000\000\000\000\002\130\000\000\006\166\000\000\000\000\002\246\000\000\000\000\000\000\0035\000\000\000\000\000\000\0035\000\000\001\210\000\000\006\198\000\000\000\000\000\000\000\000\003Z\0035\0035\b\226\000\000\0035\0035\000\000\000\000\000\000\000\000\023B\000\000\003f\000\000\0035\003r\001\190\000\000\000\000\000\000\015\250\0035\002\178\000\000\000\000\003\246\0035\000\000\000\000\003\250\000\000\004\002\0035\n\190\005v\000\000\000\000\000\000\003V\002\190\000\000\000\000\002\130\000\000\006\166\000\000\005z\002\246\000\000\000\000\000\000\000\000\000\000\000\000\005\130\005\134\000\000\001\210\021\178\006\198\000\000\000\000\000\000\000\000\003Z\000\000\000\000\b\226\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\024\014\003f\005\138\000\000\n\174\001\190\000\000\000\000\004r\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\000\000\n\190\005v\000\000\000\000\000\000\003V\002\190\000\000\000\000\002\130\000\000\006\166\000\000\005z\002\246\000\000\000\000\000\000\000\000\000\000\000\000\005\130\005\134\000\000\001\210\n\198\006\198\000\000\000\000\000\000\000\000\003Z\000\000\000\000\b\226\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\022J\003f\005\138\000\000\n\174\001\190\000\000\000\000\004r\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\005\194\n\190\005v\000\000\000\000\000\000\003V\002\190\000\000\000\000\002\130\000\000\000\000\000\000\005z\002\246\000\000\000\000\000\000\000\000\005\198\000\000\005\130\005\134\000\000\001\210\n\198\000\000\000\000\000\000\000\000\000\000\003Z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\022\170\003f\005\138\000\000\003r\001\190\000\000\000\000\004r\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\005j\000\000\005v\000\000\000\000\t\017\000\000\000\000\000\000\000\000\000\000\003V\002\190\000\000\005z\002\130\000\000\000\000\000\000\000\000\002\246\000\000\005\130\005\134\000\000\005\202\000\000\t\017\000\000\000\000\001\210\000\000\000\000\000\000\000\000\000\000\000\000\003Z\000\000\000\000\000\000\000\000\000\000\006\022\000\000\000\000\005\138\002\225\002\225\000\000\003f\002\225\004r\003r\001\190\000\000\002\225\000\000\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\002\225\003\250\000\000\004\002\005j\000\000\005v\002\225\000\n\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005z\000\000\002\225\000\000\000\000\002\225\002\225\000\000\005\130\005\134\000\000\005\202\002\225\000\000\000\000\002\225\000\000\000\000\002\225\002\225\000\000\002\225\002\225\000\000\002\225\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\138\000\000\t\017\000\000\002\225\000\000\004r\004A\004A\000\000\000\000\004A\002\225\002\225\000\000\002\225\004A\000\000\000\000\000\000\000\000\000\000\004A\000\000\000\000\000\000\004A\000\000\000\000\000\000\000\000\000\000\000\000\004A\022\250\000\000\002\225\023\018\000\000\000\000\002\225\000\000\002\225\000\000\000\000\000\000\004A\000\000\000\000\004A\004A\000\000\000\000\000\000\000\000\000\000\004A\000\000\000\000\004A\000\000\000\000\000\238\004A\000\000\004A\004A\000\000\004A\0035\000\000\000\000\000\000\0035\0035\000\000\000\000\0035\0035\000\000\004A\0035\000\000\000\000\000\000\000\000\000\000\0035\004A\004A\000\000\0035\000\000\0035\000\000\0035\000\000\0035\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0035\015\154\000\000\000\000\0035\015\154\0035\004A\000\000\000\000\0035\000\000\000\000\004A\000\000\0035\000\000\000\000\0035\0035\000\000\000\000\0035\0035\0035\0035\000\000\0035\0035\0035\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0035\000\000\000\000\000\000\0035\000\000\000\000\000\000\0035\000\000\000\000\000\000\000\000\000\000\0035\0035\025\134\000\000\0035\0035\025\182\000\000\0035\0035\012\145\000\000\000\000\000\000\000\000\012\145\000\000\000\000\012\145\000\000\015\250\0035\000\000\000\000\015\250\0035\0035\000\000\012\145\000\000\0035\000\000\012\145\000\000\012\145\000\000\000\000\000\000\000\000\000\000\004\253\000\000\000\000\000\000\000\000\000\000\012\145\000\000\000\000\000\000\000\000\000\000\012\145\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\145\000\000\000\000\012\145\000\000\000\000\003V\002\190\012\145\012\145\002\130\000\000\006\166\000\000\000\000\002\246\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\145\001\210\000\000\006\198\012\145\000\000\000\000\000\000\003Z\000\000\000\000\b\226\000\000\000\000\012\145\012\145\002z\000\000\012\145\012\145\000\000\003f\000\000\000\000\t\014\001\190\000\000\000\000\012\145\000\000\000\000\002\178\026v\000\000\003\246\012\145\000\000\000\000\003\250\000\000\004\002\000\000\n\190\005v\005U\000\000\012\145\000\000\000\000\005U\000\000\000\000\005U\000\000\000\000\005z\000\000\000\000\000\000\000\000\000\000\000\000\005U\005\130\005\134\000\000\005U\000\000\005U\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005U\000\000\000\000\000\000\000\000\000\000\005U\005\138\000\000\000\000\000\000\000\000\007\222\004r\000\000\005U\000\000\000\000\005U\000\000\000\000\000\000\000\000\005U\005U\000\238\000\000\005Y\000\000\000\000\000\000\000\000\005Y\000\000\000\000\005Y\000\000\000\000\000\000\005U\005U\000\000\000\000\005U\000\000\005Y\000\000\000\000\000\000\005Y\000\000\005Y\000\000\005U\005U\000\000\000\000\005U\005U\000\000\000\000\000\000\000\000\005Y\000\000\000\000\000\000\000\000\000\000\005Y\000\000\0035\000\000\000\000\005U\007\222\0035\000\000\005Y\0035\000\000\005Y\000\000\000\000\000\000\005U\005Y\005Y\000\238\0035\000\000\000\000\000\000\0035\000\000\0035\000\000\000\000\000\000\000\000\000\000\000\000\005Y\005Y\000\000\000\000\005Y\0035\015\154\000\000\000\000\000\000\000\000\0035\000\000\000\000\005Y\005Y\000\000\000\000\005Y\005Y\0035\000\000\000\000\0035\000\000\000\000\000\000\000\000\0035\0035\0035\006\001\000\000\000\000\000\000\005Y\006\001\000\000\000\000\006\001\000\000\000\000\000\000\000\000\0035\000\000\005Y\000\000\0035\006\001\000\000\000\000\000\000\006\001\000\000\006\001\000\000\000\000\0035\0035\017\130\000\000\0035\0035\000\000\000\000\000\000\006\001\000\000\000\000\000\000\000\000\000\000\006\001\000\000\000\000\000\000\000\000\015\250\0035\000\000\000\000\006\001\000\000\000\000\006\001\000\000\000\000\000\000\000\000\006\001\006\001\000\238\000\000\000\000\000\000\000\000\000\000\025^\000\000\000\000\000\000\000\000\000\000\003V\002\190\006\001\000\000\002\130\000\000\006\001\000\000\000\000\002\246\000\000\000\000\000\000\000\000\000\000\000\000\006\001\006\001\021>\001\210\006\001\006\001\000\000\000\000\000\000\000\000\003Z\001\202\001\206\000\000\006\001\000\000\000\000\000\000\000\000\000\000\000\000\006\001\000\000\003f\000\000\000\000\003r\001\190\000\000\000\000\001\210\001\214\006\001\002\178\000\000\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\005j\000\000\005v\000\000\000\000\000\000\005\238\000\000\000\000\000\000\001\246\002\162\003V\002\190\005z\002\158\002\130\002\178\004\030\004*\000\000\002\246\005\130\005\134\0046\005\202\000\000\000\000\003\254\000\000\000\000\001\210\000\000\000\000\000\000\000\000\000\000\000\000\003Z\000\000\000\000\004:\000\000\000\000\004\209\000\000\005\138\000\000\006\146\000\000\b\202\003f\004r\000\000\003r\001\190\000\000\000\000\000\000\000\000\026\002\002\178\000\000\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\005j\000\000\005v\000\000\000\000\006.\000\000\000\000\000\000\000\000\000\000\003V\002\190\000\000\005z\002\130\000\000\000\000\000\000\000\000\002\246\000\000\005\130\005\134\000\000\005\202\000\000\006R\000\000\000\000\001\210\000\000\000\000\000\000\000\000\000\000\000\000\003Z\000\000\000\000\000\000\006:\000\000\000\000\000\000\000\000\005\138\003V\002\190\000\000\003f\002\130\004r\003r\001\190\000\000\002\246\000\000\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\001\210\003\250\000\000\004\002\005j\000\000\005v\003Z\000\000\000\000\000\000\000\000\007\129\000\000\000\000\007\129\000\000\000\000\005z\000\000\003f\000\000\000\000\003r\001\190\000\000\005\130\005\134\000\000\005\202\002\178\007\129\007\129\003\246\007\129\007\129\000\000\003\250\000\000\004\002\005j\000\000\005v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\138\006M\000\000\000\000\005z\007\129\004r\003V\002\190\000\000\000\000\002\130\005\130\005\134\000\000\005\202\002\246\000\000\000\000\000\000\000\000\006M\000\000\007\129\000\000\000\000\001\210\000\000\000\000\000\000\000\000\000\000\000\000\003Z\000\000\000\000\005\138\011\166\000\000\000\000\000\000\000\000\004r\003V\002\190\000\000\003f\002\130\000\000\003r\001\190\000\000\002\246\007\129\000\000\007\129\002\178\000\000\000\000\003\246\000\000\000\000\001\210\003\250\000\000\004\002\005j\005\226\005v\003Z\007\129\007\129\000\000\000\000\000\000\007\129\000\000\007\129\000\000\000\000\005z\007\129\003f\000\000\000\000\003r\001\190\000\000\005\130\005\134\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\005j\000\000\005v\000\000\000\000\011\178\000\000\000\000\000\000\000\000\005\138\003V\002\190\000\000\005z\002\130\004r\000\000\000\000\000\000\002\246\000\000\005\130\005\134\000\000\005\202\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000\000\000\000\000\000\000\000\003Z\000\000\000\000\000\000\011\190\000\000\000\000\000\000\000\000\005\138\003V\002\190\000\000\003f\002\130\004r\003r\001\190\000\000\002\246\000\000\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\001\210\003\250\000\000\004\002\005j\000\000\005v\003Z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005z\000\000\003f\000\000\000\000\003r\001\190\000\000\005\130\005\134\000\000\005\202\002\178\000\000\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\005j\000\000\005v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\138\006q\000\000\000\000\005z\000\000\004r\000\000\002\190\000\000\000\000\002\130\005\130\005\134\000\000\005\202\002\246\000\000\000\000\000\000\000\000\006q\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000\000\002\250\000\000\000\000\000\000\000\000\000\000\005\138\000\000\000\000\000\000\000\000\002\254\004r\000\000\000\000\000\000\000\000\000\000\000\000\0032\001\190\000\000\000\000\000\000\000\000\000\000\002\178\000\000\000\000\003:\000\000\000\000\000\000\b\026\b\030\b*\000\000\000\000\005v\000\000\000\000\000\000\006\249\007\030\000\000\000\000\000\000\006\249\000\000\000\000\006\249\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\130\005\134\006\249\000\000\000\000\000\000\006\249\000\000\006\249\000\000\001\181\000\000\000\000\000\000\000\000\001\181\000\000\000\000\001\181\000\000\006\249\000\000\000\000\000\000\005\138\b2\006\249\007\138\001\181\bJ\004r\000\000\001\181\000\000\001\181\006\249\000\000\000\000\006\249\000\000\000\000\000\000\000\000\006\249\006\249\000\238\001\181\000\000\000\000\000\000\000\000\000\000\001\181\000\000\000\000\000\000\000\000\000\000\000\000\006\249\000\000\001\181\000\000\006\249\001\181\000\000\000\000\000\000\000\000\001\181\001\181\001\181\000\000\006\249\006\249\000\000\000\000\006\249\006\249\000\000\000\000\000\000\000\000\000\000\000\000\001\181\000\000\000\000\001\217\001\181\000\000\000\000\000\000\001\217\006\249\000\000\001\217\000\000\000\000\001\181\001\181\000\000\000\000\001\181\001\181\000\000\001\217\000\000\000\000\017\142\001\217\000\000\001\217\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\181\000\000\000\000\000\000\001\217\001\181\000\000\000\000\000\000\000\000\001\217\000\000\000\000\006\005\000\000\000\000\000\000\000\000\006\005\001\217\000\000\006\005\001\217\000\000\000\000\000\000\000\000\001\217\001\217\000\000\000\000\006\005\000\000\000\000\000\000\006\005\000\000\006\005\000\000\000\000\000\000\000\000\000\000\001\217\000\000\000\000\000\000\001\217\000\000\006\005\000\000\000\000\000\000\000\000\000\000\006\005\000\000\001\217\001\217\000\000\000\000\001\217\001\217\000\000\006\005\000\000\000\000\006\005\000\000\000\000\000\000\001\217\006\005\006\005\000\238\000\000\000\000\000\000\001\217\000\000\000\000\000\000\000\000\021\026\000\000\000\000\000\000\000\000\006\005\001\217\012\145\000\000\006\005\000\000\000\000\012\145\000\000\000\000\012\145\000\000\000\000\000\000\006\005\006\005\000\000\000\000\006\005\006\005\012\145\000\000\000\000\000\000\012\145\000\000\012\145\000\000\006\005\000\000\000\000\000\000\004\253\000\000\000\000\006\005\000\000\000\000\012\145\000\000\000\000\000\000\000\000\000\000\012\145\000\000\006\005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\145\000\000\000\000\000\000\000\000\012\145\012\145\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012I\000\000\002\190\012I\000\000\028\002\000\000\012\145\000\000\000\000\028\006\000\000\000\000\012I\000\000\000\000\000\000\000\000\000\000\012I\000\000\012\145\012\145\002z\000\000\012\145\012\145\000\000\000\000\000\000\000\000\012I\000\000\000\000\000\000\012\145\000\000\012I\000\000\026\174\000\000\000\000\012\145\001\002\001\190\000\000\012I\000\000\000\000\012I\000\000\000\000\000\000\012\145\012I\004Y\000\000\000\000\000\000\000\000\004Y\000\000\028\n\004Y\000\000\000\000\000\000\000\000\000\000\000\000\012I\000\000\000\000\004Y\012I\000\000\000\000\004Y\000\000\004Y\000\000\000\000\000\000\028\014\012I\012I\000\000\000\000\012I\000\000\000\000\004Y\000\000\000\000\000\000\000\000\000\000\004Y\b1\b1\000\000\000\000\b1\007\222\000\000\012I\004Y\b1\000\000\004Y\000\000\000\000\000\000\016*\004Y\002\226\000\238\b1\000\000\000\000\000\000\000\000\000\000\000\000\b1\000\000\000\000\000\000\000\000\000\000\004Y\000\000\000\000\000\000\004Y\000\000\000\000\b1\000\000\000\000\b1\b1\000\000\000\000\004Y\004Y\000\000\b1\004Y\004Y\b1\000\000\000\000\000\000\b1\000\000\b1\b1\007J\b1\000\000\000\000\000\000\000\000\001q\004Y\000\000\000\000\000\000\001q\025~\b1\001q\000\000\000\000\000\000\004Y\000\000\000\000\b1\b1\000\000\001q\000\000\001q\000\000\001q\000\000\001q\000\000\000\237\000\000\000\000\000\000\000\000\000\237\000\000\000\000\000\237\000\000\001q\000\000\000\000\b1\000\000\000\000\001q\000\000\000\237\b1\000\000\000\000\000\237\000\000\000\237\000\000\000\000\000\000\001q\000\000\000\000\000\000\000\000\001q\001q\000\238\000\237\000\000\000\000\000\000\000\000\000\000\000\237\000\000\000\000\000\000\000\000\000\000\000\000\001q\000\000\000\237\000\000\000\000\000\237\000\000\000\000\000\000\000\000\000\237\000\237\000\238\000\000\001q\001q\001q\000\000\001q\001q\000\000\000\000\000\000\000\000\000\000\000\000\000\237\000\000\000\000\000\241\000\237\000\000\000\000\000\000\000\241\001q\000\000\000\241\000\000\000\000\000\237\000\237\000\000\000\000\000\237\000\237\001q\000\241\000\000\000\000\000\000\000\241\000\000\000\241\000\000\006\245\000\000\000\000\000\000\000\000\006\245\000\237\000\000\006\245\000\000\000\241\000\000\000\000\000\000\000\000\000\000\000\241\000\237\006\245\000\000\000\000\000\000\006\245\000\000\006\245\000\241\000\000\000\000\000\241\000\000\000\000\000\000\000\000\000\241\000\241\000\238\006\245\000\000\000\000\000\000\000\000\000\000\006\245\000\000\000\000\000\000\000\000\000\000\000\000\000\241\000\000\006\245\000\000\000\241\006\245\000\000\000\000\000\000\000\000\006\245\006\245\000\000\000\000\000\241\000\241\000\000\000\000\000\241\000\241\000\000\000\000\000\000\000\000\000\000\000\000\006\245\000\000\000\000\000\000\006\245\000\000\000\000\000\000\000\000\000\241\000\000\006\201\006\201\000\000\006\245\006\245\016\194\000\000\006\245\006\245\000\241\005\249\000\000\000\000\000\000\000\000\005\249\000\000\000\000\005\249\006\201\006\201\006\201\000\000\000\000\006\245\017b\000\000\000\000\005\249\006\201\000\000\000\000\005\249\000\000\005\249\000\000\005a\007\030\000\000\000\000\000\000\005a\006\201\006\201\005a\000\000\005\249\006\201\000\000\006\201\006\201\006\201\005\249\000\000\005a\000\000\006\201\000\000\005a\000\000\005a\005\249\000\000\000\000\005\249\000\000\000\000\000\000\000\000\005\249\005\249\000\000\005a\006\201\000\000\000\000\000\000\000\000\005a\007\138\000\000\000\000\000\000\000\000\000\000\005\249\000\000\000\000\000\000\005\249\005a\000\000\000\000\000\000\000\000\005a\005a\000\238\000\000\005\249\005\249\000\000\000\000\005\249\005\249\000\000\000\000\000\000\000\000\011\249\000\000\005a\000\000\000\000\011\249\000\000\004\230\011\249\000\000\000\000\005\249\000\000\000\000\000\000\000\000\005a\005a\011\249\000\000\005a\005a\011\249\000\000\011\249\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\249\005a\000\000\000\000\000\000\000\000\011\249\000\000\000\000\000\000\000\000\000\000\000\000\001\202\002~\011\249\000\000\002\130\011\249\000\000\000\000\000\000\000\000\011\249\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\210\001\214\001\230\000\000\000\000\000\000\000\000\011\249\t\190\000\000\001\242\011\249\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\249\011\249\002\138\002\146\011\249\011\249\000\000\002\158\000\000\002\178\004\030\004*\0041\000\000\000\000\000\000\020\242\0041\026Z\004)\0041\011\249\000\000\000\000\004)\000\000\000\000\004)\000\000\000\000\0041\000\000\n\162\004:\0041\000\000\0041\004)\000\000\000\000\000\000\004)\005\134\004)\000\000\000\000\000\000\000\000\0041\000\000\000\000\000\000\026f\000\000\0041\004)\000\000\000\000\000\000\000\000\000\000\004)\000\000\0041\000\000\000\000\0041\000\000\000\000\021\006\004)\0041\000\000\004)\000\000\000\000\000\000\000\000\004)\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0041\000\000\000\000\000\000\0041\004I\000\000\004)\000\000\000\000\004I\004)\004\025\004I\0041\0041\000\000\004\025\0041\0041\004\025\004)\004)\004I\000\000\004)\004)\004I\000\000\004I\004\025\000\000\000\000\000\000\004\025\0041\004\025\000\000\000\000\000\000\000\000\004I\004)\000\000\000\000\000\000\016\234\004I\004\025\000\000\000\000\000\000\000\000\019\214\004\025\000\000\004I\000\000\000\000\004I\000\000\000\000\000\000\004\025\004I\000\000\004\025\000\000\000\000\000\000\000\000\004\025\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004I\000\000\000\000\n\222\004I\000\000\000\000\004\025\000\000\001\202\001\206\004\025\000\000\000\000\004I\004I\000\000\000\000\004I\004I\000\000\004\025\004\025\002\142\000\000\004\025\004\025\000\000\001\210\001\214\001\230\000\000\000\000\000\000\000\000\004I\000\000\000\000\001\242\000\000\000\000\000\000\004\025\000\000\000\000\001\250\020\182\006\205\006\205\000\000\000\000\001\246\002\146\024.\000\000\000\000\002\158\000\000\002\178\004\030\004*\000\000\000\000\004.\000\000\0046\006\205\006\205\006\205\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\205\000\000\000\000\000\000\000\000\000\000\004:\000\000\000\000\000\000\000\000\000\000\000\000\006\205\006\205\000\000\000\000\000\000\006\205\000\000\006\205\006\205\006\205\000\000\0049\000\000\000\000\006\205\000\000\0049\000\000\004!\0049\000\000\000\000\015\138\004!\000\000\000\000\004!\000\000\000\000\0049\000\000\006\205\000\000\0049\000\000\0049\004!\000\000\000\000\000\000\004!\000\000\004!\000\000\000\000\000\000\000\000\0049\000\000\000\000\000\000\000\000\000\000\0049\004!\000\000\004Q\000\000\000\000\000\000\004!\004Q\000\000\000\000\004Q\0049\000\000\004\"\000\000\006\205\0049\000\000\004!\000\000\004Q\000\000\000\000\004!\004Q\000\000\004Q\000\000\000\000\000\000\000\000\000\000\0049\000\000\000\000\000\000\000\000\000\000\004Q\004!\000\000\000\000\000\000\000\000\004Q\000\000\0049\0049\000\000\000\000\0049\0049\000\000\004!\004!\000\000\004Q\004!\004!\000\000\000\000\004Q\011*\000\000\000\000\000\000\000\000\0049\001\202\001\206\000\000\000\000\000\000\000\000\004!\000\000\000\000\004Q\018\018\000\000\000\000\000\000\000\000\000\000\003\254\020b\000\000\001\210\001\214\001\230\000\000\004Q\004Q\000\000\000\000\004Q\004Q\001\242\004m\000\000\000\000\000\000\000\000\000\246\000\000\000\000\002\194\000\000\000\000\000\000\001\246\002\146\004Q\000\000\000\000\002\158\003\178\002\178\004\030\004*\004m\000\000\003\182\020\222\0046\007\149\000\000\000\000\007\149\000\000\000\000\000\000\000\000\000\000\003\186\000\000\000\000\000\000\000\000\000\000\016\174\004:\000\000\000\000\007\149\007\149\000\000\007\149\007\149\024Z\000\000\000\000\017\018\000\000\000\000\000\000\000\000\017*\000\000\000\000\000\000\007m\000\000\000\000\007m\000\000\000\000\000\000\007\149\000\000\000\000\000\000\000\000\0172\000\000\000\000\000\000\004n\000\000\004r\007m\007m\000\000\007m\007m\000\000\000\238\017F\017r\000\000\000\000\004m\004m\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007m\000\000\007\153\000\000\021\154\007\153\000\000\000\000\000\000\000\000\000\000\000\000\007\149\000\000\007\149\000\000\000\000\000\000\007m\000\000\000\000\007\153\007\153\000\000\007\153\007\153\007\149\000\000\000\000\005\234\007\149\000\000\000\000\000\000\007\149\007\137\007\149\000\000\007\137\000\000\007\149\000\000\000\000\000\000\000\000\007\153\000\000\000\000\007m\000\000\007m\000\000\000\000\000\000\007\137\007\137\000\000\007\137\007\137\000\000\000\000\000\000\007m\000\238\000\000\005\234\007m\000\000\000\000\000\000\007m\000\000\007m\000\000\000\000\000\000\007m\000\000\007\137\000\000\rI\rI\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\153\000\000\007\153\000\238\000\000\000\000\rI\rI\rI\0072\000\000\000\000\000\000\000\000\007\153\000\000\rI\005\234\007\153\000\000\000\000\000\000\007\153\000\000\007\153\001\202\001\206\022N\007\153\rI\rI\000\000\000\000\007\137\rI\007\137\rI\rI\rI\000\000\000\000\000\000\000\000\rI\001\210\002\170\001\230\006*\000\000\000\000\005\234\007\137\000\000\000\000\001\242\007\137\000\000\007\137\000\000\000\000\rI\007\137\000\000\001\202\001\206\022\174\000\000\001\246\002\146\000\000\000\000\000\000\002\158\000\000\002\178\004\030\004*\000\000\000\000\000\000\000\000\0046\001\210\002\170\001\230\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\242\000\000\000\000\000\000\000\246\000\000\004:\002\194\000\000\000\000\000\000\000\000\000\000\001\246\002\146\000\000\000\000\004\141\002\158\000\000\002\178\004\030\004*\003\182\000\000\000\000\000\000\0046\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\186\000\000\000\000\000\000\000\000\000\000\016\174\000\000\000\000\004:\000\000\000\000\000\000\000\000\000\000\024Z\000\000\000\000\017\018\000\000\000\000\000\000\000\000\017*\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0172\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017F\017r\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\021\154")) + ((16, "D6Q4H\204\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\021tH\204\000\000\000\000\020\130H\204D6\025\240\000-\000[\\\168\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\160\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\021\182\007V\000\236\000\000\002x\004\174\000\000\000\240\003\142\007\156\000\000\003\198\003\214\b\150\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000*\000\000\000\000\000\000\004\"g<\000\000\000\000\000\000\003\152\000\000\000\000\000\000\005~\006X\000\000\000\000|\200Px\020\130C\b]\030\020\130Q\246M\190\020\130P0\000\000\005\156\000\000D\254\005\242\000\000D\254\000\000\028\128\000\000\000\000\001\244\000\000\003\152\000\000\000\000\000\000\005Z\000\000D\254\000\000\0058xvH:c\252\000\000w\000|\200\000\000LzWf\000\000e\210\021di\000\003\152p&H\204D6\000\000\000\000M\190\020\130S,D\254\006\026u\014\000\000}\166H\204D6Q4\020\130\000\000\000\000\016\154\025:\002\144\007\128\000\000\006\218\007\222\000\000\000\000\000\000\000\000\000\000\020\130\000\000BVd\224D6\000\000\000\000MH\020\130K\198V\208\000\000\006\194\000\000\000\000\007l\000\000\000\000I\164\027\204\024@\002\230\0024\000\000\000\000\000\200\000\000C\b\b\018\bR\020\130\028@\020\130D6D6\000\000M\152M\152\020\130\028@B\128\020\130\000\000\000\000\000\000Q4\020\130\000\000\000\250\000\000V\208p\178p\178\000\000\007\128\000\000\000r\000\000\000\000\021\230g<\127\246\000\000|\200\127\246\000\000|\200\134X\000b\000E\0008\000\000\b`\000\000\b\014\000\000\000\000\b\014\000\000\000\000\000\000|\200\003\152\000\000\000\000U\228g<R\bWf\000\000\000\000Mr\000b\000\000\000\000Wf\t\026g<\000\000NjWfOb\000\000\000\000\000\000\000<\000\000|\200\000\000\001\002oH\000\000g<\005\228g<\000\000C\018\t>\003\152\000\000\000\000EB\000\000\006\222\000\000Yp\t\226\000\000\n\014|\200\011\004\000\000\011\254\000\000\r\180\000\000\000\000\004\b\000\000\000\000\000\000&\228\031hV\208Q\018\020\130V\208\000\000\000b\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000PN\029\018\000\000\000\000\000\000\001\248\021\206p\178\000\000\000\000Q\018\020\130V\208V\208V\208\000\000\000\000\000\000\000\000\000\000\000\000\134\204V\208\135\000r\236\000\000\1354\000\000V\208\000\000W\190\000\000\000\000\n\226\000\000\024\202\000\000\000\000x\156\000\000\135\156y4\000\000\135\208\014L\000\000\000\000w\228\000\000\001\154\000\000\000\000C\230q\014\000\000\000\000T\204\022\024\020\"\024\218\000\000\000\000\000\000\000\000\001H\000\000\000\000[\156\b\022\011L\000\017g<\000\222\011\220\000\000\000\000\b\182\011L\002\216\000\000Q4P\212M\152\020\130\028@\000-\003|\0024\000\000\011.C\bC\b\000-\003|\005\142C\b\000\000h\020\006\158D\254\007\128\002@\136\218\000\000g<d\150g<]\184eXg<\006ng<e\242\000\000\000\000\020\132\0008^z\007\222\0008^\210\000\000h\214\006\158\000\000C\bi.\000\000\006\174\bl]`\000\000\000\000\000\000\000\000\000\000\000\000\003\152\000\000\000\000\bz\000\000\b|\028@\000\000\\>B\128\000\000\026n\000\000\000\000C\b\004\146\000\000\000\000\000\000\000\000Z2\000\000\002\198\000\000G\222\t4\001F\000\000\022dA\170Q4\020\130F\242Q\018\020\130\016\154\016\154\000\000\000\000\000\000\000\000\001\244\023^CF\000\000R\246S\172P\190\020\130\028@\b\180C\b\000\000\tt\000\000TbU\024~P\022\188g<\007\180\000\000Q4\020\130\000\000Q\018\020\130p\178V\208\024\176\000\000Q4\020\130y\184\004.\000\000V\208\024\176g<\002\210\002\216\012\\\000\000\000\000\000\000I\164\004\140\004\140\000\000\012\128q\150\000\000Q\018\020\130V\208\025\170\000\000Q\018\020\130\016\154\022d\016\154\002\238\021\236\000\000\000\000\016\154\012\192\000\000\012\250\000\000\016\154\003\232\r\028\000\000\027F\000\000\t<\000\000\000\000\026L\000\000\017\148\023^\000\000\000\000\000\000\000\000\005\234\000\000\000\000\027F\000\000\028@\000\000\029:\000\000\018\142\024X\000\000\000\000\000\000H\204\000\000\000\000\000\000\000\000\0304\000\000\031.\000\000 (\000\000!\"\000\000\"\028\000\000#\022\000\000$\016\000\000%\n\000\000&\004\000\000&\254\000\000'\248\000\000(\242\000\000)\236\000\000*\230\000\000+\224\000\000,\218\000\000-\212\000\000.\206\000\000/\200\000\0000\194\020\130V\208Z\232J\146\004\140\rzm\238V\208\000\000\000\000\000\000\136\240\000\000\029 \1374\000\000E\134g<\030\026\012\254\000\000\000\000\000\000\000\000m\238\000\000\000\000\028\198\014*\000\000G\142\000\000\000\000\137v\000\000\007\128\000\000\000\000i\000\004\140\r\142g<\n\168\000\000\000\000\001\198\003\152\000\000g<\011\156\000\000\000\000\014\224\000\000\000\000\000\000\023\236g<\011\162\000\000\000\000\030h\000\000\000\000z\016\000\000\031bzF\000\000 \\z\206\000\000!V\014\240\000\000\000\000\000\000\000\000\"PV\208#Jnfnf\000\000\000\000\000\0001\188\000\000\004 \000\000\000\000\000\000q\254\000\000\000\000\007\016\023P\000\000\tL\000\000\000\000_vF\242\000\000\000\000\005\232\000\000\000\000\000\000\n\218\000\000\000\000\000\000\016\154\004\226\024\016\000\000\n6\000\000\005\220\000\0002\182\000\000\b\b\000\000\006\214\000\0003\176\000\000\015x\007\208\000\0004\170o\n\000\000&\144\000\000\nF\b\202\000\0005\164\000\000\b\214\t\196\000\0006\158\000\000r\132\n\190\000\0007\152\t\b\024*\000\000\011@\011\184\000\0008\146\000\000\t\186\012\178\000\0009\140\000\000\011\172\r\172\000\000:\134\014\166\000\000;\128\015\160\019\136\000\000\000\000\000\000\012:\000\000\000\000\t\252\000\000\000\000\015z\000\000\n\030\000\000\000\000\000\000\014\222\000\000\015\014\000\000\000\000K\128\004\140\015\196q\150Wf\000b\000\000\000\000q\150\000\000\000\000\000\000q\150\000\000\015\156\000\000\000\000\000\000\000\000\000\000\000\000<zV\208\000\000\000\000\015\234\000\000=t\000\000>n\000\000$D\000\000\000\000\005\182\000\000\000\000V\208\000\000\000\000~\172\012~\000\000\000\000G\222\000\000\011\240\000\000\000\000X\164\000\000\012\234\000\000\000\000\006@\002\154\000\000\000\000\022d\024\156\007\128\000\000B\198\000\000 b\025\212\022,\000\000\000\000\011\212\000\000\000\000\002\026\026LO.\000\000\025R\000\000\r\246\000\000\000\000\012\206\000\000\000\000i\152\005\136\006@\000\000\000\000\011\188\000\000\000\000\rL\000\000\000\000\000\000\020\130\028@\004\186\000\000\000\000\022\218\002\230\0024\003|\028@u\142C\b\026\b\028@u\230\015\138\000\000\000\000\003|\000\000Ef\020\130\021<\000\000\003l\016\018\000\000\016\020\002\216W\232\007\240\000\000\015\230\015ni\000\tNg<Ah\020p\r,\004\b\000\000C\216\016*\000\000\007\240\000\000\000\000\016FWf_\200\000\000frW\232\016\022Wfj4`\146\004\b\015\246\000\000\000\000\000\000\020\130\128\228\000\000V\208nf\000\000\000\000\016z\000\000\000\000\000\000?h\016\164p\178@bj\158\000\000\000\000D\160\000\000\nn\000\000R\184\000\000\029\172\000\000C\b\011h\000\000nf\000\000\020\130\028@nf\000\000\023\212\025:\002\144\003\152\129lC\b{`nf\000\000\002\230\003,\0024\003|nf\130\198\002\230\0024\003|nf\130\198\000\000\000\000\003|nf\000\000H\204D6V\208\025\170\000\000\000\000H\204D6M\152\020\130\028@nf\000\000\025\240\000-\000[\015\208g<\012J\016\152\129\220\000\000nf\000\000Ef\020\130\021<t\182\027\150\nT\001\254\r\176\015\226\020\130nf\000\000\020\130nf\000\000\021<\000\000\000\000\000\000\000\240\004\174\027\150nf\000\000Wf\016\178Wf\019\234\016\144Wf\127>vfnf\000\000g<g<\019\174\004\014\000\184\0008\131F\000\000\000\184\0008\131F\000\000\023\212\002\230\005 \025\140\011X\000\000\131F\000\000\0024\016\012C\bnfqT\002\230\0024\016\016C\bnfqT\000\000\000\000\006j\000\000nf\000\000C\b\1304nf\000\000\006j\000\000Px\020\130C\bnf\000\000Ef\020\130\021<o\\\021<\000\000\000\240\004\174B|\025:\020L\003\142\000\000\004\136D\254\014\164\000\000\016\150\016H\026\236\020\130J\ng<\n\168\000\000J\248\020L\004\222\012\210\000\000\nd\000\000\016\168\0160g<G\170\000\000\020R\t\192\r\150\000\000\012X\000\000\016\186\016Xi\000\r\176g<N@G\170\000\000O8\020\130\026\236\016\242\000\184\000\184\000\000\000:\026\236g<\014\222\000b\000\000g<\t>\n8\000\000\000\000j\242\000\000\000\000\bT\026\236k\170G\170\000\000\020\130g<\r\144g<XpG\170\000\000\014\030\000\000\000\000G\170\000\000\000\000J\248\000\000nf\131\158\020L\003\142\004\136\016\222\016\140\026\236nf\131\158\000\000\000\000\020L\003\142\004\136\016\226\016v\135\248LpWf\017\n\135\248\134X\020p\017\016\135\248Wf\017\022\135\248lbl\226\000\000\127T\000\000\000\000nf\133L\020L\003\142\004\136\017&\016\174\135\248nf\133L\000\000\000\000\000\000g<\000\000\000\000\000\000\000\000\000\000\000\000nf\000\000\132\030\020\130D\254\017:u\014\000\000}\166\132\030\000\000\000\000\133\188\020\130D\254\017D\016\216H:\134X\007\240\017\136\000\000\000\000mbo\\\020\130\000\000{\148\021<\000\000\000\000}\166\133\188\000\000\000\000\000\000v\214E\226H\146\007\240\017\154\000\000\000\000\000\000o\\\020\130\000\000\007\240\017\158\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\138B|\020L\003\142\004\136\017|r\236\023\254\020\130K\198T\028\020p\004\b\007\240\017~\t\180\000\000\000\000\017,\000\000\000\000[\n\000\000\0062\rN\000\000\012\246\000\000\017\132\017\022g<X\236\017\150\n\174\000\000\000\000\017F\000\000\000\000\020\170\006\192\014\028\000\000\017\162st\137\168\004\140\017>g<\014>\000\000\000\000\017`\000\000\000\000\000\000[\n\000\000\n\186\014\144\000\000\015\016\000\000\017\204\017Xi\000\000\000\017\216s\252\137\234\004\140\017tg<\015H\000\000\000\000\017\136\000\000\000\000\000\000\020\130\000\000[\n\000\000\020\164\020\130\023\254\023\254w\140H\204\020\130\128\228V\208\015R\000\000\004\146\000\184\000\000\tH\023\254g<\015\026\007\128\000\000\020\130V\208r\236\023\254\n\028\023\254\000\000E\028F\004\000\000a\018\000\000\000\000a\172\000\000\000\000bF\000\000\rf\023\254b\224\128\228V\208\015R\000\000\000\"\000\000\000\000\135\248\014r\000\000\000\000Ub\017\234\000\000[\n\000\000\023\254Ub[\n\000\000\020\130g<[\n\000\000\015L\000\000\000\000[\n\000\000\000\000T\028\000\000\128\022\135\248\017\164\023\254\128nr\236\000\000nf\132v\020L\003\142\004\136\017\254r\236nf\132v\000\000\000\000\000\000\133\242Q\018\000\000\000\000\000\000\000\000\000\000\000\000\130nnf\000\000\132\030\000\000\000\000\000\000\000\000nf\133\242\000\000\018:\000\000\000\000\130n\018V\000\000nf\133\242\000\000\000\000\016\018\000\000\000\000g\188\005\140\000\000\000\000\025\170\000\000g<\016J\000\000T\028\016\228\000\000\000\000\000\000\r\250\000\000\000\000\000\000P\190\020\130\028@\000\228\000\000Sb\000\000\012b\000\000\007\000\000\000\000\000\018\\\000\000\018\148w\228\000\000A\\\018n\000\000\000\000\018d\027\004\027\130\021<o\\\027\150\020\130\000\000}\166\000\000\000\000\000\000\000\000\000\000\000\000\000\000tt\027\150\020\130\000\000\b\216u\014\000\000}\166\000\000\018n\027\004\027\130}\166\000\000\018\132\000\000\005\210\014\132\020\130jF\000\000\000\000\028\000lB\000\000\000\000\018\020\000\000\018lg<\000\000\014\208\011h\000b\000\000\000\000g<\011\156\012\150\000\000g<\r\144\007\240\018\152\000\000\000\000|&\000\000\000\000H:\000\000}\166\000\000\018\156\027\004\028|\132\246\000\000\000\000\000\000\000\000\r\186|\184H:\000\000}\166\000\000\018\158\027\004\028|\132\246\000\000\017\002\000\000\000\000\r\\\000\000nf\000\000\018\176\000\000\000\000\018\018\000\000\018\"\000\000\0188\000\000\000\000Q\246\018<\000\000\000\000&\004\\\168\018\214\000\000\000\000\000\000\011`\016>c\134\018\216\000\000\000\000\000\000\000\000\000\000\000\000\018V\000\000\027\150\000\000\018n\000\000g<\000\000\015\026\000\000\000\000\018t\000\000\000\000\0008\000\000\014\164\000\000\000\000\000\000\014\134\000\000\014\180\000\000\018z\000\000V\208\024\176\000\000\000\000\0178\018|\000\000\000\000\018p\0182F\242\003\152}2\000\000\000\000\000\000\000\000\000\000\134\180\000\000\000\000\019\022\000\000\138\024\000\000\015\152\019\"\000\000\0190\000\000G\222G\222\136~\136~\000\000\000\000nf\136~\000\000\000\000\000\000nf\136~\018\160\000\000\018\166\000\000"), (16, "\tM\tM\000\006\001\002\001\190\tM\002\186\002\190\tM\002\234\002\130\tM\003\177\tM\004B\002\246\tM\024\006\tM\tM\tM\001\182\tM\tM\tM\001\210\004a\004a\004F\002\250\tM\003>\003B\t\254\tM\001\206\tM\024\n\003F\000\238\002\254\001\186\tM\tM\003\214\003\218\tM\003\222\0032\003\234\003\242\006\226\004\210\tM\tM\002\178\001\206\004\014\003:\tM\tM\tM\b&\b*\b6\bJ\004^\005v\tM\tM\tM\tM\tM\tM\tM\tM\tM\b\190\000\238\tM\004\018\tM\tM\003\177\b\202\b\226\t6\005\130\005\134\tM\tM\tM\r\202\tM\tM\tM\tM\tM\002\154\004a\r\250\tM\006\190\tM\tM\019\178\tM\tM\tM\tM\tM\tM\005\138\b>\tM\tM\tM\bV\004r\tJ\003\146\tM\tM\tM\tM\r!\r!\024\014\004\154\007z\r!\003\181\r!\r!\025\150\r!\r!\r!\r!\001f\r!\r!\003\137\r!\r!\r!\004\214\r!\r!\r!\r!\004a\r!\000\238\r!\r!\r!\r!\r!\r!\r!\r!\007\234\007\r\006\166\r!\004\226\r!\r!\r!\r!\r!\000\238\r!\r!\000\238\r!\003\238\r!\r!\r!\000\238\007\r\r!\r!\r!\r!\r!\r!\r!\000\238\r!\r!\r!\r!\r!\r!\r!\r!\r!\r!\r!\003\181\r!\r!\006j\r!\r!\001*\019\166\003\150\004a\r!\r!\r!\r!\r!\001j\r!\r!\r!\r!\r!\r!\025\154\r!\r!\006n\r!\r!\004a\r!\r!\r!\r!\r!\r!\r!\r!\r!\r!\r!\r!\r!\007\r\004a\r!\r!\r!\r!\001\181\001\181\001\181\011f\b2\001\181\002N\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\002R\001\181\006\170\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\003\134\003\138\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\007\002\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\011n\001\181\001\181\001\181\001\181\001\181\014\146\001\181\004a\001r\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\bn\001\181\005\186\001\181\001\181\017\154\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\001\181\014\214\001\181\001\181\001\181\001\181\001\181\n\133\n\133\004a\004a\007:\n\133\004!\n\133\n\133\007%\n\133\n\133\n\133\n\133\000\238\n\133\n\133\004a\n\133\n\133\n\133\007B\n\133\n\133\n\133\n\133\015\166\n\133\007\234\n\133\n\133\n\133\n\133\n\133\n\133\n\133\n\133\003\134\003\138\014\150\n\133\000\238\n\133\n\133\n\133\n\133\n\133\000\238\n\133\n\133\003U\n\133\016\230\n\133\n\133\n\133\b\"\000\238\n\133\n\133\n\133\n\133\n\133\n\133\n\133\003U\n\133\n\133\n\133\n\133\n\133\n\133\n\133\n\133\n\133\n\133\n\133\004!\n\133\n\133\006\222\n\133\n\133\002\142\018\246\007\202\007*\n\133\n\133\n\133\n\133\n\133\001\218\n\133\n\133\n\133\n\133\n\133\tb\016\006\t\146\n\133\001\130\n\133\n\133\007\206\n\133\n\133\n\133\n\133\n\133\n\133\n\133\n\133\n\133\n\133\n\133\n\133\n\133\006\254\n\133\n\133\n\133\n\133\n\133\003\205\003\205\001f\007\150\rE\003\205\003\137\003\205\003\205\001\222\003\205\003\205\003\205\003\205\001\146\003\205\003\205\rE\003\205\003\205\003\205\000\238\003\205\003\205\003\205\003\205\003\001\003\205\012\018\003\205\003\205\003\205\003\205\003\205\003\205\003\205\003\205\015V\005R\004a\003\205\b\242\003\205\003\205\003\205\003\205\003\205\015\150\003\205\003\205\012\022\003\205\000\n\003\205\003\205\003\205\015^\004a\003\205\003\205\003\205\003\205\003\205\003\205\003\205\004a\003\205\003\205\003\205\003\205\003\205\003\205\003\205\003\205\003\205\003\205\003\205\000\238\tZ\t\138\003\001\003\205\003\205\b\246\t\018\b\006\007*\003\205\003\205\003\205\003\205\003\205\004a\003\205\003\205\003\205\003\205\003\205\tb\006u\t\146\003\205\006\017\003\205\003\205\b\n\003\205\003\205\003\205\003\205\003\205\003\205\003\205\003\205\003\205\003\205\003\205\003\205\003\205\006u\003\205\003\205\003\205\003\205\003\205\003\193\003\193\0196\007\150\003\029\003\193\t\"\003\193\003\193\004r\003\193\003\193\003\193\003\193\001\198\003\193\003\193\018\254\003\193\003\193\003\193\000\238\003\193\003\193\003\193\003\193\001v\003\193\007\234\003\193\003\193\003\193\003\193\003\193\003\193\003\193\003\193\003\134\018B\019>\003\193\000\238\003\193\003\193\003\193\003\193\003\193\005\249\003\193\003\193\001\206\003\193\018V\003\193\003\193\003\193\015>\006\017\003\193\003\193\003\193\003\193\003\193\003\193\003\193\017\210\003\193\003\193\003\193\003\193\003\193\003\193\003\193\003\193\003\193\003\193\003\193\023~\tZ\t\138\002f\003\193\003\193\t%\017\222\025F\007*\003\193\003\193\003\193\003\193\003\193\002v\003\193\003\193\003\193\003\193\003\193\tb\012\229\t\146\003\193\015\n\003\193\003\193\025J\003\193\003\193\003\193\003\193\003\193\003\193\003\193\003\193\003\193\003\193\003\193\003\193\003\193\012\229\003\193\003\193\003\193\003\193\003\193\n\001\n\001\001\234\007\150\007\030\n\001\012V\n\001\n\001\006\254\n\001\n\001\n\001\n\001\004a\n\001\n\001\012\233\n\001\n\001\n\001\000\238\n\001\n\001\n\001\n\001\004a\n\001\012Z\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\012\233\001\206\t%\n\001\002j\n\001\n\001\n\001\n\001\n\001\022^\n\001\n\001\t)\n\001\012\142\n\001\n\001\n\001\000\238\014>\n\001\n\001\n\001\n\001\n\001\n\001\n\001\000\238\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\004a\n\001\n\001\002\214\n\001\n\001\t\202\022f\002&\004a\n\001\n\001\n\001\n\001\n\001\005\241\n\001\n\001\n\001\n\001\n\001\n\001\b.\n\001\n\001\014F\n\001\n\001\007.\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\n\001\006\254\004a\n\001\n\001\n\001\n\001\t\249\t\249\004\242\0022\n\174\t\249\t)\t\249\t\249\000\238\t\249\t\249\t\249\t\249\007j\t\249\t\249\004a\t\249\t\249\t\249\025\174\t\249\t\249\t\249\t\249\t\021\t\249\004B\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\018\142\004a\007^\t\249\025\178\t\249\t\249\t\249\t\249\t\249\001\238\t\249\t\249\000\238\t\249\012\166\t\249\t\249\t\249\018\154\003^\t\249\t\249\t\249\t\249\t\249\t\249\t\249\000\238\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\003b\t\249\t\249\007\166\t\249\t\249\001f\003\137\011>\t\021\t\249\t\249\t\249\t\249\t\249\002\190\t\249\t\249\t\249\t\249\t\249\t\249\006}\t\249\t\249\003\018\t\249\t\249\011B\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\t\249\006}\t\021\t\249\t\249\t\249\t\249\n\t\n\t\012.\n\218\003\018\n\t\n\230\n\t\n\t\003\n\n\t\n\t\n\t\n\t\003\022\n\t\n\t\003j\n\t\n\t\n\t\000\238\n\t\n\t\n\t\n\t\001\134\n\t\012\158\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\003n\004V\003\169\n\t\003\158\n\t\n\t\n\t\n\t\n\t\000\238\n\t\n\t\012\162\n\t\012\186\n\t\n\t\n\t\003\026\015\174\n\t\n\t\n\t\n\t\n\t\n\t\n\t\005\241\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\b\186\n\t\n\t\004b\n\t\n\t\006\182\006\206\007\170\007*\n\t\n\t\n\t\n\t\n\t\004N\n\t\n\t\n\t\n\t\n\t\n\t\006\133\n\t\n\t\003\162\n\t\n\t\007\214\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\006\133\004B\n\t\n\t\n\t\n\t\t\233\t\233\001\222\007\150\007\222\t\233\012\018\t\233\t\233\006\254\t\233\t\233\t\233\t\233\001\206\t\233\t\233\019\234\t\233\t\233\t\233\000\238\t\233\t\233\t\233\t\233\001\150\t\233\012\234\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\007\234\006\214\016R\t\233\007z\t\233\t\233\t\233\t\233\t\233\004R\t\233\t\233\000\238\t\233\012\218\t\233\t\233\t\233\026.\t\158\t\233\t\233\t\233\t\233\t\233\t\233\t\233\012:\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\162\t\233\t\233\b\229\t\233\t\233\004\174\005\002\012>\007*\t\233\t\233\t\233\t\233\t\233\011f\t\233\t\233\t\233\t\233\t\233\t\233\b\146\t\233\t\233\b.\t\233\t\233\b\158\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\t\233\000\238\012V\t\233\t\233\t\233\t\233\t\241\t\241\019b\007\150\r\014\t\241\003\018\t\241\t\241\015\018\t\241\t\241\t\241\t\241\023\138\t\241\t\241\r.\t\241\t\241\t\241\000\238\t\241\t\241\t\241\t\241\019j\t\241\012\158\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\005&\007z\b\229\t\241\015\194\t\241\t\241\t\241\t\241\t\241\bA\t\241\t\241\r~\t\241\012\238\t\241\t\241\t\241\r\146\012\134\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\158\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\012\138\t\241\t\241\b\225\t\241\t\241\022>\019B\012\214\007*\t\241\t\241\t\241\t\241\t\241\002\142\t\241\t\241\t\241\t\241\t\241\t\241\n\218\t\241\t\241\n\230\t\241\t\241\016\130\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\t\241\000\238\023\178\t\241\t\241\t\241\t\241\n)\n)\022\234\007\150\005\253\n)\t\017\n)\n)\019&\n)\n)\n)\n)\012f\n)\n)\r\150\n)\n)\n)\000\238\n)\n)\n)\n)\022\242\n)\005.\n)\n)\n)\n)\n)\n)\n)\n)\012j\006*\b\225\n)\n\174\n)\n)\n)\n)\n)\b9\n)\n)\000\238\n)\r\002\n)\n)\n)\011\030\0056\n)\n)\n)\n)\n)\n)\n)\012:\n)\n)\n)\n)\n)\n)\n)\n)\n)\n)\n)\018J\n)\n)\011Z\n)\n)\022\134\001\206\r\026\007*\n)\n)\n)\n)\n)\001\206\n)\n)\n)\n)\n)\n)\n\218\n)\n)\n\230\n)\n)\016\158\n)\n)\n)\n)\n)\n)\n)\n)\n)\n)\n)\n)\n)\012f\006\186\n)\n)\n)\n)\n\025\n\025\015\026\007\150\004B\n\025\b\249\n\025\n\025\002\154\n\025\n\025\n\025\n\025\014\202\n\025\n\025\rB\n\025\n\025\n\025\000\238\n\025\n\025\n\025\n\025\004\214\n\025\014n\n\025\n\025\n\025\n\025\n\025\n\025\n\025\n\025\014\206\006\202\026\158\n\025\007\n\n\025\n\025\n\025\n\025\n\025\000\238\n\025\n\025\000\238\n\025\r\030\n\025\n\025\n\025\027\170\005>\n\025\n\025\n\025\n\025\n\025\n\025\n\025\012\134\n\025\n\025\n\025\n\025\n\025\n\025\n\025\n\025\n\025\n\025\n\025\011v\n\025\n\025\011\154\n\025\n\025\015\030\019n\rr\007*\n\025\n\025\n\025\n\025\n\025\b\249\n\025\n\025\n\025\n\025\n\025\n\025\014Z\n\025\n\025\t\014\n\025\n\025\025\166\n\025\n\025\n\025\n\025\n\025\n\025\n\025\n\025\n\025\n\025\n\025\n\025\n\025\014^\t.\n\025\n\025\n\025\n\025\n\017\n\017\b\021\007\150\bE\n\017\026\182\n\017\n\017\000\238\n\017\n\017\n\017\n\017\014\250\n\017\n\017\014r\n\017\n\017\n\017\000\238\n\017\n\017\n\017\n\017\004\214\n\017\014\130\n\017\n\017\n\017\n\017\n\017\n\017\n\017\n\017\014\254\022j\017j\n\017\000\238\n\017\n\017\n\017\n\017\n\017\000\238\n\017\n\017\014\134\n\017\r2\n\017\n\017\n\017\tv\019:\n\017\n\017\n\017\n\017\n\017\n\017\n\017\006\001\n\017\n\017\n\017\n\017\n\017\n\017\n\017\n\017\n\017\n\017\n\017\015&\n\017\n\017\015\210\n\017\n\017\005\245\003\157\t~\007*\n\017\n\017\n\017\n\017\n\017\026\186\n\017\n\017\n\017\n\017\n\017\n\017\015*\n\017\n\017\t\142\n\017\n\017\027J\n\017\n\017\n\017\n\017\n\017\n\017\n\017\n\017\n\017\n\017\n\017\n\017\n\017\022b\n\198\n\017\n\017\n\017\n\017\n!\n!\rM\007\150\n\254\n!\b\253\n!\n!\003\022\n!\n!\n!\n!\001\206\n!\n!\019f\n!\n!\n!\000\238\n!\n!\n!\n!\005F\n!\011f\n!\n!\n!\n!\n!\n!\n!\n!\014\238\bI\025z\n!\023\234\n!\n!\n!\n!\n!\000\238\n!\n!\017\158\n!\rF\n!\n!\n!\027\018\020\026\n!\n!\n!\n!\n!\n!\n!\007z\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\020\006\n!\n!\006V\n!\n!\011\"\022\166\011R\005J\n!\n!\n!\n!\n!\b\253\n!\n!\n!\n!\n!\n!\024\022\n!\n!\019\130\n!\n!\b9\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\n!\024\026\004\214\n!\n!\n!\n!\nq\nq\026b\001\002\001\190\nq\014\242\nq\nq\000\238\nq\nq\nq\nq\002\006\nq\nq\022\238\nq\nq\nq\019\006\nq\nq\nq\nq\020\030\nq\025~\nq\nq\nq\nq\nq\nq\nq\nq\011\214\rY\022\198\nq\026\154\nq\nq\nq\nq\nq\004B\nq\nq\019\190\nq\rR\nq\nq\nq\001\222\022\246\nq\nq\nq\nq\nq\nq\nq\004\245\nq\nq\nq\nq\nq\nq\nq\nq\nq\nq\nq\028#\nq\nq\023\150\nq\nq\024V\007z\001\002\001\190\nq\nq\nq\nq\nq\028\019\nq\nq\nq\nq\nq\nq\004R\nq\nq\b=\nq\nq\002j\nq\nq\nq\nq\nq\nq\nq\nq\nq\nq\nq\nq\nq\000\238\011\130\nq\nq\nq\nq\003\189\003\189\026\170\012\182\r\138\003\189\r\162\003\189\003\189\019\198\003\189\003\189\003\189\003\189\004y\003\189\003\189\000\238\003\189\003\189\003\189\002\226\003\189\003\189\003\189\003\189\027\243\003\189\r\170\003\189\003\189\003\189\003\189\003\189\003\189\003\189\003\189\004y\r\190\019\198\003\189\r\238\003\189\003\189\003\189\003\189\003\189\023&\003\189\003\189\014\026\003\189\024Z\003\189\003\189\003\189\002\226\0256\003\189\003\189\003\189\003\189\003\189\003\189\003\189\015r\003\189\003\189\003\189\003\189\003\189\003\189\003\189\003\189\003\189\003\189\003\189\015\154\tZ\t\138\003\254\003\189\003\189\004y\015\182\015\186\007\170\003\189\003\189\003\189\003\189\003\189\015\226\003\189\003\189\003\189\003\189\003\189\tb\015\246\t\146\003\189\016\014\003\189\003\189\025^\003\189\003\189\003\189\003\189\003\189\003\189\003\189\003\189\003\189\003\189\003\189\003\189\003\189\016\"\003\189\003\189\003\189\003\189\003\189\002\r\002\r\027\174\001\222\016N\002\r\016b\002\190\002\r\017b\002\130\002\r\tr\002\r\017n\002\246\002\r\006&\002\r\002\r\002\r\000\238\002\r\002\r\002\r\001\210\025:\tz\017\230\002\250\002\r\002\r\002\r\002\r\002\r\t\130\002\r\025j\017\242\018^\002\254\018v\002\r\002\r\002\r\002\r\002\r\019\014\0032\001\190\019\018\002\r\027>\002\r\002\r\002\178\019J\019N\003:\002\r\002\r\002\r\b&\b*\b6\019v\012r\005v\002\r\002\r\002\r\002\r\002\r\002\r\002\r\002\r\002\r\019z\tZ\t\138\019\162\002\r\002\r\020N\020R\020v\002\190\005\130\005\134\002\r\002\r\002\r\020z\002\r\002\r\002\r\002\r\002\r\012z\020\138\012\202\002\r\020\154\002\r\002\r\020\166\002\r\002\r\002\r\002\r\002\r\002\r\005\138\b>\002\r\002\r\002\r\bV\004r\020\218\020\222\002\r\002\r\002\r\002\r\nY\nY\001\002\001\190\021*\nY\025n\002\190\nY\021R\002\130\nY\nY\nY\021V\002\246\nY\021f\nY\nY\nY\027B\nY\nY\nY\001\210\021\182\nY\021\214\002\250\nY\nY\nY\nY\nY\nY\nY\022\022\022:\022J\002\254\022r\nY\nY\nY\nY\nY\022v\0032\001\190\022\130\nY\022\146\nY\nY\002\178\022\174\022\190\003:\nY\nY\nY\b&\b*\b6\022\210\nY\005v\nY\nY\nY\nY\nY\nY\nY\nY\nY\022\254\nY\nY\023\002\nY\nY\023\014\023\030\0232\003\022\005\130\005\134\nY\nY\nY\024&\nY\nY\nY\nY\nY\nY\024~\nY\nY\024\166\nY\nY\025\014\nY\nY\nY\nY\nY\nY\005\138\b>\nY\nY\nY\bV\004r\025\030\025\186\nY\nY\nY\nY\nU\nU\001\002\001\190\025\194\nU\025\210\002\190\nU\025\222\002\130\nU\nU\nU\026B\002\246\nU\026V\nU\nU\nU\026\134\nU\nU\nU\001\210\026\142\nU\026\202\002\250\nU\nU\nU\nU\nU\nU\nU\026\242\027*\027Z\002\254\027f\nU\nU\nU\nU\nU\027n\0032\001\190\027w\nU\027\135\nU\nU\002\178\027\154\027\182\003:\nU\nU\nU\b&\b*\b6\027\211\nU\005v\nU\nU\nU\nU\nU\nU\nU\nU\nU\027\227\nU\nU\027\255\nU\nU\0283\028O\028Z\028\143\005\130\005\134\nU\nU\nU\028\163\nU\nU\nU\nU\nU\nU\028\171\nU\nU\028\231\nU\nU\028\239\nU\nU\nU\nU\nU\nU\005\138\b>\nU\nU\nU\bV\004r\000\000\000\000\nU\nU\nU\nU\002Y\002Y\000\000\000\000\000\000\002Y\000\000\002\190\002Y\000\000\002\130\002Y\tr\002Y\000\000\002\246\002Y\000\000\002Y\002Y\002Y\000\000\002Y\002Y\002Y\001\210\003\001\tz\000\000\002\250\002Y\002Y\002Y\002Y\002Y\t\130\002Y\000\000\000\000\000\000\002\254\000\000\002Y\002Y\002Y\002Y\002Y\000\000\0032\001\190\000\000\002Y\000\n\002Y\002Y\002\178\001\206\000\000\003:\002Y\002Y\002Y\b&\b*\b6\b\245\012r\005v\002Y\002Y\002Y\002Y\002Y\002Y\002Y\002Y\002Y\004\205\000\000\002Y\003\001\002Y\002Y\006\142\002\190\000\000\000\000\005\130\005\134\002Y\002Y\002Y\002\001\002Y\002Y\002Y\002Y\002Y\002\154\000\000\004\205\002Y\004a\002Y\002Y\004a\002Y\002Y\002Y\002Y\002Y\002Y\005\138\b>\002Y\002Y\002Y\bV\004r\000\000\004a\002Y\002Y\002Y\002Y\004a\003\n\004a\004\154\004a\004a\004a\004a\004a\004a\004a\018\018\004a\b\225\004a\004a\000\000\004a\004a\004a\000\000\004a\004a\004a\004a\004a\004a\004a\004a\004a\000\000\004a\004a\000\000\000\238\004a\004a\000\238\004a\004a\004a\004a\004a\000\000\004a\004a\004a\004a\004a\004a\004a\004a\000\238\004a\004a\004a\004a\004a\004a\004a\004a\000\238\004a\004a\004a\004a\004a\004a\004a\004a\000\000\000\000\004a\000\000\000\000\004a\004a\004a\000\238\004a\000\000\000\238\004a\004a\004a\004a\004a\004a\004a\004a\004a\004a\007r\004a\004a\000\000\004a\b\225\000\000\004a\015\142\007z\004a\002\130\004a\000\000\000\000\t\021\022.\007~\004a\004a\004a\004a\000\000\000\000\004a\004a\004a\004a\005\029\000\161\004a\000\161\000\000\000\161\000\161\000\161\000\161\000\161\000\161\000\161\005\029\000\161\023R\000\161\000\161\022\158\000\161\000\161\000\000\015\146\000\161\000\161\000\000\000\161\000\161\000\161\000\161\000\000\000\161\000\000\000\161\000\161\000\000\015\158\000\161\000\161\000\000\000\161\000\161\000\161\005\029\000\161\000\000\000\161\000\161\000\161\000\161\000\161\000\161\000\161\000\161\003\022\000\000\000\161\000\161\000\000\007\005\000\161\000\161\005\134\000\161\000\161\000\161\000\161\000\161\000\161\000\161\000\161\000\161\000\000\005\029\000\161\000\000\005\029\000\161\007\005\000\161\000\000\000\161\007\005\001b\004\201\000\161\000\161\000\161\000\161\000\161\000\161\000\161\000\161\000\000\tA\005\190\000\161\001z\000\161\001\138\000\000\002\190\000\222\006\138\002\166\003\246\000\161\004\201\000\000\006^\tf\004\002\000\161\000\161\000\161\000\161\000\000\tA\000\161\000\161\000\161\000\161\002I\002I\rv\000\000\r\130\002I\000\000\002\190\002I\000\000\002\130\002I\000\000\002I\000\000\002\246\002I\000\000\002I\002I\002I\003\n\002I\002I\002I\001\210\000\000\000\000\007\005\002\250\002I\002I\002I\002I\002I\000\000\002I\000\000\000\000\000\000\002\254\000\000\002I\002I\002I\002I\002I\004\026\0032\b:\000\000\002I\000\000\002I\002I\002\178\000\000\000\000\003:\002I\002I\002I\b&\b*\b6\003\001\003\001\005v\002I\002I\002I\002I\002I\002I\002I\002I\002I\000\000\tZ\t\138\000\000\002I\002I\000\000\000\000\000\000\000\000\005\130\005\134\002I\002I\002I\000\n\002I\002I\002I\002I\002I\tb\000\000\t\146\002I\000\000\002I\002I\007\209\002I\002I\002I\002I\002I\002I\005\138\b>\002I\002I\002I\bV\004r\000\000\003\001\002I\002I\002I\002I\002e\002e\000\000\000\000\000\000\002e\000\000\003\022\002e\000\000\007\209\002e\000\000\002e\000\000\000\000\002e\000\000\002e\002e\002e\000\000\002e\002e\002e\007\209\000\000\000\000\007\209\b\178\002e\002e\002e\002e\002e\007\209\002e\000\000\000\000\007\209\000\000\0122\002e\002e\002e\002e\002e\000\000\br\001\190\000\000\002e\000\000\002e\002e\012N\000\000\012^\014b\002e\002e\002e\014v\014\138\014\154\003\001\003\001\016\190\002e\002e\002e\002e\002e\002e\002e\002e\002e\000\000\tZ\t\138\003\001\002e\002e\000\000\000\000\000\000\000\000\002\190\000\000\002e\002e\002e\000\n\002e\002e\002e\002e\002e\tb\000\000\t\146\002e\000\000\002e\002e\001\210\002e\002e\002e\002e\002e\002e\000\000\001*\002e\002e\002e\000\000\022\030\003\001\003\001\002e\002e\002e\002e\002a\002a\000\000\023Z\003\n\002a\023^\n\221\002a\000\000\002\178\002a\012~\002a\000\000\000\000\002a\023\142\002a\002a\002a\000\n\002a\002a\002a\r\018\012\150\000\000\012\174\000\000\002a\002a\002a\002a\002a\014\162\002a\n\221\000\000\r&\023\158\r:\002a\002a\002a\002a\002a\b\222\000\000\003\001\000\000\002a\n\221\002a\002a\n\221\011\146\0062\000\000\002a\002a\002a\n\221\000\000\004\029\006\245\n\221\000\000\002a\002a\002a\002a\002a\002a\002a\002a\002a\0066\tZ\t\138\000\000\002a\002a\000\000\006\146\000\000\000\000\r\246\006\245\002a\002a\002a\000\000\002a\002a\002a\002a\002a\tb\000\000\t\146\002a\000\000\002a\002a\000\238\002a\002a\002a\002a\002a\002a\tZ\t\138\002a\002a\002a\003\001\000\238\000\000\003\001\002a\002a\002a\002a\002M\002M\000\000\000\000\000\000\002M\000\000\tb\002M\t\146\004\029\002M\028?\002M\000\000\000\000\002M\000\000\002M\002M\002M\000\n\002M\002M\002M\006:\000\000\000\000\006\002\b\254\002M\002M\002M\002M\002M\006F\002M\003\001\006:\006R\000\000\006\002\002M\002M\002M\002M\002M\017.\006F\003\001\003\001\002M\006R\002M\002M\000\000\000\000\000\000\000\000\002M\002M\002M\000\000\000\000\025R\t=\b\025\000\000\002M\002M\002M\002M\002M\002M\002M\002M\002M\005\173\tZ\t\138\000\000\002M\002M\000\000\014\186\000\000\000\000\000\000\t=\002M\002M\002M\007*\002M\002M\002M\002M\002M\tb\000\000\t\146\002M\000\000\002M\002M\000\238\002M\002M\002M\002M\002M\002M\000\n\000\000\002M\002M\002M\000\000\000\000\000\000\005\173\002M\002M\002M\002M\002]\002]\003\001\003\001\000\000\002]\000\000\003\022\002]\007\150\tF\002]\018F\002]\005\173\003\001\002]\007\246\002]\002]\002]\000\000\002]\002]\002]\006:\000\000\000\238\006\002\025V\002]\002]\002]\002]\002]\006F\002]\007\250\000\000\006R\000\000\000\000\002]\002]\002]\002]\002]\000\000\br\014\218\000\000\002]\000\000\002]\002]\000\000\000\000\015f\014b\002]\002]\002]\014v\014\138\014\154\007\234\000\000\000\000\002]\002]\002]\002]\002]\002]\002]\002]\002]\000\000\000\238\002]\000\000\002]\002]\000\000\000\000\000\000\000\000\001\206\000\000\002]\002]\002]\000\000\002]\002]\002]\002]\002]\000\000\b9\000\000\002]\b9\002]\002]\001\210\t\170\002]\002]\002]\002]\002]\000\000\000\000\002]\002]\002]\000\000\019\022\000\000\022\166\002]\002]\002]\002]\tI\tI\007\254\000\000\002\154\tI\019\158\002\190\tI\000\000\002\178\tI\000\000\tI\000\000\b9\t\214\019\182\tI\t\250\tI\000\000\tI\tI\tI\000\000\000\000\000\000\000\000\b9\n\014\n&\n.\n\022\n6\000\000\tI\015\142\000\000\000\000\002\130\000\000\tI\tI\n>\nF\tI\002\190\t\150\003\n\002\130\tI\000\000\nN\tI\b9\000\000\000\000\000\000\tI\tI\000\238\012\n\000\000\012\026\000\000\000\000\006\169\tI\tI\t\222\n\030\nV\n^\nn\tI\tI\000\000\015\146\tI\000\000\tI\nv\b9\000\000\000\000\000\000\006\169\017\146\tI\tI\n~\015\158\tI\tI\tI\tI\tI\000\000\000\000\001\206\tI\015\158\tI\tI\000\000\n\158\tI\n\166\nf\tI\tI\026v\000\000\tI\n\134\tI\000\000\005\134\000\000\000\000\tI\tI\n\142\n\150\002\145\002\145\000\000\005\134\000\000\002\145\000\000\002\190\002\145\003^\000\000\002\145\000\000\002\145\003\170\000\000\002\145\002\154\002\145\002\145\002\145\025\230\002\145\002\145\002\145\001\210\000\000\000\000\000\000\003b\002\145\002\145\002\145\002\145\002\145\000\000\002\145\015\142\012\237\000\000\002\130\000\000\002\145\002\145\002\145\002\145\002\145\004\154\003\202\000\000\004\249\002\145\000\000\002\145\002\145\002\178\000\000\000\000\012\237\002\145\002\145\002\145\000\000\000\000\002B\000\000\000\000\006\181\002\145\002\145\t\222\002\145\002\145\002\145\002\145\002\145\002\145\002F\015\146\002\145\000\000\002\145\002\145\006\246\000\000\000\000\000\000\006\181\000\000\002\145\002\145\002\145\015\158\002\145\002\145\002\145\002\145\002\145\000\000\000\000\000\000\002\145\000\000\002\145\002\145\000\000\002\145\002\145\002\145\002\145\002\145\002\145\012\177\000\000\002\145\002\145\002\145\000\000\005\134\000\000\002\246\002\145\002\145\002\145\002\145\002y\002y\000\000\000\000\000\000\002y\012\177\012\177\002y\003j\012\177\002y\003Z\002y\000\000\000\000\002y\000\000\002y\002y\002y\021\130\002y\002y\002y\003f\000\000\000\000\000\000\003n\002y\002y\002y\002y\002y\000\000\002y\000\000\000\000\000\000\000\000\000\000\002y\002y\002y\002y\002y\005v\000\238\000\000\000\000\002y\000\000\002y\002y\000\000\000\000\000\000\007*\002y\002y\002y\000\000\000\000\000\000\000\000\000\000\005\130\002y\002y\t\222\002y\002y\002y\002y\002y\002y\016\146\012\177\002y\000\000\002y\002y\000\000\000\000\000\000\000\000\000\000\000\000\002y\002y\002y\005\138\002y\002y\002y\002y\002y\000\000\000\000\007\150\002y\000\000\002y\002y\000\000\002y\002y\002y\002y\002y\002y\012\173\000\000\002y\002y\002y\000\000\000\238\000\000\000\000\002y\002y\002y\002y\002\133\002\133\000\000\000\000\000\000\002\133\012\173\012\173\002\133\000\000\012\173\002\133\000\000\002\133\000\000\000\000\t\214\000\000\002\133\002\133\002\133\000\000\002\133\002\133\002\133\000\000\000\000\000\000\000\000\000\000\002\133\002\133\002\133\n\022\002\133\000\000\002\133\000\000\000\000\016\150\000\000\000\000\002\133\002\133\002\133\002\133\002\133\000\000\000\238\000\000\000\000\002\133\000\000\002\133\002\133\000\000\000\000\000\000\000\000\002\133\002\133\002\133\000\000\000\000\000\000\000\000\000\000\000\000\002\133\002\133\t\222\n\030\002\133\002\133\002\133\002\133\002\133\000\000\012\173\002\133\000\000\002\133\002\133\000\000\000\000\000\000\000\000\000\238\000\000\002\133\002\133\002\133\000\000\002\133\002\133\002\133\002\133\002\133\000\000\000\000\000\000\002\133\000\000\002\133\002\133\000\000\002\133\002\133\002\133\002\133\002\133\002\133\000\000\000\000\002\133\002\133\002\133\011\166\000\000\000\000\000\000\002\133\002\133\002\133\002\133\002\149\002\149\000\000\000\000\000\000\002\149\000\000\011\174\002\149\000\000\011\186\002\149\000\000\002\149\000\000\000\000\002\149\011\198\002\149\002\149\002\149\011\210\002\149\002\149\002\149\000\000\000\000\000\000\000\000\007\029\002\149\002\149\002\149\002\149\002\149\000\000\002\149\000\000\000\000\000\000\000\000\000\000\002\149\002\149\002\149\002\149\002\149\000\000\007\029\000\000\000\000\002\149\007\029\002\149\002\149\000\000\000\000\000\000\000\000\002\149\002\149\002\149\000\000\000\000\000\000\000\000\000\000\000\000\002\149\002\149\t\222\002\149\002\149\002\149\002\149\002\149\002\149\000\000\000\000\002\149\000\000\002\149\002\149\000\000\000\000\000\000\000\000\000\238\000\000\002\149\002\149\002\149\000\000\002\149\002\149\002\149\002\149\002\149\000\000\000\000\000\000\002\149\000\000\002\149\002\149\000\000\002\149\002\149\002\149\002\149\002\149\002\149\000\000\000\000\002\149\002\149\002\149\007\201\000\000\000\000\005f\002\149\002\149\002\149\002\149\002u\002u\000\000\000\000\000\000\002u\000\000\007\201\002u\000\000\006\002\002u\000\000\002u\000\000\000\000\002u\007\201\002u\002u\002u\007\201\002u\002u\002u\000\000\000\000\000\000\000\000\007\r\002u\002u\002u\002u\002u\000\000\002u\000\000\000\000\000\000\000\000\000\000\002u\002u\002u\002u\002u\000\000\007\r\000\000\000\000\002u\007\r\002u\002u\000\000\000\000\000\000\000\000\002u\002u\002u\000\000\000\000\000\000\000\000\000\000\000\000\002u\002u\t\222\002u\002u\002u\002u\002u\002u\000\000\000\000\002u\000\000\002u\002u\000\000\000\000\000\000\000\000\007\225\000\000\002u\002u\002u\000\000\002u\002u\002u\002u\002u\000\000\000\000\000\000\002u\000\000\002u\002u\000\000\002u\002u\002u\002u\002u\002u\000\000\000\000\002u\002u\002u\007\225\000\000\000\000\b2\002u\002u\002u\002u\002\129\002\129\000\000\000\000\000\000\002\129\000\000\007\225\002\129\000\000\006\002\002\129\000\000\002\129\000\000\000\000\t\214\007\225\002\129\002\129\002\129\007\225\002\129\002\129\002\129\000\000\000\000\000\000\000\000\000\000\002\129\002\129\002\129\n\022\002\129\000\000\002\129\000\000\000\000\000\000\000\000\000\000\002\129\002\129\002\129\002\129\002\129\000\000\000\000\000\000\000\000\002\129\000\000\002\129\002\129\000\000\000\000\000\000\000\000\002\129\002\129\002\129\000\000\000\000\000\000\000\000\000\000\000\000\002\129\002\129\t\222\n\030\002\129\002\129\002\129\002\129\002\129\000\000\000\000\002\129\000\000\002\129\002\129\000\000\000\000\000\000\000\000\000\238\000\000\002\129\002\129\002\129\000\000\002\129\002\129\002\129\002\129\002\129\000\000\000\000\000\000\002\129\000\000\002\129\002\129\000\000\002\129\002\129\002\129\002\129\002\129\002\129\000\000\000\000\002\129\002\129\002\129\007\253\000\000\000\000\000\000\002\129\002\129\002\129\002\129\002}\002}\000\000\000\000\000\000\002}\000\000\006:\002}\000\000\006\002\002}\000\000\002}\000\000\000\000\t\214\007\253\002}\002}\002}\007\253\002}\002}\002}\000\000\000\000\000\000\000\000\000\000\002}\002}\002}\n\022\002}\000\000\002}\000\000\000\000\000\000\000\000\000\000\002}\002}\002}\002}\002}\000\000\000\000\000\000\000\000\002}\000\000\002}\002}\000\000\000\000\000\000\000\000\002}\002}\002}\000\000\000\000\000\000\000\000\000\000\000\000\002}\002}\t\222\n\030\002}\002}\002}\002}\002}\000\000\000\000\002}\000\000\002}\002}\000\000\000\000\000\000\000\000\007\245\000\000\002}\002}\002}\000\000\002}\002}\002}\002}\002}\000\000\000\000\000\000\002}\000\000\002}\002}\000\000\002}\002}\002}\002}\002}\002}\000\000\000\000\002}\002}\002}\007\245\000\000\000\000\000\000\002}\002}\002}\002}\002\165\002\165\000\000\000\000\000\000\002\165\000\000\011\234\002\165\000\000\007\245\002\165\000\000\002\165\000\000\000\000\t\214\007\245\002\165\002\165\002\165\007\245\002\165\002\165\002\165\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002\165\000\000\000\000\000\000\000\000\000\000\002\165\002\165\n>\nF\002\165\000\000\000\000\000\000\000\000\002\165\000\000\nN\002\165\000\000\000\000\000\000\000\000\002\165\002\165\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\165\002\165\t\222\n\030\nV\n^\nn\002\165\002\165\000\000\000\000\002\165\000\000\002\165\nv\000\000\000\000\000\000\000\000\000\238\000\000\002\165\002\165\n~\000\000\002\165\002\165\002\165\002\165\002\165\000\000\000\000\000\000\002\165\000\000\002\165\002\165\000\000\002\165\002\165\002\165\nf\002\165\002\165\000\000\000\000\002\165\n\134\002\165\007\197\000\000\000\000\000\000\002\165\002\165\n\142\n\150\002\141\002\141\000\000\000\000\000\000\002\141\000\000\007\197\002\141\000\000\006\002\002\141\000\000\002\141\000\000\000\000\t\214\007\197\002\141\002\141\002\141\007\197\002\141\002\141\002\141\000\000\000\000\000\000\000\000\000\000\002\141\002\141\002\141\n\022\002\141\000\000\002\141\000\000\000\000\000\000\000\000\000\000\002\141\002\141\002\141\002\141\002\141\000\000\000\000\000\000\000\000\002\141\000\000\002\141\002\141\000\000\000\000\000\000\000\000\002\141\002\141\002\141\000\000\000\000\000\000\000\000\000\000\000\000\002\141\002\141\t\222\n\030\002\141\002\141\002\141\002\141\002\141\000\000\000\000\002\141\000\000\002\141\002\141\000\000\000\000\000\000\000\000\000\238\000\000\002\141\002\141\002\141\000\000\002\141\002\141\002\141\002\141\002\141\000\000\000\000\000\000\002\141\000\000\002\141\002\141\000\000\002\141\002\141\002\141\002\141\002\141\002\141\000\000\000\000\002\141\002\141\002\141\0142\000\000\000\000\000\000\002\141\002\141\002\141\002\141\002\137\002\137\000\000\000\000\000\000\002\137\000\000\011\174\002\137\000\000\011\186\002\137\000\000\002\137\000\000\000\000\t\214\011\198\002\137\002\137\002\137\011\210\002\137\002\137\002\137\000\000\000\000\000\000\000\000\000\000\002\137\002\137\002\137\n\022\002\137\000\000\002\137\000\000\000\000\000\000\000\000\000\000\002\137\002\137\002\137\002\137\002\137\000\000\000\000\000\000\000\000\002\137\000\000\002\137\002\137\000\000\000\000\000\000\000\000\002\137\002\137\002\137\000\000\000\000\000\000\000\000\000\000\000\000\002\137\002\137\t\222\n\030\002\137\002\137\002\137\002\137\002\137\000\000\000\000\002\137\000\000\002\137\002\137\000\000\000\000\000\000\000\000\000\000\000\000\002\137\002\137\002\137\000\000\002\137\002\137\002\137\002\137\002\137\000\000\000\000\000\000\002\137\000\000\002\137\002\137\000\000\002\137\002\137\002\137\002\137\002\137\002\137\000\000\000\000\002\137\002\137\002\137\000\000\000\000\000\000\000\000\002\137\002\137\002\137\002\137\002\157\002\157\000\000\000\000\000\000\002\157\000\000\002\006\002\157\000\000\002\130\002\157\000\000\002\157\000\000\000\000\t\214\000\000\002\157\002\157\002\157\000\000\002\157\002\157\002\157\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\002\157\000\000\002\157\000\000\000\000\000\000\000\000\000\000\002\157\002\157\n>\nF\002\157\000\000\027\146\001\222\000\000\002\157\000\000\002\157\002\157\000\000\000\000\000\000\000\000\002\157\002\157\000\238\015\158\000\000\000\000\000\000\000\000\000\000\002\157\002\157\t\222\n\030\nV\n^\002\157\002\157\002\157\002\190\000\000\002\157\000\000\002\157\002\157\000\000\000\000\000\000\000\000\000\000\005\134\002\157\002\157\002\157\000\000\002\157\002\157\002\157\002\157\002\157\000\000\000\000\000\000\002\157\000\000\002\157\002\157\000\000\002\157\002\157\002\157\nf\002\157\002\157\007\t\000\000\002\157\002\157\002\157\000\000\012\206\003\n\000\000\002\157\002\157\002\157\002\157\002q\002q\000\000\000\000\000\000\002q\007\t\012\226\002q\012\246\007\t\002q\000\000\002q\000\000\000\000\t\214\000\000\002q\002q\002q\000\000\002q\002q\002q\000\000\000\000\000\000\000\000\000\000\002q\002q\002q\n\022\002q\000\000\002q\000\000\000\000\000\000\000\000\000\000\002q\002q\002q\002q\002q\000\000\000\238\000\000\000\000\002q\000\000\002q\002q\000\000\000\000\000\000\000\000\002q\002q\002q\000\000\000\000\000\000\000\000\000\000\000\000\002q\002q\t\222\n\030\002q\002q\002q\002q\002q\000\000\007\t\002q\000\000\002q\002q\000\000\000\000\000\000\000\000\000\000\000\000\002q\002q\002q\000\000\002q\002q\002q\002q\002q\000\000\000\000\000\000\002q\000\000\002q\002q\000\000\002q\002q\002q\002q\002q\002q\000\000\000\000\002q\002q\002q\000\000\000\000\000\000\000\000\002q\002q\002q\002q\002m\002m\000\000\000\000\000\000\002m\000\000\000\000\002m\000\000\000\000\002m\000\000\002m\000\000\000\000\t\214\000\000\002m\002m\002m\000\000\002m\002m\002m\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\002m\000\000\002m\000\000\000\000\000\000\000\000\000\000\002m\002m\n>\nF\002m\000\000\000\000\000\000\000\000\002m\000\000\002m\002m\000\000\000\000\000\000\000\000\002m\002m\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002m\002m\t\222\n\030\nV\n^\002m\002m\002m\000\000\000\000\002m\000\000\002m\002m\000\000\000\000\000\000\000\000\000\000\000\000\002m\002m\002m\000\000\002m\002m\002m\002m\002m\000\000\000\000\000\000\002m\000\000\002m\002m\000\000\002m\002m\002m\nf\002m\002m\000\000\000\000\002m\002m\002m\000\000\000\000\000\000\000\000\002m\002m\002m\002m\002\201\002\201\000\000\000\000\000\000\002\201\000\000\000\000\002\201\000\000\000\000\002\201\000\000\002\201\000\000\000\000\t\214\000\000\002\201\002\201\002\201\000\000\002\201\002\201\002\201\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\002\201\000\000\002\201\000\000\000\000\000\000\000\000\000\000\002\201\002\201\n>\nF\002\201\000\000\000\000\000\000\000\000\002\201\000\000\002\201\002\201\000\000\000\000\000\000\000\000\002\201\002\201\002\201\000\000\000\000\000\000\000\000\000\000\000\000\002\201\002\201\t\222\n\030\nV\002\201\002\201\002\201\002\201\000\000\000\000\002\201\000\000\002\201\002\201\000\000\000\000\000\000\000\000\000\000\000\000\002\201\002\201\002\201\000\000\002\201\002\201\002\201\002\201\002\201\000\000\000\000\000\000\002\201\000\000\002\201\002\201\000\000\002\201\002\201\002\201\nf\002\201\002\201\000\000\000\000\002\201\002\201\002\201\000\000\000\000\000\000\000\000\002\201\002\201\002\201\002\201\002i\002i\000\000\000\000\000\000\002i\000\000\000\000\002i\000\000\000\000\002i\000\000\002i\000\000\000\000\t\214\000\000\002i\002i\002i\000\000\002i\002i\002i\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\002i\000\000\002i\000\000\000\000\000\000\000\000\000\000\002i\002i\n>\nF\002i\000\000\000\000\000\000\000\000\002i\000\000\002i\002i\000\000\000\000\000\000\000\000\002i\002i\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002i\002i\t\222\n\030\nV\n^\002i\002i\002i\000\000\000\000\002i\000\000\002i\002i\000\000\000\000\000\000\000\000\000\000\000\000\002i\002i\002i\000\000\002i\002i\002i\002i\002i\000\000\000\000\000\000\002i\000\000\002i\002i\000\000\002i\002i\002i\nf\002i\002i\000\000\000\000\002i\002i\002i\000\000\000\000\000\000\000\000\002i\002i\002i\002i\002\161\002\161\000\000\000\000\000\000\002\161\000\000\000\000\002\161\000\000\000\000\002\161\000\000\002\161\000\000\000\000\t\214\000\000\002\161\002\161\002\161\000\000\002\161\002\161\002\161\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\002\161\000\000\002\161\000\000\000\000\000\000\000\000\000\000\002\161\002\161\n>\nF\002\161\000\000\000\000\000\000\000\000\002\161\000\000\002\161\002\161\000\000\000\000\000\000\000\000\002\161\002\161\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\161\002\161\t\222\n\030\nV\n^\002\161\002\161\002\161\000\000\000\000\002\161\000\000\002\161\002\161\000\000\000\000\000\000\000\000\000\000\000\000\002\161\002\161\002\161\000\000\002\161\002\161\002\161\002\161\002\161\000\000\000\000\000\000\002\161\000\000\002\161\002\161\000\000\002\161\002\161\002\161\nf\002\161\002\161\000\000\000\000\002\161\002\161\002\161\000\000\000\000\000\000\000\000\002\161\002\161\002\161\002\161\002\153\002\153\000\000\000\000\000\000\002\153\000\000\000\000\002\153\000\000\000\000\002\153\000\000\002\153\000\000\000\000\t\214\000\000\002\153\002\153\002\153\000\000\002\153\002\153\002\153\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\002\153\000\000\002\153\000\000\000\000\000\000\000\000\000\000\002\153\002\153\n>\nF\002\153\000\000\000\000\000\000\000\000\002\153\000\000\002\153\002\153\000\000\000\000\000\000\000\000\002\153\002\153\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\153\002\153\t\222\n\030\nV\n^\002\153\002\153\002\153\000\000\000\000\002\153\000\000\002\153\002\153\000\000\000\000\000\000\000\000\000\000\000\000\002\153\002\153\002\153\000\000\002\153\002\153\002\153\002\153\002\153\000\000\000\000\000\000\002\153\000\000\002\153\002\153\000\000\002\153\002\153\002\153\nf\002\153\002\153\000\000\000\000\002\153\002\153\002\153\000\000\000\000\000\000\000\000\002\153\002\153\002\153\002\153\002\169\002\169\000\000\000\000\000\000\002\169\000\000\000\000\002\169\000\000\000\000\002\169\000\000\002\169\000\000\000\000\t\214\000\000\002\169\002\169\002\169\000\000\002\169\002\169\002\169\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002\169\000\000\000\000\000\000\000\000\000\000\002\169\002\169\n>\nF\002\169\000\000\000\000\000\000\000\000\002\169\000\000\nN\002\169\000\000\000\000\000\000\000\000\002\169\002\169\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\169\002\169\t\222\n\030\nV\n^\nn\002\169\002\169\000\000\000\000\002\169\000\000\002\169\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\169\002\169\n~\000\000\002\169\002\169\002\169\002\169\002\169\000\000\000\000\000\000\002\169\000\000\002\169\002\169\000\000\002\169\002\169\002\169\nf\002\169\002\169\000\000\000\000\002\169\n\134\002\169\000\000\000\000\000\000\000\000\002\169\002\169\n\142\n\150\002\173\002\173\000\000\000\000\000\000\002\173\000\000\000\000\002\173\000\000\000\000\002\173\000\000\002\173\000\000\000\000\t\214\000\000\002\173\002\173\002\173\000\000\002\173\002\173\002\173\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\002\173\000\000\002\173\000\000\000\000\000\000\000\000\000\000\002\173\002\173\n>\nF\002\173\000\000\000\000\000\000\000\000\002\173\000\000\nN\002\173\000\000\000\000\000\000\000\000\002\173\002\173\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\173\002\173\t\222\n\030\nV\n^\nn\002\173\002\173\000\000\000\000\002\173\000\000\002\173\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\173\002\173\n~\000\000\002\173\002\173\002\173\002\173\002\173\000\000\000\000\000\000\002\173\000\000\002\173\002\173\000\000\002\173\002\173\002\173\nf\002\173\002\173\000\000\000\000\002\173\002\173\002\173\000\000\000\000\000\000\000\000\002\173\002\173\n\142\n\150\002\177\002\177\000\000\000\000\000\000\002\177\000\000\000\000\002\177\000\000\000\000\002\177\000\000\002\177\000\000\000\000\t\214\000\000\002\177\002\177\002\177\000\000\002\177\002\177\002\177\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\002\177\000\000\002\177\000\000\000\000\000\000\000\000\000\000\002\177\002\177\n>\nF\002\177\000\000\000\000\000\000\000\000\002\177\000\000\nN\002\177\000\000\000\000\000\000\000\000\002\177\002\177\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\177\002\177\t\222\n\030\nV\n^\nn\002\177\002\177\000\000\000\000\002\177\000\000\002\177\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\177\002\177\n~\000\000\002\177\002\177\002\177\002\177\002\177\000\000\000\000\000\000\002\177\000\000\002\177\002\177\000\000\002\177\002\177\002\177\nf\002\177\002\177\000\000\000\000\002\177\002\177\002\177\000\000\000\000\000\000\000\000\002\177\002\177\n\142\n\150\t\005\t\005\000\000\000\000\000\000\t\005\000\000\000\000\t\005\000\000\000\000\t\005\000\000\t\005\000\000\000\000\t\214\000\000\t\005\t\005\t\005\000\000\t\005\t\005\t\005\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\t\005\000\000\000\000\000\000\000\000\000\000\t\005\t\005\n>\nF\t\005\000\000\000\000\000\000\000\000\t\005\000\000\nN\t\005\000\000\000\000\000\000\000\000\t\005\t\005\000\238\000\000\000\000\000\000\000\000\000\000\000\000\t\005\t\005\t\222\n\030\nV\n^\nn\t\005\t\005\000\000\000\000\t\005\000\000\t\005\nv\000\000\000\000\000\000\000\000\000\000\000\000\t\005\t\005\n~\000\000\t\005\t\005\t\005\t\005\t\005\000\000\000\000\000\000\t\005\000\000\t\005\t\005\000\000\t\005\t\005\t\005\nf\t\005\t\005\000\000\000\000\t\005\n\134\t\005\000\000\000\000\000\000\000\000\t\005\t\005\n\142\n\150\002\181\002\181\000\000\000\000\000\000\002\181\000\000\000\000\002\181\000\000\000\000\002\181\000\000\002\181\000\000\000\000\t\214\000\000\002\181\002\181\002\181\000\000\002\181\002\181\002\181\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002\181\000\000\000\000\000\000\000\000\000\000\002\181\002\181\n>\nF\002\181\000\000\000\000\000\000\000\000\002\181\000\000\nN\002\181\000\000\000\000\000\000\000\000\002\181\002\181\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\181\002\181\t\222\n\030\nV\n^\nn\002\181\002\181\000\000\000\000\002\181\000\000\002\181\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\181\002\181\n~\000\000\002\181\002\181\002\181\002\181\002\181\000\000\000\000\000\000\002\181\000\000\002\181\002\181\000\000\n\158\002\181\n\166\nf\002\181\002\181\000\000\000\000\002\181\n\134\002\181\000\000\000\000\000\000\000\000\002\181\002\181\n\142\n\150\t\001\t\001\000\000\000\000\000\000\t\001\000\000\000\000\t\001\000\000\000\000\t\001\000\000\t\001\000\000\000\000\t\214\000\000\t\001\t\001\t\001\000\000\t\001\t\001\t\001\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\t\001\000\000\000\000\000\000\000\000\000\000\t\001\t\001\n>\nF\t\001\000\000\000\000\000\000\000\000\t\001\000\000\nN\t\001\000\000\000\000\000\000\000\000\t\001\t\001\000\238\000\000\000\000\000\000\000\000\000\000\000\000\t\001\t\001\t\222\n\030\nV\n^\nn\t\001\t\001\000\000\000\000\t\001\000\000\t\001\nv\000\000\000\000\000\000\000\000\000\000\000\000\t\001\t\001\n~\000\000\t\001\t\001\t\001\t\001\t\001\000\000\000\000\000\000\t\001\000\000\t\001\t\001\000\000\t\001\t\001\t\001\nf\t\001\t\001\000\000\000\000\t\001\n\134\t\001\000\000\000\000\000\000\000\000\t\001\t\001\n\142\n\150\002\229\002\229\000\000\000\000\000\000\002\229\000\000\000\000\002\229\000\000\000\000\002\229\000\000\002\229\000\000\000\000\t\214\000\000\002\229\002\229\002\229\000\000\002\229\002\229\002\229\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002\229\000\000\000\000\000\000\000\000\000\000\002\229\002\229\n>\nF\002\229\000\000\000\000\000\000\000\000\002\229\000\000\nN\002\229\000\000\000\000\000\000\000\000\002\229\002\229\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\229\002\229\t\222\n\030\nV\n^\nn\002\229\002\229\000\000\000\000\002\229\000\000\002\229\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\229\002\229\n~\000\000\002\229\002\229\002\229\002\229\002\229\000\000\000\000\000\000\002\229\000\000\002\229\002\229\000\000\n\158\002\229\n\166\nf\002\229\002\229\000\000\000\000\002\229\n\134\002\229\000\000\000\000\000\000\000\000\002\229\002\229\n\142\n\150\002\225\002\225\000\000\000\000\000\000\002\225\000\000\000\000\002\225\000\000\000\000\002\225\000\000\002\225\000\000\000\000\t\214\000\000\002\225\002\225\002\225\000\000\002\225\002\225\002\225\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002\225\000\000\000\000\000\000\000\000\000\000\002\225\002\225\n>\nF\002\225\000\000\000\000\000\000\000\000\002\225\000\000\nN\002\225\000\000\000\000\000\000\000\000\002\225\002\225\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\225\002\225\t\222\n\030\nV\n^\nn\002\225\002\225\000\000\000\000\002\225\000\000\002\225\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\225\002\225\n~\000\000\002\225\002\225\002\225\002\225\002\225\000\000\000\000\000\000\002\225\000\000\002\225\002\225\000\000\n\158\002\225\n\166\nf\002\225\002\225\000\000\000\000\002\225\n\134\002\225\000\000\000\000\000\000\000\000\002\225\002\225\n\142\n\150\002\233\002\233\000\000\000\000\000\000\002\233\000\000\000\000\002\233\000\000\000\000\002\233\000\000\002\233\000\000\000\000\t\214\000\000\002\233\002\233\002\233\000\000\002\233\002\233\002\233\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002\233\000\000\000\000\000\000\000\000\000\000\002\233\002\233\n>\nF\002\233\000\000\000\000\000\000\000\000\002\233\000\000\nN\002\233\000\000\000\000\000\000\000\000\002\233\002\233\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\233\002\233\t\222\n\030\nV\n^\nn\002\233\002\233\000\000\000\000\002\233\000\000\002\233\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\233\002\233\n~\000\000\002\233\002\233\002\233\002\233\002\233\000\000\000\000\000\000\002\233\000\000\002\233\002\233\000\000\n\158\002\233\n\166\nf\002\233\002\233\000\000\000\000\002\233\n\134\002\233\000\000\000\000\000\000\000\000\002\233\002\233\n\142\n\150\002\213\002\213\000\000\000\000\000\000\002\213\000\000\000\000\002\213\000\000\000\000\002\213\000\000\002\213\000\000\000\000\t\214\000\000\002\213\002\213\002\213\000\000\002\213\002\213\002\213\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002\213\000\000\000\000\000\000\000\000\000\000\002\213\002\213\n>\nF\002\213\000\000\000\000\000\000\000\000\002\213\000\000\nN\002\213\000\000\000\000\000\000\000\000\002\213\002\213\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\213\002\213\t\222\n\030\nV\n^\nn\002\213\002\213\000\000\000\000\002\213\000\000\002\213\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\213\002\213\n~\000\000\002\213\002\213\002\213\002\213\002\213\000\000\000\000\000\000\002\213\000\000\002\213\002\213\000\000\n\158\002\213\n\166\nf\002\213\002\213\000\000\000\000\002\213\n\134\002\213\000\000\000\000\000\000\000\000\002\213\002\213\n\142\n\150\002\217\002\217\000\000\000\000\000\000\002\217\000\000\000\000\002\217\000\000\000\000\002\217\000\000\002\217\000\000\000\000\t\214\000\000\002\217\002\217\002\217\000\000\002\217\002\217\002\217\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002\217\000\000\000\000\000\000\000\000\000\000\002\217\002\217\n>\nF\002\217\000\000\000\000\000\000\000\000\002\217\000\000\nN\002\217\000\000\000\000\000\000\000\000\002\217\002\217\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\217\002\217\t\222\n\030\nV\n^\nn\002\217\002\217\000\000\000\000\002\217\000\000\002\217\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\217\002\217\n~\000\000\002\217\002\217\002\217\002\217\002\217\000\000\000\000\000\000\002\217\000\000\002\217\002\217\000\000\n\158\002\217\n\166\nf\002\217\002\217\000\000\000\000\002\217\n\134\002\217\000\000\000\000\000\000\000\000\002\217\002\217\n\142\n\150\002\221\002\221\000\000\000\000\000\000\002\221\000\000\000\000\002\221\000\000\000\000\002\221\000\000\002\221\000\000\000\000\t\214\000\000\002\221\002\221\002\221\000\000\002\221\002\221\002\221\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002\221\000\000\000\000\000\000\000\000\000\000\002\221\002\221\n>\nF\002\221\000\000\000\000\000\000\000\000\002\221\000\000\nN\002\221\000\000\000\000\000\000\000\000\002\221\002\221\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\221\002\221\t\222\n\030\nV\n^\nn\002\221\002\221\000\000\000\000\002\221\000\000\002\221\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\221\002\221\n~\000\000\002\221\002\221\002\221\002\221\002\221\000\000\000\000\000\000\002\221\000\000\002\221\002\221\000\000\n\158\002\221\n\166\nf\002\221\002\221\000\000\000\000\002\221\n\134\002\221\000\000\000\000\000\000\000\000\002\221\002\221\n\142\n\150\002\241\002\241\000\000\000\000\000\000\002\241\000\000\000\000\002\241\000\000\000\000\002\241\000\000\002\241\000\000\000\000\t\214\000\000\002\241\002\241\002\241\000\000\002\241\002\241\002\241\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002\241\000\000\000\000\000\000\000\000\000\000\002\241\002\241\n>\nF\002\241\000\000\000\000\000\000\000\000\002\241\000\000\nN\002\241\000\000\000\000\000\000\000\000\002\241\002\241\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\241\002\241\t\222\n\030\nV\n^\nn\002\241\002\241\000\000\000\000\002\241\000\000\002\241\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\241\002\241\n~\000\000\002\241\002\241\002\241\002\241\002\241\000\000\000\000\000\000\002\241\000\000\002\241\002\241\000\000\n\158\002\241\n\166\nf\002\241\002\241\000\000\000\000\002\241\n\134\002\241\000\000\000\000\000\000\000\000\002\241\002\241\n\142\n\150\002\237\002\237\000\000\000\000\000\000\002\237\000\000\000\000\002\237\000\000\000\000\002\237\000\000\002\237\000\000\000\000\t\214\000\000\002\237\002\237\002\237\000\000\002\237\002\237\002\237\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002\237\000\000\000\000\000\000\000\000\000\000\002\237\002\237\n>\nF\002\237\000\000\000\000\000\000\000\000\002\237\000\000\nN\002\237\000\000\000\000\000\000\000\000\002\237\002\237\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\237\002\237\t\222\n\030\nV\n^\nn\002\237\002\237\000\000\000\000\002\237\000\000\002\237\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\237\002\237\n~\000\000\002\237\002\237\002\237\002\237\002\237\000\000\000\000\000\000\002\237\000\000\002\237\002\237\000\000\n\158\002\237\n\166\nf\002\237\002\237\000\000\000\000\002\237\n\134\002\237\000\000\000\000\000\000\000\000\002\237\002\237\n\142\n\150\002\245\002\245\000\000\000\000\000\000\002\245\000\000\000\000\002\245\000\000\000\000\002\245\000\000\002\245\000\000\000\000\t\214\000\000\002\245\002\245\002\245\000\000\002\245\002\245\002\245\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002\245\000\000\000\000\000\000\000\000\000\000\002\245\002\245\n>\nF\002\245\000\000\000\000\000\000\000\000\002\245\000\000\nN\002\245\000\000\000\000\000\000\000\000\002\245\002\245\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\245\002\245\t\222\n\030\nV\n^\nn\002\245\002\245\000\000\000\000\002\245\000\000\002\245\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\245\002\245\n~\000\000\002\245\002\245\002\245\002\245\002\245\000\000\000\000\000\000\002\245\000\000\002\245\002\245\000\000\n\158\002\245\n\166\nf\002\245\002\245\000\000\000\000\002\245\n\134\002\245\000\000\000\000\000\000\000\000\002\245\002\245\n\142\n\150\002\209\002\209\000\000\000\000\000\000\002\209\000\000\000\000\002\209\000\000\000\000\002\209\000\000\002\209\000\000\000\000\t\214\000\000\002\209\002\209\002\209\000\000\002\209\002\209\002\209\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002\209\000\000\000\000\000\000\000\000\000\000\002\209\002\209\n>\nF\002\209\000\000\000\000\000\000\000\000\002\209\000\000\nN\002\209\000\000\000\000\000\000\000\000\002\209\002\209\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\209\002\209\t\222\n\030\nV\n^\nn\002\209\002\209\000\000\000\000\002\209\000\000\002\209\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\209\002\209\n~\000\000\002\209\002\209\002\209\002\209\002\209\000\000\000\000\000\000\002\209\000\000\002\209\002\209\000\000\n\158\002\209\n\166\nf\002\209\002\209\000\000\000\000\002\209\n\134\002\209\000\000\000\000\000\000\000\000\002\209\002\209\n\142\n\150\002!\002!\000\000\000\000\000\000\002!\000\000\000\000\002!\000\000\000\000\002!\000\000\002!\000\000\000\000\002!\000\000\002!\002!\002!\000\000\002!\002!\002!\000\000\000\000\000\000\000\000\000\000\002!\002!\002!\002!\002!\000\000\002!\000\000\000\000\000\000\000\000\000\000\002!\002!\002!\002!\002!\000\000\000\000\000\000\000\000\002!\000\000\002!\002!\000\000\000\000\000\000\000\000\002!\002!\002!\000\000\000\000\000\000\000\000\000\000\000\000\002!\002!\002!\002!\002!\002!\002!\002!\002!\000\000\000\000\002!\000\000\002!\002!\000\000\000\000\000\000\000\000\000\000\000\000\002!\002!\002!\000\000\002!\002!\002!\002!\002!\000\000\000\000\000\000\002!\000\000\002!\002!\000\000\002!\002!\002!\002!\002!\002!\000\000\000\000\002!\002!\014\n\000\000\000\000\000\000\000\000\002!\002!\002!\002!\002=\002=\000\000\000\000\000\000\002=\000\000\000\000\002=\000\000\000\000\002=\000\000\002=\000\000\000\000\t\214\000\000\002=\002=\002=\000\000\002=\002=\002=\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002=\000\000\000\000\000\000\000\000\000\000\002=\002=\n>\nF\002=\000\000\000\000\000\000\000\000\002=\000\000\nN\002=\000\000\000\000\000\000\000\000\002=\002=\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002=\002=\t\222\n\030\nV\n^\nn\002=\002=\000\000\000\000\002=\000\000\002=\nv\000\000\000\000\000\000\000\000\000\000\000\000\002=\002=\n~\000\000\002=\002=\014\"\002=\002=\000\000\000\000\000\000\002=\000\000\002=\002=\000\000\n\158\002=\n\166\nf\002=\002=\000\000\000\000\002=\n\134\002=\000\000\000\000\000\000\000\000\002=\002=\n\142\n\150\0029\0029\000\000\000\000\000\000\0029\000\000\000\000\0029\000\000\000\000\0029\000\000\0029\000\000\000\000\t\214\000\000\0029\0029\0029\000\000\0029\0029\0029\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\0029\000\000\000\000\000\000\000\000\000\000\0029\0029\n>\nF\0029\000\000\000\000\000\000\000\000\0029\000\000\nN\0029\000\000\000\000\000\000\000\000\0029\0029\000\238\000\000\000\000\000\000\000\000\000\000\000\000\0029\0029\t\222\n\030\nV\n^\nn\0029\0029\000\000\000\000\0029\000\000\0029\nv\000\000\000\000\000\000\000\000\000\000\000\000\0029\0029\n~\000\000\0029\0029\0029\0029\0029\000\000\000\000\000\000\0029\000\000\0029\0029\000\000\n\158\0029\n\166\nf\0029\0029\000\000\000\000\0029\n\134\0029\000\000\000\000\000\000\000\000\0029\0029\n\142\n\150\002\205\002\205\000\000\000\000\000\000\002\205\000\000\000\000\002\205\000\000\000\000\002\205\000\000\002\205\000\000\000\000\t\214\000\000\002\205\002\205\002\205\000\000\002\205\002\205\002\205\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\002\205\000\000\000\000\000\000\000\000\000\000\002\205\002\205\n>\nF\002\205\000\000\000\000\000\000\000\000\002\205\000\000\nN\002\205\000\000\000\000\000\000\000\000\002\205\002\205\000\238\000\000\000\000\000\000\000\000\000\000\000\000\002\205\002\205\t\222\n\030\nV\n^\nn\002\205\002\205\000\000\000\000\002\205\000\000\002\205\nv\000\000\000\000\000\000\000\000\000\000\000\000\002\205\002\205\n~\000\000\002\205\002\205\002\205\002\205\002\205\000\000\000\000\000\000\002\205\000\000\002\205\002\205\000\000\n\158\002\205\n\166\nf\002\205\002\205\000\000\000\000\002\205\n\134\002\205\000\000\000\000\000\000\000\000\002\205\002\205\n\142\n\150\002-\002-\000\000\000\000\000\000\002-\000\000\000\000\002-\000\000\000\000\002-\000\000\002-\000\000\000\000\002-\000\000\002-\002-\002-\000\000\002-\002-\002-\000\000\000\000\000\000\000\000\000\000\002-\002-\002-\002-\002-\000\000\002-\000\000\000\000\000\000\000\000\000\000\002-\002-\002-\002-\002-\000\000\000\000\000\000\000\000\002-\000\000\002-\002-\000\000\000\000\000\000\000\000\002-\002-\002-\000\000\000\000\000\000\000\000\000\000\000\000\002-\002-\002-\002-\002-\002-\002-\002-\002-\000\000\000\000\002-\000\000\002-\002-\000\000\000\000\000\000\000\000\000\000\000\000\002-\002-\002-\000\000\002-\002-\002-\002-\002-\000\000\000\000\000\000\002-\000\000\002-\002-\000\000\002-\002-\002-\002-\002-\002-\000\000\000\000\002-\002-\014\n\000\000\000\000\000\000\000\000\002-\002-\002-\002-\0021\0021\000\000\000\000\000\000\0021\000\000\000\000\0021\000\000\000\000\0021\000\000\0021\000\000\000\000\0021\000\000\0021\0021\0021\000\000\0021\0021\0021\b-\000\000\000\000\000\000\b-\0021\0021\0021\0021\0021\000\000\0021\000\000\000\000\005M\r!\000\000\0021\0021\0021\0021\0021\000\000\000\000\000\000\000\000\0021\000\000\0021\0021\000\000\000\000\000\000\005M\0021\0021\0021\005M\000\000\000\000\000\000\000\000\b-\0021\0021\0021\0021\0021\0021\0021\0021\0021\000\000\000\000\0021\000\000\0021\0021\000\000\000\000\000\000\000\000\000\000\b-\0021\0021\0021\000\000\0021\0021\0021\0021\0021\000\000\000\000\000\000\0021\000\000\0021\0021\000\000\0021\0021\0021\0021\0021\0021\000\000\000\000\0021\0021\014\n\r!\r!\000\000\000\000\0021\0021\0021\0021\001\006\004\254\000\006\000\000\000\000\005M\002\186\002\190\000\000\002\234\002\130\000\000\r!\000\000\r!\002\246\001\n\000\000\000\000\000\000\002\142\005M\000\000\003\001\005M\001\210\003\206\018\234\002\190\0036\001\018\bz\b~\001\030\001\"\003\170\000\000\000\000\003F\000\000\002\254\007\238\025\134\000\000\b\162\b\166\001\210\003\222\0032\003\234\b\170\006\226\000\n\001:\000\000\002\178\007-\000\000\003:\000\000\000\000\000\000\b&\b*\b6\bJ\000\000\005v\003\001\003\202\001>\001B\001F\001J\001N\007-\002\178\b\190\001R\007-\003\001\003\001\001V\000\000\b\202\b\226\t6\005\130\005\134\b\150\000\000\001Z\000\000\000\000\000\000\000\000\002\006\000\000\001^\000\000\000\000\000\000\000\000\000\000\006\246\000\000\002\n\000\000\001\154\011\030\000\000\000\000\005\138\b>\001\210\001\158\b\205\014R\004r\tJ\001\006\001\166\000\006\001\170\001\174\000\000\002\186\002\190\000\000\002\234\002\130\003\154\000\000\000\000\000\000\002\246\001\n\007\014\001\222\000\000\bv\000\000\000\000\000\000\002\178\001\210\000\000\007-\000\000\0036\001\018\bz\b~\001\030\001\"\b\205\000\000\000\000\003F\000\000\002\254\000\000\b\130\n\218\b\162\b\166\n\230\003\222\0032\003\234\b\170\006\226\007\018\001:\000\000\002\178\b\205\000\000\003:\000\000\000\000\000\000\b&\b*\b6\bJ\000\000\005v\000\000\000\000\001>\001B\001F\001J\001N\000\000\000\000\b\190\001R\000\000\t1\000\000\001V\000\000\b\202\b\226\t6\005\130\005\134\000\000\b\205\001Z\b)\000\000\004\254\000\000\b)\b\205\001^\006v\000\000\000\000\t1\000\000\000\000\000\000\000\000\000\000\001\154\006&\000\000\000\000\005\138\b>\000\000\001\158\000\000\014R\004r\tJ\004\141\001\166\000\006\001\170\001\174\000\246\002\186\002\190\002\194\002\234\002\130\000\000\000\000\000\000\b)\002\246\000\000\000\000\003\178\000\000\000\000\000\238\004\141\000\000\003\182\001\210\000\000\017&\000\000\002\250\000\000\003>\003B\000\000\000\000\b)\003\186\000\000\003F\000\000\002\254\000\000\016\186\000\000\003\214\003\218\000\000\003\222\0032\003\234\003\242\006\226\000\000\016z\017\030\002\178\000\000\000\000\003:\0176\002\006\000\000\b&\b*\b6\bJ\006:\005v\000\000\006\002\002\n\000\000\000\000\004\254\t1\017>\006F\b\190\001\210\000\000\006R\000\000\000\000\000\000\b\202\b\226\t6\005\130\005\134\017R\017~\000\000\000\000\004\141\004\141\003\154\017\186\000\000\000\000\000\000\000\000\007\014\001\222\000\000\000\000\000\000\012\225\012\205\002\178\000\000\018\006\022\002\005\138\b>\025r\000\173\000\000\bV\004r\tJ\000\173\000\000\002\190\000\173\000\000\002\130\012\225\tr\000\000\002\030\002\246\000\000\002\"\000\173\000\000\000\173\007\018\000\173\000\000\000\173\001\210\000\000\tz\000\000\002\250\002.\000\000\000\000\0026\012\205\t\130\000\173\000\000\000\000\000\000\002\254\b\201\000\173\000\000\003\001\000\000\000\173\003\001\0032\001\190\000\000\000\173\000\000\012\169\000\173\002\178\000\000\002:\003:\000\173\000\173\000\173\b&\b*\b6\000\000\012r\005v\000\173\000\173\000\n\000\000\012\169\012\169\000\000\000\173\012\169\000\000\000\000\000\173\b\201\000\000\000\000\000\000\000\000\003\001\000\000\005\130\005\134\000\173\000\173\000\000\000\000\000\173\000\173\000\000\000\173\000\000\003\001\003\001\000\000\b\201\002>\000\000\000\173\000\000\015\142\000\000\000\000\002\130\000\173\000\173\005\138\b>\000\238\000\000\000\197\bV\004r\000\000\000\173\000\197\000\173\002\190\000\197\003\001\002\130\021\170\tr\000\000\000\000\002\246\000\000\000\000\000\197\b\201\000\197\000\000\000\197\004\254\000\197\001\210\b\201\tz\012\169\002\250\000\000\015\146\000\000\000\000\000\000\t\130\000\197\000\000\000\000\000\000\002\254\000\000\000\197\000\000\n\242\015\158\000\197\021\206\0032\001\190\000\000\000\197\000\000\000\000\000\197\002\178\000\000\000\000\003:\000\197\000\197\000\197\b&\b*\b6\000\000\012r\005v\000\197\000\197\000\000\005\134\000\000\000\000\000\000\000\197\000\000\000\000\000\000\000\197\000\000\000\000\021\218\000\000\000\000\000\000\000\000\005\130\005\134\000\197\000\197\000\000\000\000\000\197\000\197\000\000\000\197\000\000\000\000\021n\000\000\000\000\000\000\000\000\000\197\000\000\000\000\000\000\000\000\000\000\000\197\000\197\005\138\b>\000\000\000\000\000\000\bV\004r\t\029\000\197\000\006\000\197\000\000\000\246\002\186\002\190\002\194\002\234\002\130\000\000\000\000\000\000\000\000\002\246\000\000\000\000\004\173\000\000\t\029\000\000\t\029\t\029\003\182\001\210\000\000\000\000\000\000\002\250\000\000\003>\003B\000\000\000\000\000\000\003\186\000\000\003F\000\000\002\254\000\000\016\186\000\000\003\214\003\218\000\000\003\222\0032\003\234\003\242\006\226\000\000\000\000\017\030\002\178\000\000\000\000\003:\0176\000\000\000\000\b&\b*\b6\bJ\000\000\005v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017>\000\000\b\190\011*\028b\000\000\000\000\000\000\000\000\b\202\b\226\t6\005\130\005\134\017R\017~\000\000\004y\028\131\014\230\000\000\017\186\004y\011.\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\022\002\005\138\b>\t\029\000\000\004y\bV\004r\tJ\000\006\000\000\000\000\000\246\002\186\002\190\002\194\002\234\002\130\000\000\000\000\000\000\000\000\002\246\000\000\000\000\028\178\000\000\004y\000\238\003\254\000\000\003\182\001\210\000\000\000\000\004y\002\250\000\000\003>\003B\004y\002\226\000\238\003\186\000\000\003F\000\000\002\254\000\000\016\186\004y\003\214\003\218\000\000\003\222\0032\003\234\003\242\006\226\001\202\002~\017\030\002\178\002\130\000\000\003:\0176\000\000\000\000\b&\b*\b6\bJ\006:\005v\004y\006\002\0112\001\210\001\214\001\230\002\134\017>\006F\b\190\004y\028b\006R\001\242\000\000\000\000\b\202\b\226\t6\005\130\005\134\017R\017~\000\000\000\000\004\181\002\138\002\146\017\186\015\142\000\000\002\158\002\130\002\178\004\030\004*\000\000\000\000\000\000\000\000\021Z\000\000\021^\022\002\005\138\b>\014f\000\000\000\000\bV\004r\tJ\000\014\000\018\000\022\000\026\000\030\004:\000\"\000&\000*\000.\0002\000\000\0006\000:\005\134\000\000\000>\000\000\015\146\000\000\000B\000\000\000\000\000\000\000\000\021j\000\000\000F\000\000\000\000\000\000\000\000\015\158\000J\021\174\000N\000R\000V\000Z\000^\000b\000f\021n\000\000\000\000\000j\000n\000\000\000r\000\000\000v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\134\000\000\000\000\000\000\000\000\000\000\000z\000\000\000\000\000~\000\130\021\186\000\000\000\000\000\000\000\000\000\134\000\138\000\142\000\000\000\000\000\000\000\000\000\000\000\146\000\150\000\154\000\158\021n\000\162\000\166\000\170\000\000\000\000\000\000\000\174\000\178\000\000\000\182\000\000\000\000\000\000\000\186\000\000\000\190\000\194\000\000\000\000\000\000\001\006\000\000\000\000\000\198\000\000\000\202\003V\002\190\t\030\000\000\002\130\000\206\000\210\000\000\000\214\002\246\001\n\000\000\000\000\000\000\002\142\000\000\000\000\000\000\000\000\001\210\000\000\000\000\000\000\001\014\001\018\001\022\003v\001\030\001\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003z\000\000\001.\011\026\000\000\000\000\003r\001\190\0016\001\021\000\000\001:\000\000\002\178\001\021\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\005j\000\000\005v\000\000\000\000\001>\001B\001F\001J\001N\001\021\000\000\000\000\001R\005z\000\000\000\000\001V\000\000\000\000\000\000\000\000\005\130\005\134\000\000\005\202\001Z\000\000\000\000\000\000\000\000\005\214\001\021\001^\019\030\000\000\000\000\000\000\000\000\000\000\001\021\000\000\000\000\001\154\011\030\001\021\000\000\005\138\000\000\000\000\001\158\000\000\001\162\004r\001\006\001\021\001\166\000\000\001\170\001\174\003V\002\190\n\190\000\000\002\130\000\000\000\000\000\000\000\000\002\246\001\n\000\000\000\000\000\000\002\142\000\000\000\000\000\000\000\000\001\210\001\021\000\000\000\000\001\014\001\018\001\022\003v\001\030\001\"\000\000\001\021\000\000\000\000\000\000\000\000\000\000\003z\000\000\001.\011\026\000\000\000\000\003r\001\190\0016\004\157\000\000\001:\000\000\002\178\019.\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\005j\000\000\005v\000\000\000\000\001>\001B\001F\001J\001N\003\182\000\000\000\000\001R\005z\000\000\000\000\001V\000\000\000\000\000\000\000\000\005\130\005\134\000\000\005\202\001Z\000\000\000\000\000\000\000\000\005\214\019Z\001^\000\000\000\000\000\000\000\000\000\000\000\000\017\030\000\000\000\000\001\154\011\030\0176\000\000\005\138\000\000\000\000\001\158\000\000\001\162\004r\001\006\019\150\001\166\000\000\001\170\001\174\003V\002\190\r\182\000\000\002\130\000\000\000\000\000\000\000\000\002\246\001\n\000\000\000\000\000\000\002\142\000\000\000\000\000\000\000\000\001\210\004\157\000\000\000\000\001\014\001\018\001\022\003v\001\030\001\"\001\r\019\250\000\000\000\000\000\000\001\r\000\000\003z\000\000\001.\011\026\000\000\000\000\003r\001\190\0016\000\000\000\000\001:\000\000\002\178\000\000\000\000\003\246\001\r\000\000\000\000\003\250\000\000\004\002\005j\000\000\005v\000\000\000\000\001>\001B\001F\001J\001N\000\000\000\000\000\000\001R\005z\000\000\001\r\001V\003R\000\000\000\000\000\000\005\130\005\134\001\r\005\202\001Z\000\000\000\000\001\r\000\000\005\214\000\000\001^\000\000\000\000\000\000\000\000\001\r\001\r\000\000\000\000\000\000\001\154\011\030\000\000\000\000\005\138\000\000\000\000\001\158\000\000\001\162\004r\000\000\005\029\001\166\000\000\001\170\001\174\005\029\005\029\005\029\005\029\001\r\005\029\000\000\005\029\005\029\000\000\000\000\005\029\000\000\005\029\001\r\005\029\005\029\005\029\005\029\005\029\005\029\000\000\005\029\005\029\005\029\000\000\000\000\000\000\000\000\000\000\000\000\005\029\000\000\000\000\000\000\000\000\005\029\005\029\005\029\000\000\000\000\000\000\005\029\005\029\005\029\000\000\005\029\000\000\000\000\005\029\000\000\005\029\000\000\000\000\005\029\005\029\005\029\000\000\000\000\005\029\005\029\005\029\000\000\000\000\000\000\000\000\000\000\000\000\005\029\005\029\005\029\000\000\000\000\000\000\005\029\005\029\000\000\000\000\000\000\005\029\000\000\000\000\005\029\000\000\005\029\005\029\005\029\000\000\005\029\005\029\005\029\005\029\000\000\005\029\005\029\000\000\005\029\000\000\000\000\000\000\000\000\000\000\000\000\003\001\005\029\020\130\005\029\005\029\003\001\000\000\002\150\005\029\000\000\000\000\000\000\000\000\005\029\005\029\000\000\000\000\005\029\000\000\005\029\005\029\t\t\t\t\000\000\003\001\000\000\t\t\000\000\001\206\t\t\000\000\000\000\000\000\000\n\000\000\000\000\000\000\t\t\000\000\t\t\t\t\t\t\000\000\t\t\t\t\t\t\003\001\003\001\003\001\000\000\000\000\000\000\000\000\000\000\003\001\000\000\000\000\t\t\000\000\003\001\000\000\003\001\000\000\t\t\t\t\003\001\003\001\t\t\003\001\003\001\002\154\000\000\t\t\000\n\000\000\t\t\000\000\000\000\000\000\000\000\t\t\t\t\t\t\000\000\000\000\003\001\000\000\000\000\003\001\t\t\t\t\003\001\000\n\000\000\003\001\003\001\t\t\000\000\003\001\000\000\004\154\003\001\000\000\t\t\003\001\000\000\000\000\003\001\003\001\000\000\t\t\t\t\t\t\000\000\t\t\t\t\000\000\t\t\000\000\000\000\003\001\000\000\000\000\003\001\b%\t\t\000\000\t\t\t\t\b%\000\000\003\001\t\t\000\000\000\000\000\000\000\000\t\t\000\000\000\000\000\000\t\t\000\000\t\t\t\t\012\161\012\161\000\000\b%\000\000\012\161\000\000\001\206\012\161\000\000\000\000\000\000\003\190\000\000\000\000\000\000\004\186\000\000\012\161\012\161\012\161\000\000\012\161\012\161\012\161\b%\000\000\000\000\000\000\000\000\000\000\003\001\000\000\b%\000\000\000\000\012\161\000\000\b%\b%\000\238\000\000\012\161\012\161\000\000\000\000\012\161\b%\b%\002\154\000\000\012\161\000\000\000\000\012\161\000\000\000\000\000\000\000\000\012\161\012\161\012\161\000\000\000\000\000\000\000\000\000\000\000\000\012\161\012\161\b%\000\000\000\000\b%\000\000\012\161\000\000\000\000\000\000\004\154\000\000\000\000\012\161\b%\000\000\000\000\000\000\000\000\000\000\012\161\012\161\012\161\000\000\012\161\012\161\000\000\012\161\000\000\005Q\r!\000\000\000\000\000\000\b!\012\161\000\000\012\161\012\161\b!\000\000\000\000\012\161\000\000\000\000\000\000\000\000\012\161\005Q\000\000\000\000\012\161\005Q\012\161\012\161\t\r\t\r\000\000\b!\000\000\t\r\000\000\001\206\t\r\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\r\000\000\t\r\t\r\t\r\000\000\t\r\t\r\t\r\b!\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b!\000\000\000\000\t\r\000\000\b!\b!\000\238\000\000\t\r\t\r\000\000\000\000\t\r\b!\b!\002\154\000\000\t\r\r!\r!\t\r\000\000\000\000\000\000\000\000\t\r\t\r\t\r\000\000\000\000\000\000\005Q\000\000\000\000\t\r\t\r\b!\000\000\r!\b!\r!\t\r\000\000\000\000\000\000\004\154\000\000\005Q\t\r\b!\005Q\000\000\000\000\000\000\000\000\t\r\t\r\t\r\000\000\t\r\t\r\000\000\t\r\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\r\000\000\t\r\t\r\000\000\012\225\012\205\t\r\000\000\000\000\000\000\000\000\t\r\000\000\n\245\000\000\t\r\n\245\t\r\t\r\n\245\n\245\000\000\000\000\n\245\012\225\n\245\000\000\002\030\n\245\000\000\002\"\000\000\n\245\n\245\000\000\n\245\n\245\002*\n\245\000\000\n\245\003\001\000\000\002.\000\000\n\245\0026\012\205\n\245\000\000\000\000\003\001\000\000\000\000\000\000\000\000\n\245\000\000\n\245\003\001\000\000\n\245\n\245\000\000\000\000\000\000\000\000\000\n\n\245\001*\002:\n\245\000\000\000\000\n\245\n\245\003\001\n\245\000\000\n\245\n\245\000\000\003\001\003\001\000\000\000\000\000\000\003\001\000\000\003\001\000\000\000\000\n\245\000\000\003\001\003\001\000\000\000\000\000\000\000\000\n\245\n\245\000\n\000\000\n\245\003\001\n\245\000\000\000\000\000\000\000\000\000\000\005\166\000\n\000\000\002>\000\000\003\001\003\001\n\245\n\245\003\001\n\245\n\245\003\001\n\245\003\001\n\245\003\001\n\245\003\001\n\245\003\001\n\245\003\001\003\001\003\001\003\001\003\001\000\000\003\001\003\001\000\000\003\001\000\n\000\000\000\000\000\000\000\000\003\001\000\000\003\001\003\001\003\001\000\000\003\001\003\001\003\001\000\000\003\001\003\001\000\n\000\000\003\001\006\230\000\000\003\001\000\000\003\001\003\001\015F\000\000\003\001\003\001\003\001\003\001\003\001\003\001\003\001\003\001\000\000\000\000\000\000\003\001\000\000\000\000\003\001\000\000\000\000\003\001\003\001\003\001\003\001\003\001\003\001\003\001\000\000\006\234\003\001\003\001\000\000\003\001\000\000\000\000\000\000\003\001\000\000\003\001\000\000\000\000\000\000\000\000\003\001\003\001\003\001\003\001\003\001\000\000\015\130\000\000\000\000\000\000\003\001\003\001\003\001\004\129\000\000\003\001\003\001\003\001\000\246\000\000\000\000\002\018\012\165\012\165\000\000\000\000\000\000\012\165\003\001\003\001\012\165\018\n\000\000\003\001\003\001\003\001\000\000\003\182\004\138\000\000\012\165\012\165\012\165\000\000\012\165\012\165\012\165\000\000\000\000\018\014\000\000\000\000\000\000\000\000\000\000\0186\000\000\000\000\012\165\000\000\000\000\000\000\000\000\000\000\012\165\012\165\000\000\017\030\012\165\000\000\000\000\000\000\0176\012\165\000\000\000\000\012\165\000\000\000\000\000\000\000\000\012\165\012\165\012\165\000\000\000\000\000\000\000\000\018\178\000\000\012\165\012\165\000\000\000\000\000\000\000\000\000\000\012\165\000\000\000\000\000\000\012\165\017R\018\198\012\165\000\000\004\129\004\129\000\000\018\214\016\138\012\165\012\165\012\165\000\000\012\165\012\165\002\006\012\165\000\000\000\000\000\000\000\000\000\000\018\230\000\000\012\165\002\n\012\165\012\165\000\000\000\000\000\000\012\165\000\000\001\210\000\000\000\000\012\165\000\000\000\000\006\173\012\165\0009\012\165\012\165\000\000\0009\0009\000\000\0009\0009\003\154\000\000\000\000\000\000\0009\000\000\007\014\001\222\000\000\006\173\000\000\000\000\000\000\002\178\0009\000\000\000\000\000\000\0009\000\000\0009\0009\012\225\012\205\000\000\000\000\000\000\0009\000\000\0009\000\000\000\000\000\000\0009\0009\000\000\0009\0009\0009\0009\0009\007\018\012\225\025\158\0009\002\030\000\000\0009\002\"\000\000\002\006\0009\0009\0009\0009\002\206\0009\000\000\000\000\000\000\002\n\002.\000\000\000\000\0026\012\205\0009\000\000\001\210\000\000\000\000\000\000\000\000\0009\0009\0009\0009\0009\000\000\000\000\006\169\000\000\0005\000\000\000\000\003\154\0005\0005\002:\0005\0005\007\014\001\222\000\000\000\000\0005\000\000\000\000\002\178\000\000\006\169\0009\0009\000\000\000\000\0005\0009\0009\0009\0005\000\000\0005\0005\000\000\000\000\000\000\000\000\000\000\0005\000\000\0005\000\000\000\000\000\000\0005\0005\007\018\0005\0005\0005\0005\0005\000\000\002>\000\000\0005\004\165\000\000\0005\000\000\000\000\022*\0005\0005\0005\0005\000\000\0005\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0005\000\000\000\000\003\182\000\000\000\000\000\000\0005\0005\0005\0005\0005\000\000\000\000\006\185\000\000\012i\000\000\000\000\000\000\012i\012i\000\000\012i\012i\022\154\000\000\000\000\000\000\012i\000\000\000\000\000\000\017\030\006\185\0005\0005\000\000\0176\012i\0005\0005\0005\012i\000\000\012i\012i\023>\023N\000\000\000\000\000\000\012i\000\000\012i\000\000\000\000\000\000\012i\012i\000\000\012i\012i\012i\012i\012i\000\000\007!\000\000\012i\000\000\000\000\012i\004\165\000\000\000\000\012i\012i\012i\012i\000\000\012i\000\000\024B\000\000\000\000\007!\000\000\000\000\000\000\007!\012i\000\000\000\000\000\000\000\000\000\000\000\000\012i\012i\012i\012i\012i\000\000\000\000\006\181\000\000\012e\000\000\000\000\000\000\012e\012e\000\000\012e\012e\000\000\000\000\000\000\000\000\012e\000\000\000\000\000\000\000\000\006\181\012i\012i\000\238\000\000\012e\012i\012i\012i\012e\000\000\012e\012e\000\000\000\000\000\000\000\000\006\253\012e\000\000\012e\000\000\006\253\000\000\012e\012e\000\000\012e\012e\012e\012e\012e\000\000\000\000\000\000\012e\000\000\000\000\012e\000\000\000\000\006\253\012e\012e\012e\012e\000\000\012e\006:\000\000\000\000\006\002\000\000\000\000\000\000\000\000\000\000\012e\006F\000\000\000\000\000\000\006R\006\253\012e\012e\012e\012e\012e\000\000\000\000\006\253\000\000\000\000\000\000\000\000\006\253\006\253\000\238\000\000\000\000\000\000\003=\003=\000\000\006\253\006\253\003=\000\000\000\000\003=\000\000\012e\012e\000\000\000\000\000\000\012e\012e\012e\003=\003=\003=\000\000\003=\003=\003=\000\000\000\000\000\000\000\000\006\253\000\000\000\000\000\000\000\000\000\000\000\000\003=\000\000\000\000\006\253\000\000\000\000\003=\004\130\000\000\000\000\003=\000\000\000\000\000\000\000\000\003=\000\000\000\000\003=\024\"\000\000\000\000\000\000\003=\003=\003=\000\000\000\000\000\000\000\000\000\000\000\000\003=\003=\000\000\000\000\000\000\000\000\000\000\003=\000\000\000\000\000\000\003=\000\000\000\000\003=\000\000\000\000\000\000\000\000\000\000\000\000\003=\003=\003=\000\000\003=\003=\000\000\003=\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003=\000\000\003=\003=\000\000\000\000\000\000\003=\000\000\000\000\000\000\000\000\003=\000\000\011\001\000\000\003=\011\001\003=\003=\003V\002\190\000\000\000\000\002\130\000\000\006\178\000\000\000\000\002\246\000\000\000\000\000\000\011\001\011\001\000\000\011\001\011\001\000\000\001\210\000\000\006\210\000\000\000\000\000\000\000\000\003Z\000\000\000\000\b\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\001\000\000\003f\000\000\000\000\003r\001\190\000\000\000\000\000\000\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\011\001\003\250\000\000\004\002\005j\n\202\005v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005z\000\000\001\202\001\206\000\000\000\000\000\000\000\000\005\130\005\134\000\000\005\202\011\001\000\000\011\001\000\000\000\000\005\214\000\000\000\000\000\000\001\210\001\214\000\000\000\000\000\000\000\000\011\001\000\000\000\000\011\001\011\001\000\000\005\138\000\000\011\001\000\000\011\001\000\000\004r\n\253\011\001\000\000\n\253\001\246\002\154\003V\002\190\000\000\002\158\002\130\002\178\004\030\004*\000\000\002\246\000\000\000\000\0046\n\253\n\253\000\000\n\253\n\253\000\000\001\210\000\000\001\202\001\206\000\000\000\000\000\000\003Z\000\000\000\000\004:\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\253\000\000\003f\001\210\001\214\003r\001\190\000\000\000\000\000\000\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\n\253\003\250\000\000\004\002\005j\000\000\005v\000\000\001\246\002\154\000\000\000\000\000\000\002\158\000\000\002\178\004\030\004*\005z\000\000\000\000\000\000\0046\000\000\015\170\000\000\005\130\005\134\001\197\005\202\n\253\000\000\n\253\001\197\000\000\005\214\000\000\000\000\000\000\004:\000\000\000\000\000\000\000\000\000\000\n\253\000\000\000\000\n\253\n\253\000\000\005\138\001\197\n\253\000\000\n\253\000\006\004r\000\000\n\253\002\186\002\190\000\000\002\234\002\130\000\000\000\000\000\000\000\000\002\246\000\000\000\000\000\000\000\000\001\197\000\000\014z\000\000\000\000\001\210\000\000\000\000\001\197\002\250\000\000\003>\003B\001\197\001\197\000\238\r-\000\000\003F\000\000\002\254\r-\001\197\001\197\003\214\003\218\000\000\003\222\0032\003\234\003\242\006\226\000\000\000\000\000\000\002\178\000\000\000\000\003:\000\000\r-\000\000\b&\b*\b6\bJ\000\000\005v\001\197\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\190\001\197\000\000\000\000\000\000\r-\000\000\b\202\b\226\t6\005\130\005\134\000\000\r-\000\000\000\000\000\000\000\000\r-\r-\000\238\000\000\000\000\000\000\000\000\001\221\001\221\r-\r-\000\000\001\221\000\000\000\000\001\221\000\000\005\138\b>\000\000\000\000\000\000\bV\004r\tJ\001\221\001\221\001\221\000\000\001\221\001\221\001\221\000\000\000\000\000\000\r-\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\221\000\000\r-\000\000\000\000\000\000\001\221\001\221\000\000\000\000\001\221\000\000\000\000\000\000\000\000\001\221\000\000\000\000\001\221\000\000\000\000\000\000\000\000\001\221\001\221\001\221\000\000\000\000\000\000\000\000\000\000\000\000\001\221\001\221\000\000\000\000\000\000\000\000\000\000\001\221\000\000\000\000\000\000\001\221\000\000\000\000\001\221\000\000\000\000\000\000\000\000\000\000\000\000\001\221\001\221\001\221\000\000\001\221\001\221\000\000\001\221\005\157\005\157\000\000\000\000\000\000\005\157\000\000\001\221\005\157\001\221\001\221\000\000\000\000\000\000\001\221\000\000\000\000\000\000\005\157\001\221\005\157\000\000\005\157\004\254\005\157\001\221\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\157\000\000\000\000\000\000\000\000\000\000\005\157\005\157\000\000\000\000\000\000\000\000\005\157\000\000\000\000\005\157\000\000\000\000\005\157\000\000\000\000\000\000\000\000\005\157\005\157\005\157\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\157\005\157\000\000\000\000\005\157\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\157\005\157\005\157\000\000\005\157\005\157\000\000\005\157\003V\002\190\000\000\007z\002\130\000\000\006\178\000\000\000\000\002\246\005\157\004y\000\000\005\157\005\157\000\000\004y\000\000\000\000\001\210\000\000\006\210\000\000\000\000\000\000\005\157\003Z\000\000\000\000\b\238\000\000\000\000\000\000\000\000\000\000\004y\000\000\000\000\000\000\003f\000\000\000\000\n\186\001\190\000\000\000\000\000\000\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\n\217\003\250\004y\004\002\000\000\n\202\005v\000\000\000\000\000\000\004y\000\000\000\000\000\000\000\000\004y\002\226\000\000\005z\000\000\000\000\000\000\000\000\000\000\004y\004y\005\130\005\134\000\000\000\000\n\210\000\000\000\000\000\000\000\000\003V\002\190\000\000\000\000\002\130\000\000\006\178\000\000\000\000\002\246\n\217\n\218\000\000\n\217\011F\004y\005\138\000\000\000\000\001\210\n\217\006\210\004r\000\000\n\217\004y\003Z\000\000\000\000\b\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003f\000\000\000\000\n\186\001\190\000\000\000\000\000\000\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\n\217\003\250\000\000\004\002\000\000\n\202\005v\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005z\000\000\005\145\005\145\000\000\000\000\000\000\005\145\005\130\005\134\005\145\000\000\n\210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\145\000\000\005\145\000\000\005\145\000\000\005\145\n\217\000\000\000\000\n\217\n\217\000\000\005\138\000\000\000\000\000\000\n\217\005\145\004r\000\000\n\217\000\000\000\000\005\145\005\145\000\000\000\000\000\000\000\000\007\234\000\000\000\000\005\145\000\000\001\006\005\145\000\000\000\000\000\000\000\000\005\145\005\145\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\n\000\000\000\000\000\000\002\142\000\000\005\145\005\145\000\000\000\000\005\145\000\000\000\000\001\014\001\018\001\022\001\026\001\030\001\"\000\000\005\145\005\145\005\145\000\000\005\145\005\145\001&\005\145\001.\0012\000\000\000\000\000\000\000\000\0016\000\000\000\000\001:\005\145\000\000\000\000\005\145\005\145\003}\003}\000\000\000\000\000\000\003}\000\000\000\000\003}\000\000\005\145\001>\001B\001F\001J\001N\000\000\000\000\003}\001R\003}\000\000\003}\001V\003}\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001Z\003}\003}\000\000\003}\000\000\003}\001^\000\000\003}\003}\003}\000\000\000\000\000\000\000\000\005%\001\154\027\150\003}\000\000\003}\003}\003}\001\158\003}\001\162\003}\003}\003}\001\166\000\000\001\170\001\174\000\000\000\000\000\000\003}\000\000\000\000\000\000\000\000\000\000\003}\003}\b\149\b\149\003}\000\000\005)\b\149\000\000\003}\b\149\000\000\003}\000\000\003}\003}\003}\003}\003}\003}\b\149\003}\b\149\000\000\b\149\005%\b\149\000\000\000\000\000\000\000\000\000\000\003}\003}\000\000\000\000\003}\003}\b\149\000\000\000\000\000\000\000\000\000\000\b\149\b\149\000\000\003}\003}\003}\000\000\003}\003}\b\149\003}\000\000\b\149\000\000\005)\000\000\000\000\b\149\b\149\b\149\000\000\003}\000\000\000\000\000\000\003}\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\149\000\000\000\000\003}\b\149\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\b\149\b\149\b\149\000\000\b\149\b\149\000\000\b\149\rm\rm\000\000\000\000\000\000\rm\000\000\b\149\rm\000\000\b\149\000\000\000\000\000\000\b\149\000\000\000\000\000\000\rm\000\000\rm\000\000\rm\004\254\rm\b\149\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\rm\000\000\000\000\000\000\000\000\000\000\rm\rm\rq\rq\000\000\000\000\004B\rq\000\000\rm\rq\000\000\rm\000\000\000\000\000\000\000\000\rm\rm\rm\rq\000\000\rq\000\000\rq\000\000\rq\000\000\000\000\000\000\000\000\000\000\000\000\rm\000\000\000\000\000\000\rm\rq\000\000\000\000\000\000\000\000\000\000\rq\rq\000\000\rm\rm\rm\004B\rm\rm\rq\rm\000\000\rq\000\000\004R\000\000\000\000\rq\rq\rq\000\000\rm\000\000\000\000\000\000\rm\000\000\000\000\000\000\000\000\000\000\000\000\000\000\rq\000\000\000\000\rm\rq\000\000\000\000\t\025\000\000\000\000\000\000\000\000\000\000\000\000\rq\rq\rq\000\000\rq\rq\000\000\rq\000\000\t\214\000\000\004R\012F\t\025\000\000\t\025\t\025\000\000\rq\000\000\000\000\000\000\rq\n\014\n&\n.\n\022\n6\000\000\000\000\000\000\000\000\000\000\rq\001\205\000\000\000\000\n>\nF\001\205\000\000\001\206\001\205\000\000\000\000\000\000\nN\000\000\000\000\000\000\b\245\000\000\001\205\000\000\000\238\000\000\001\205\000\000\001\205\000\000\000\000\000\000\000\000\t\222\n\030\nV\n^\nn\000\000\000\000\001\205\000\000\000\000\000\000\000\000\nv\001\205\001\205\000\000\000\000\000\000\000\000\000\000\002\154\n~\001\205\000\000\000\000\001\205\000\000\000\000\000\000\000\000\001\205\001\205\001\205\000\000\000\000\000\000\n\158\000\000\n\166\nf\000\000\000\000\000\000\000\000\t\025\n\134\001\205\001\205\000\000\000\000\004\154\000\000\000\000\n\142\n\150\000\000\000\000\000\000\000\000\000\000\001\205\001\205\000\000\000\000\001\205\001\205\000\000\001\205\000\000\000\000\000\000\000\000\003a\000\000\000\000\001\205\000\000\003a\000\000\001\206\003a\000\000\001\205\000\000\000\000\000\000\000\000\001\205\b\241\000\000\003a\000\000\000\000\001\205\003a\000\000\003a\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003a\000\000\000\000\000\000\000\000\000\000\003a\001\201\000\000\000\000\000\000\000\000\000\000\002\154\000\000\003a\000\000\000\000\003a\000\000\000\000\000\000\000\000\003a\003a\003a\000\000\000\000\000\181\000\000\000\000\000\000\000\000\000\181\000\000\000\000\000\181\000\000\000\000\003a\003a\000\000\000\000\004\154\000\000\000\000\000\181\000\000\000\181\000\000\000\181\000\000\000\181\003a\003a\000\000\000\000\003a\003a\000\000\003a\000\000\000\000\000\000\000\181\000\000\000\000\000\000\003a\000\000\000\181\000\000\000\000\000\000\000\181\003a\000\000\000\000\000\000\000\181\003a\000\000\000\181\000\000\000\000\000\000\003a\000\181\000\181\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\181\000\181\000\000\000\000\000\000\000\000\000\000\000\181\000\000\000\249\000\000\000\181\000\000\000\000\000\249\000\000\000\000\000\249\000\000\000\000\000\000\000\181\000\181\000\000\000\000\000\181\000\181\000\249\000\181\000\249\000\000\000\249\000\000\000\249\000\000\000\000\000\181\000\000\000\000\000\000\000\000\000\000\000\181\000\181\000\000\000\249\000\000\000\000\000\000\000\000\000\000\000\249\000\181\000\000\000\181\000\249\000\000\000\000\000\000\000\000\000\249\000\000\000\000\000\249\000\000\000\000\000\000\000\000\000\249\000\249\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\249\000\249\000\000\000\000\000\000\000\000\000\000\000\249\000\000\000\189\000\000\000\249\000\000\000\000\000\189\000\000\000\000\000\189\000\000\000\000\000\000\000\249\000\249\000\000\000\000\000\249\000\249\000\189\000\249\000\189\000\000\000\189\000\000\000\189\000\000\000\000\000\249\000\000\000\000\000\000\000\000\000\000\000\249\000\249\000\000\000\189\000\000\000\000\000\000\000\000\000\000\000\189\000\249\000\000\000\249\000\189\000\000\000\000\000\000\000\000\000\189\000\000\000\000\000\189\000\000\000\000\000\000\000\000\000\189\000\189\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\189\000\189\000\000\000\000\000\000\000\000\000\000\000\189\000\000\000\185\000\000\000\189\000\000\000\000\000\185\000\000\000\000\000\185\000\000\000\000\000\000\000\189\000\189\000\000\000\000\000\189\000\189\000\185\000\189\000\185\000\000\000\185\000\000\000\185\000\000\000\000\000\189\000\000\000\000\000\000\000\000\000\000\000\189\000\189\000\000\000\185\000\000\000\000\000\000\000\000\000\000\000\185\000\189\000\000\000\189\000\185\000\000\000\000\000\000\000\000\000\185\000\000\000\000\000\185\000\000\000\000\000\000\000\000\000\185\000\185\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\185\000\185\000\000\000\000\000\000\000\000\000\000\000\185\000\000\000\000\000\000\000\185\000\000\000\000\000\000\001\006\000\000\000\000\000\000\000\000\000\000\000\185\000\185\000\000\000\000\000\185\000\185\000\000\000\185\000\000\000\000\001\n\000\000\000\000\000\000\000\000\000\185\000\000\000\000\000\000\000\000\000\000\000\185\000\185\001\014\001\018\001\022\001\026\001\030\001\"\000\000\000\000\000\185\000\000\000\185\000\000\000\000\001&\000\000\001.\0012\000\000\000\000\000\000\000\000\0016\000\000\000\000\001:\000\000\000\000\000\000\000\000\000\000\001\169\000\000\000\000\000\000\000\000\001\169\000\000\000\000\001\169\000\000\000\000\001>\001B\001F\001J\001N\000\000\000\000\001\169\001R\000\000\000\000\001\169\001V\001\169\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001Z\000\000\000\000\000\000\001\169\001\169\000\000\001^\000\000\000\000\001\169\000\000\000\000\000\000\000\000\000\000\005%\001\154\027\178\001\169\000\000\000\000\001\169\000\000\001\158\000\000\001\162\001\169\001\169\001\169\001\166\000\000\001\170\001\174\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\169\000\000\ri\ri\001\169\000\000\000\000\ri\000\000\000\000\ri\000\000\000\000\000\000\001\169\001\169\000\000\000\000\001\169\001\169\ri\001\169\ri\000\000\ri\005%\ri\000\000\000\000\001\169\000\000\000\000\000\000\000\000\000\000\001\169\001\169\000\000\ri\006i\000\000\001\169\000\000\000\000\ri\ri\002\190\001\169\000\000\002\130\000\000\000\000\000\000\ri\002\246\000\000\ri\000\000\000\000\006i\000\000\ri\ri\ri\001\210\000\000\000\000\000\000\002\250\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\ri\000\000\002\254\000\000\ri\000\000\000\000\000\000\000\000\000\000\0032\001\190\000\000\000\000\ri\ri\ri\002\178\ri\ri\003:\ri\re\re\b&\b*\b6\re\000\000\005v\re\000\000\ri\000\000\000\000\000\000\ri\000\000\000\000\000\000\re\000\000\re\000\000\re\004\254\re\ri\000\000\005\130\005\134\000\000\000\000\000\000\000\000\000\000\000\000\000\000\re\000\000\000\000\000\000\000\000\000\000\re\re\000\000\000\000\000\000\000\000\000\000\000\000\000\000\re\005\138\b>\re\000\000\000\000\bV\004r\re\re\re\000\000\000\000\000\000\000\000\000\000\001\202\001\206\000\000\000\000\000\000\000\000\000\000\000\000\re\000\000\b\153\b\153\re\000\000\000\000\b\153\000\000\000\000\b\153\001\210\001\214\000\000\re\re\re\000\000\re\re\b\153\re\b\153\000\000\b\153\000\000\b\153\000\000\000\000\007V\000\000\000\000\re\000\000\001\246\002\162\re\000\000\b\153\002\158\000\000\002\178\004\030\004*\b\153\b\153\000\000\re\0046\000\000\000\000\000\000\000\000\b\153\000\000\000\000\b\153\000\000\000\000\000\000\000\000\b\153\b\153\000\238\000\000\004:\001\201\000\000\026~\000\000\000\000\001\201\000\000\001\206\001\201\000\000\000\000\b\153\000\000\000\000\000\000\b\153\b\241\000\000\001\201\026j\000\000\000\000\001\201\000\000\001\201\b\153\b\153\b\153\000\000\b\153\b\153\000\000\b\153\000\000\000\000\000\000\001\201\000\000\000\000\000\000\b\153\000\000\001\201\b\153\000\000\000\000\000\000\b\153\000\000\002\154\000\000\001\201\000\000\000\000\001\201\000\000\000\000\000\000\b\153\001\201\001\201\001\201\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\201\001\201\000\000\000\000\004\154\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\201\001\201\000\000\000\000\001\201\001\201\000\000\001\201\000\000\000\000\000\000\000\000\004\129\000\000\000\000\001\201\000\000\000\246\001\202\001\206\002\018\000\000\001\201\000\000\000\000\000\000\000\000\001\201\000\000\000\000\018\n\000\000\000\000\001\201\004\129\000\000\003\182\001\210\001\214\001\230\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\242\018\014\000\000\000\000\000\000\000\000\000\000\0186\000\000\000\000\000\000\000\000\000\000\001\246\002\146\000\000\000\000\000\000\002\158\017\030\002\178\004\030\004*\000\000\0176\000\000\000\000\0046\000\000\005\201\005\201\000\000\000\000\000\000\005\201\000\000\000\000\005\201\000\000\000\000\018\178\000\000\000\000\000\000\004:\000\000\000\000\005\201\000\000\005\201\000\000\005\201\000\000\005\201\017R\018\198\000\000\000\000\004\129\004\129\000\000\018\214\000\000\000\000\000\000\005\201\000\000\000\000\000\000\000\000\000\000\005\201\005\201\005\197\007*\000\000\018\230\007\234\005\197\000\000\005\201\005\197\000\000\005\201\000\000\000\000\000\000\000\000\005\201\005\201\000\238\005\197\000\000\005\197\000\000\005\197\000\000\005\197\000\000\000\000\000\000\000\000\000\000\000\000\005\201\000\000\000\000\000\000\005\201\005\197\000\000\000\000\000\000\000\000\000\000\005\197\007\150\000\000\005\201\005\201\005\201\000\000\005\201\005\201\005\197\005\201\000\000\005\197\000\000\000\000\000\000\000\000\005\197\005\197\000\238\000\000\005\201\000\000\000\000\000\000\005\201\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\197\000\000\000\000\005\201\005\197\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\197\005\197\005\197\000\000\005\197\005\197\000\000\005\197\005\225\005\225\000\000\000\000\000\000\005\225\000\000\000\000\005\225\000\000\005\197\000\000\000\000\000\000\005\197\000\000\000\000\000\000\005\225\000\000\005\225\n\234\005\225\000\000\005\225\005\197\000\000\001\202\001\206\011J\000\000\000\000\000\000\000\000\000\000\000\000\005\225\000\000\000\000\000\000\000\000\000\000\005\225\005\225\005\221\007*\001\210\002\170\001\230\005\221\000\000\005\225\005\221\000\000\005\225\000\000\001\242\000\000\000\000\005\225\005\225\005\225\005\221\000\000\005\221\000\000\005\221\000\000\005\221\001\246\002\146\000\000\000\000\000\000\002\158\005\225\002\178\004\030\004*\005\225\005\221\000\000\000\000\0046\000\000\000\000\005\221\007\150\000\000\005\225\005\225\005\225\000\000\005\225\005\225\005\221\005\225\007\017\005\221\000\000\004:\000\000\000\000\005\221\005\221\000\238\000\000\005\225\000\000\000\000\000\000\005\225\000\000\t\214\000\000\000\000\007\017\000\000\000\000\005\221\007\017\000\000\007\142\005\221\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\005\221\005\221\005\221\000\000\005\221\005\221\000\000\005\221\n>\nF\000\000\000\000\000\000\000\000\000\000\000\000\000\000\nN\005\221\000\000\000\000\000\000\005\221\000\000\000\000\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\221\t\222\n\030\nV\n^\nn\000\000\000\000\000\000\003]\000\000\000\000\007\017\nv\003]\000\000\001\206\003]\000\000\000\000\000\000\000\000\n~\000\000\001\202\001\206\000\000\003]\000\000\000\000\000\000\003]\000\000\003]\000\000\000\000\000\000\n\158\000\000\n\166\nf\000\000\000\000\001\210\001\214\003]\n\134\000\000\000\000\000\000\000\000\003]\000\000\000\000\n\142\n\150\000\000\000\000\002\154\000\000\003]\000\000\016n\003]\000\000\000\000\001\246\002\162\003]\003]\003]\002\158\000\000\002\178\004\030\004*\000\000\000\000\t\214\000\000\0046\000\000\016r\000\000\003]\003]\000\000\000\000\004\154\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\004:\003]\003]\004\237\000\000\003]\003]\001M\003]\n>\nF\000\000\001M\000\000\000\000\001M\003]\000\000\nN\000\000\026j\000\000\000\000\003]\000\000\001M\000\238\001M\003]\001M\000\000\001M\000\000\000\000\003]\t\222\n\030\nV\n^\nn\000\000\000\000\000\000\001M\000\000\000\000\000\000\nv\000\000\001M\000\000\000\000\000\000\001M\000\000\000\000\n~\000\000\001M\000\000\000\000\001M\000\000\000\000\000\000\000\000\001M\001M\000\238\000\000\000\000\n\158\016v\n\166\nf\016\134\001M\000\000\000\000\000\000\n\134\000\000\001M\000\000\000\000\000\000\001M\000\000\n\142\n\150\000\000\000\000\000\000\000\000\000\000\000\000\001M\001M\001M\001I\001M\001M\000\000\001M\001I\000\000\000\000\001I\000\000\000\000\000\000\001M\000\000\000\000\000\000\000\000\000\000\001I\001M\001I\000\000\001I\000\000\001I\000\000\000\000\000\000\000\000\000\000\001M\000\000\000\000\000\000\000\000\000\000\001I\000\000\000\000\000\000\000\000\000\000\001I\000\000\000\000\000\000\001I\000\000\000\000\000\000\000\000\001I\000\000\000\000\001I\000\000\000\000\000\000\000\000\001I\001I\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001I\000\000\000\000\000\000\000\000\000\000\001I\000\000\000\000\000\000\001I\000\000\000\000\001\202\001\206\000\000\000\000\000\000\000\000\000\000\001I\001I\001I\001\133\001I\001I\000\000\001I\001\133\000\000\012\197\001\133\001\210\001\214\000\000\001I\000\000\000\000\000\000\012\197\000\000\001\133\001I\001\133\000\000\001\133\000\000\001\133\000\000\000\000\000\000\000\000\000\000\001I\000\000\001\246\002\162\000\000\000\000\001\133\002\158\000\000\002\178\004\030\004*\001\133\012\197\000\000\000\000\0046\000\000\000\000\012\197\000\000\000\000\000\000\000\000\001\133\000\000\000\000\000\000\000\000\001\133\001\133\001\133\000\000\004:\0019\000\000\004\241\000\000\000\000\0019\000\000\000\157\0019\000\000\000\000\001\133\000\000\000\000\000\000\012\197\000\157\000\000\0019\026j\0019\000\000\0019\000\000\0019\001\133\001\133\001\133\000\000\001\133\001\133\000\000\001\133\000\000\000\000\000\000\0019\000\000\000\000\000\000\000\000\000\000\0019\000\157\000\000\000\000\000\000\001\133\000\000\000\157\000\000\000\000\000\000\000\000\0019\000\000\000\000\000\000\001\133\0019\0019\0019\000\000\000\000\001\213\000\000\000\000\000\000\000\000\001\213\000\000\015\142\001\213\000\000\002\130\0019\000\000\000\000\000\000\000\157\000\000\000\000\001\213\000\000\000\000\000\000\001\213\000\000\001\213\0019\0019\0019\000\000\0019\0019\000\000\0019\000\000\000\000\000\000\001\213\000\000\000\000\000\000\000\000\000\000\001\213\000\000\000\000\000\000\000\000\0019\015\146\000\000\000\000\001\213\000\000\000\000\001\213\000\000\000\000\000\000\0019\001\213\001\213\000\000\015\158\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\213\003V\002\190\000\000\001\213\002\130\000\000\006\178\000\000\000\000\002\246\000\000\000\000\005\134\001\213\001\213\000\000\000\000\001\213\001\213\001\210\001\213\006\210\000\000\000\000\000\000\000\000\003Z\000\000\001\213\b\238\000\000\000\000\000\000\000\000\000\000\001\213\000\000\000\000\000\000\003f\000\000\000\000\n\186\001\190\000\000\000\000\001\213\000\000\000\000\002\178\000\000\000\000\003\246\000\000\004y\007*\003\250\000\000\004\002\004y\n\202\005v\004y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004y\005z\000\000\000\000\004y\000\000\004y\000\000\000\000\005\130\005\134\000\000\000\000\n\210\000\000\000\000\000\000\000\000\004y\000\000\000\000\000\000\000\000\000\000\004y\007\150\000\000\000\000\004y\n\218\007\234\000\000\n\230\004y\005\138\000\000\004y\000\000\000\000\000\000\004r\004y\002\226\000\238\000\000\000\000\000\000\000\000\000\000\000\000\004y\004y\000\000\000\000\000\000\000\000\000\000\004y\004y\000\000\000\000\004y\000\000\000\000\012\198\000\000\000\000\000\000\000\000\000\000\000\000\004y\004y\000\000\000\000\004y\004y\000\000\004y\000\000\t\214\000\000\007z\012F\000\000\000\000\004y\t\025\000\000\000\000\000\000\000\000\000\000\004y\n\014\n&\n.\n\022\n6\000\000\000\000\006\233\006\233\000\000\004y\003U\000\000\000\000\n>\nF\003U\000\000\000\000\003U\000\000\000\000\000\000\nN\000\000\000\000\006\233\006\233\006\233\003U\000\000\000\238\000\000\003U\000\000\003U\006\233\000\000\000\000\000\000\t\222\n\030\nV\n^\nn\000\000\000\000\003U\015\166\006\233\006\233\000\000\nv\003U\006\233\000\000\006\233\006\233\006\233\000\000\000\000\n~\003U\006\233\000\000\003U\000\000\000\000\000\000\000\000\003U\003U\003U\000\000\000\000\000\000\n\158\000\000\n\166\nf\006\233\000\000\000\000\000\000\000\000\n\134\003U\000\000\000\000\000\000\003U\000\000\000\000\n\142\n\150\000\000\000\000\000\000\000\000\000\000\003U\003U\025\238\000\000\003U\003U\000\000\003U\000\000\000\000\000\000\000\000\000Y\000\000\000\000\003U\000\000\000Y\000\000\000Y\000\000\016\006\003U\000\000\004\230\000\000\000\000\003U\000Y\000\000\000\000\000Y\000\000\003U\000\000\000Y\000Y\000\000\b\181\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000Y\000\000\000\000\000Y\000\000\000\000\000Y\000\000\000\000\000\000\000\000\000Y\000\000\000\000\000\000\000\000\000Y\000Y\000Y\000\000\000\000\000\000\000\000\000\000\000\000\000Y\000Y\005\194\000\000\000\000\000\000\000\000\000\000\003V\002\190\000\000\000Y\002\130\000\000\000Y\000\000\000\000\002\246\000\000\000\000\000\000\000\000\005\198\000Y\003\254\000\000\000Y\001\210\000\000\000\000\000\000\000\000\b\181\000\000\003Z\000\000\000Y\000\000\000\000\000Y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003f\t5\000\000\003r\001\190\000Y\000\000\003V\002\190\000\000\002\178\002\130\000\000\003\246\000\000\000\000\002\246\003\250\000\000\004\002\005j\000\000\005v\t5\000\000\000\000\001\210\000\000\000\000\000\000\000\000\000\000\000\000\003Z\005z\000\000\004Y\000\000\000\000\000\000\000\000\004Y\005\130\005\134\004Y\005\202\003f\000\000\000\000\003r\001\190\005\214\000\000\000\000\004Y\000\000\002\178\000\000\004Y\003\246\004Y\000\000\000\000\003\250\006&\004\002\005j\005\138\005v\006\158\000\000\b\214\004Y\004r\000\000\003V\002\190\000\000\004Y\002\130\005z\006\178\000\000\000\000\002\246\000\000\000\000\000\000\005\130\005\134\004Y\005\202\000\000\000\000\001\210\004Y\006\210\005\214\000\000\000\000\000\000\003Z\000\000\000\000\b\238\000\000\000\000\000\000\000\000\000\000\000\000\004Y\t2\005\138\003f\t5\000\000\r\178\001\190\004r\000\000\012\"\000\000\000\000\002\178\004Y\004Y\003\246\000\000\004Y\004Y\003\250\004Y\004\002\000\000\n\202\005v\t\214\000\000\000\000\000\000\000\000\000\000\000\000\012&\000\000\000\000\004Y\005z\000\000\000\000\n\014\n&\n.\n\022\n6\005\130\005\134\018j\000\000\000\000\000\000\000\000\000\000\000\000\n>\nF\000\000\000\000\000\000\000\000\000\000\000\000\000\000\nN\000\000\000\000\000\000\000\000\r\194\000\000\005\138\000\238\000\000\000\000\000\000\000\000\004r\012\"\000\000\000\000\t\222\n\030\nV\n^\nn\000\000\000\000\000\000\000\000\000\000\000\000\000\000\nv\t\214\000\000\000\000\000\000\000\000\000\000\000\000\012\254\n~\000\000\000\000\000\000\000\000\000\000\n\014\n&\n.\n\022\n6\000\000\000\000\000\000\000\000\n\158\000\000\n\166\nf\000\000\n>\nF\000\000\000\000\n\134\000\000\000\000\000\000\006\006\nN\000\000\000\000\n\142\n\150\003V\002\190\000\000\000\238\002\130\000\000\006\178\000\000\000\000\002\246\000\000\000\000\t\222\n\030\nV\n^\nn\000\000\000\000\001\210\000\000\006\210\000\000\000\000\nv\000\000\003Z\000\000\000\000\b\238\000\000\000\000\000\000\n~\000\000\000\000\000\000\023\170\000\000\003f\000\000\000\000\003r\001\190\000\000\000\000\000\000\000\000\n\158\002\178\n\166\nf\003\246\000\000\000\000\000\000\003\250\n\134\004\002\005j\n\202\005v\000\000\000\000\000\000\n\142\n\150\000\000\003V\002\190\000\000\000\000\002\130\005z\006\178\000\000\000\000\002\246\000\000\000\000\000\000\005\130\005\134\000\000\005\202\022\026\000\000\001\210\000\000\006\210\005\214\000\000\000\000\000\000\003Z\000\000\000\000\b\238\000\000\000\000\000\000\000\000\000\000\000\000\024v\000\000\005\138\003f\000\000\000\000\n\186\001\190\004r\000\000\000\000\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\000\000\n\202\005v\000\000\000\000\000\000\000\000\000\000\000\000\003V\002\190\000\000\000\000\002\130\005z\006\178\000\000\000\000\002\246\000\000\000\000\000\000\005\130\005\134\000\000\000\000\n\210\000\000\001\210\000\000\006\210\000\000\000\000\000\000\000\000\003Z\000\000\000\000\b\238\000\000\000\000\000\000\000\000\000\000\000\000\022\178\000\000\005\138\003f\000\000\000\000\n\186\001\190\004r\000\000\000\000\000\000\000\000\002\178\000\000\000\000\003\246\000\000\003U\000\000\003\250\000\000\004\002\003U\n\202\005v\003U\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003U\005z\000\000\000\000\003U\000\000\003U\000\000\000\000\005\130\005\134\000\000\000\000\n\210\000\000\003U\000\000\000\000\003U\015\166\003U\000\000\000\000\003U\003U\000\000\000\000\000\000\000\000\000\000\000\000\000\000\023\018\003U\005\138\000\000\003U\003U\000\000\003U\004r\003U\003U\003U\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003U\015\166\000\000\000\000\000\000\000\000\003U\000\000\012\189\000\000\003U\000\000\000\000\012\189\000\000\003U\012\189\000\000\003U\000\000\003U\003U\026\030\003U\003U\003U\012\189\003U\000\000\000\000\012\189\000\000\012\189\000\000\000\000\000\000\000\000\000\000\005\029\003U\000\000\016\006\003U\003U\012\189\000\000\000\000\003U\000\000\000\000\012\189\000\000\000\000\003U\003U\017\142\000\000\003U\003U\012\189\003U\000\000\012\189\000\000\000\000\000\000\000\000\012\189\012\189\000\000\000\000\000\000\005u\000\000\016\006\003U\000\000\005u\000\000\000\000\005u\000\000\000\000\012\189\000\000\000\000\000\000\012\189\000\000\000\000\005u\000\000\000\000\000\000\005u\000\000\005u\012\189\012\189\002z\000\000\012\189\012\189\000\000\012\189\000\000\000\000\000\000\005u\000\000\000\000\000\000\012\189\000\000\005u\000\000\005y\000\000\000\000\012\189\007\234\005y\000\000\005u\005y\000\000\005u\000\000\000\000\000\000\012\189\005u\005u\000\238\005y\000\000\000\000\000\000\005y\000\000\005y\000\000\000\000\000\000\000\000\000\000\000\000\005u\005u\000\000\000\000\005u\005y\000\000\000\000\000\000\000\000\000\000\005y\000\000\000\000\005u\005u\000\000\007\234\005u\005u\005y\005u\000\000\005y\000\000\000\000\000\000\000\000\005y\005y\000\238\000\000\000\000\001\241\000\000\000\000\005u\000\000\001\241\000\000\001\206\001\241\000\000\000\000\005y\005y\000\000\005u\005y\b\241\000\000\001\241\000\000\000\000\000\000\001\241\000\000\001\241\005y\005y\000\000\000\000\005y\005y\000\000\005y\000\000\000\000\000\000\001\241\000\000\000\000\000\000\000\000\000\000\001\241\001\253\000\000\000\000\000\000\005y\000\000\002\154\000\000\001\241\000\000\000\000\001\241\000\000\006!\000\000\005y\001\241\001\241\006!\000\000\000\000\006!\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006!\001\241\000\000\000\000\006!\004\154\006!\000\000\000\000\001\202\002~\000\000\000\000\002\130\000\000\001\241\001\241\000\000\006!\001\241\001\241\000\000\001\241\000\000\006!\000\000\000\000\000\000\001\210\001\214\001\230\000\000\000\000\006!\000\000\000\000\006!\001\241\001\242\000\000\000\000\006!\006!\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\138\002\146\000\000\000\000\000\000\002\158\006!\002\178\004\030\004*\006!\000\000\000\000\000\000\021Z\000\000\026\194\000\000\000\000\000\000\006!\006!\021\166\000\000\006!\006!\000\000\006!\004a\004a\000\000\004:\004a\000\000\000\000\006!\000\000\004a\000\000\000\000\005\134\000\000\006!\004a\000\000\000\000\000\000\004a\000\000\000\000\000\000\026\206\000\000\006!\004a\023b\000\000\000\000\023z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\025\198\004a\021n\000\000\004a\004a\003V\002\190\000\000\000\000\002\130\004a\000\000\000\000\004a\002\246\000\000\000\238\004a\000\000\004a\004a\006b\004a\000\000\001\210\000\000\000\000\000\000\000\000\000\000\000\000\003Z\000\000\000\000\004a\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004a\004a\003f\000\000\000\000\003r\001\190\000\000\000\000\000\000\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\005j\000\000\005v\004a\000\000\000\000\000\000\000\000\012\189\004a\000\000\000\000\000\000\012\189\005z\000\000\012\189\000\000\000\000\000\000\000\000\000\000\005\130\005\134\000\000\005\202\012\189\006>\000\000\000\000\012\189\005\214\012\189\003V\002\190\000\000\000\000\002\130\005\029\000\000\000\000\000\000\002\246\000\000\012\189\000\000\000\000\005\138\000\000\000\000\012\189\b\214\001\210\004r\000\000\000\000\000\000\000\000\000\000\003Z\000\000\000\000\012\189\000\000\000\000\000\000\000\000\012\189\012\189\000\000\000\000\000\000\003f\000\000\000\000\003r\001\190\000\000\000\000\000\000\000\000\000\000\002\178\012\189\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\005j\000\000\005v\000\000\000\000\012\189\012\189\002z\000\000\012\189\012\189\006J\012\189\000\000\005z\000\000\000\000\003V\002\190\000\000\012\189\002\130\005\130\005\134\026\222\005\202\002\246\012\189\000\000\000\000\000\000\005\214\000\000\000\000\000\000\000\000\001\210\000\000\012\189\000\000\000\000\000\000\000\000\003Z\000\000\000\000\000\000\005\138\000\000\000\000\000\000\000\000\000\000\004r\000\000\000\000\003f\000\000\000\000\003r\001\190\000\000\000\000\000\000\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\005j\000\000\005v\000\000\000\000\000\000\000\000\003V\002\190\000\000\000\000\002\130\000\000\006\178\005z\000\000\002\246\000\000\000\000\000\000\000\000\000\000\005\130\005\134\000\000\005\202\001\210\000\000\006\210\000\000\000\000\005\214\000\000\003Z\000\000\000\000\b\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011\178\003f\005\138\000\000\t\026\001\190\003V\002\190\004r\000\000\002\130\002\178\000\000\000\000\003\246\002\246\000\000\000\000\003\250\000\000\004\002\000\000\n\202\005v\000\000\001\210\000\000\011\190\000\000\000\000\000\000\000\000\003Z\003V\002\190\005z\000\000\002\130\000\000\000\000\000\000\000\000\002\246\005\130\005\134\003f\000\000\000\000\003r\001\190\000\000\000\000\001\210\000\000\000\000\002\178\000\000\000\000\003\246\003Z\000\000\000\000\003\250\000\000\004\002\005j\000\000\005v\005\138\000\000\000\000\000\000\003f\000\000\004r\003r\001\190\000\000\000\000\005z\000\000\000\000\002\178\000\000\000\000\003\246\000\000\005\130\005\134\003\250\005\202\004\002\005j\000\000\005v\011\202\005\214\000\000\000\000\000\000\000\000\003V\002\190\000\000\000\000\002\130\005z\000\000\000\000\000\000\002\246\000\000\005\138\000\000\005\130\005\134\000\000\005\202\004r\000\000\001\210\000\000\000\000\005\214\000\000\000\000\000\000\003Z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\138\003f\000\000\000\000\003r\001\190\004r\000\000\000\000\000\000\000\000\002\178\000\000\000\000\003\246\000\000\000\000\000\000\003\250\000\000\004\002\005j\000\000\005v\000\000\000\000\000\000\000\000\000\000\007\025\007*\000\000\000\000\000\000\007\025\005z\000\000\007\025\000\000\000\000\000\000\000\000\000\000\005\130\005\134\000\000\005\202\007\025\000\000\000\000\000\000\007\025\005\214\007\025\000\000\001\217\000\000\000\000\000\000\000\000\001\217\000\000\000\000\001\217\000\000\007\025\000\000\000\000\005\138\000\000\000\000\007\025\007\150\001\217\004r\000\000\000\000\001\217\000\000\001\217\007\025\000\000\000\000\007\025\000\000\000\000\000\000\000\000\007\025\007\025\000\238\001\217\000\000\000\000\000\000\000\000\000\000\001\217\000\000\000\000\000\000\000\000\000\000\000\000\007\025\000\000\001\217\000\000\007\025\001\217\000\000\000\000\000\000\000\000\001\217\001\217\000\000\000\000\007\025\007\025\000\000\000\000\007\025\007\025\000\000\007\025\000\000\000\000\006%\000\000\001\217\000\000\000\000\006%\001\217\000\000\006%\000\000\000\000\000\000\007\025\000\000\000\000\000\000\001\217\001\217\006%\000\000\001\217\001\217\006%\001\217\006%\000\000\000\000\000\000\000\000\000\000\000\000\001\217\000\000\000\000\000\000\000\000\006%\000\000\001\217\000\000\000\000\000\000\006%\021\130\000\000\000\000\000\000\000\000\000\000\001\217\000\000\006%\000\000\000\000\006%\000\000\000\000\000\000\000\000\006%\006%\000\238\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\189\000\000\006%\000\000\000\000\012\189\006%\000\000\012\189\000\000\000\000\000\000\000\000\000\000\001\202\001\206\006%\006%\012\189\000\000\006%\006%\012\189\006%\012\189\000\000\000\000\000\000\002\142\000\000\005\029\006%\000\000\001\210\001\214\001\230\012\189\000\000\006%\000\000\000\000\000\000\012\189\001\242\000\000\000\000\000\000\000\000\000\000\006%\001\250\000\000\000\000\000\000\012\189\000\000\001\246\002\146\000\000\012\189\012\189\002\158\000\000\002\178\004\030\004*\012u\000\000\002\190\012u\0046\028j\000\000\000\000\000\000\012\189\028n\000\000\000\000\012u\000\000\000\000\000\000\000\000\000\000\012u\000\000\004:\000\000\012\189\012\189\002z\000\000\012\189\012\189\000\000\012\189\012u\000\000\000\000\000\000\000\000\000\000\012u\012\189\000\000\000\000\000\000\027\022\001\002\001\190\012\189\012u\000\000\000\000\012u\000\000\015\150\000\000\004y\012u\000\000\012\189\000\000\004y\000\000\004r\004y\028r\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012u\004y\000\000\000\000\012u\004y\000\000\004y\000\000\000\000\000\000\000\000\000\000\028v\012u\012u\000\000\000\000\012u\004y\000\000\012u\000\000\000\000\000\000\004y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004y\000\000\012u\004y\000\000\000\000\000\000\000\000\004y\002\226\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004y\000\000\000\000\000\000\004y\000\000\000\000\000\000\000\000\000\000\006m\000\000\000\000\000\000\004y\004y\003V\002\190\004y\004y\002\130\004y\000\000\000\000\000\000\002\246\000\000\000\000\000\000\007V\006m\000\000\000\000\000\000\000\000\001\210\004y\000\000\000\000\000\000\000\000\025\230\003Z\000\000\000\000\000\000\000\000\004y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003f\006\145\000\000\003r\001\190\000\000\000\000\000\000\002\190\000\000\002\178\002\130\000\000\003\246\000\000\000\000\002\246\003\250\000\000\004\002\005j\006\145\005v\000\000\000\000\000\000\001\210\000\000\000\000\000\000\002\250\000\000\000\000\000\000\005z\000\000\000\000\000\000\000\000\000\000\000\000\002\254\005\130\005\134\000\000\000\000\000\000\000\000\000\000\0032\001\190\000\000\000\000\000\000\000\000\000\000\002\178\000\000\000\000\003:\000\000\000\000\000\000\b&\b*\b6\000\000\005\138\005v\000\000\000\000\000\000\000\000\004r\001\237\000\000\000\000\000\000\000\000\001\237\000\000\001\206\001\237\000\000\000\000\001q\000\000\000\000\005\130\005\134\001q\000\000\001\237\001q\000\000\000\000\001\237\000\000\001\237\000\000\000\000\000\000\000\000\001q\000\000\001q\000\000\001q\000\000\001q\001\237\000\000\000\000\005\138\b>\000\000\001\237\000\000\bV\004r\000\000\001q\000\000\002\154\000\000\001\237\000\000\001q\001\237\000\000\000\000\000\000\000\000\001\237\001\237\000\000\000\000\000\000\000\000\001q\000\000\000\000\000\000\000\000\001q\001q\000\238\000\000\000\000\001\237\000\000\000\000\000\000\004\154\000\000\000\000\000\000\000\000\000\000\000\000\001q\000\000\000\000\001\237\001\237\000\000\000\000\001\237\001\237\000\000\001\237\000\000\006\237\006\237\001q\001q\001q\000\000\001q\001q\000\000\001q\000\237\000\000\000\000\001\237\000\000\000\237\004.\000\000\000\237\006\237\006\237\006\237\000\000\000\000\001q\000\000\000\000\000\000\000\237\006\237\000\000\000\000\000\237\000\000\000\237\001q\000\000\000\000\000\000\000\000\000\000\000\000\006\237\006\237\000\000\000\000\000\237\006\237\000\000\006\237\006\237\006\237\000\237\000\000\000\241\000\000\006\237\000\000\000\000\000\241\000\000\000\237\000\241\000\000\000\237\000\000\000\000\000\000\000\000\000\237\000\237\000\238\000\241\006\237\000\000\000\000\000\241\000\000\000\241\000\000\000\000\000\000\000\000\000\000\000\000\000\237\000\000\000\000\000\000\000\237\000\241\000\000\000\000\000\000\000\000\000\000\000\241\000\000\000\000\000\237\000\237\000\000\000\000\000\237\000\237\000\241\000\237\000\000\000\241\000\000\004\"\000\000\006\237\000\241\000\241\000\238\000\000\000\000\000\000\bU\bU\000\237\000\000\bU\000\000\000\000\000\000\000\000\bU\000\241\000\000\000\000\000\237\000\241\0166\000\000\000\000\000\000\bU\000\000\000\000\000\000\000\000\000\241\000\241\bU\000\000\000\241\000\241\000\000\000\241\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bU\000\000\000\000\bU\bU\000\000\000\000\000\241\000\000\000\000\bU\000\000\000\000\bU\000\000\000\000\000\000\bU\000\241\bU\bU\000\000\bU\007\021\000\000\000\000\000\000\000\000\007\021\000\000\000\000\007\021\000\000\000\000\bU\000\000\000\000\000\000\000\000\000\000\000\000\007\021\bU\bU\000\000\007\021\000\000\007\021\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\021\000\000\000\000\000\000\000\000\000\000\007\021\000\000\bU\000\000\000\000\000\000\000\000\000\000\bU\007\021\000\000\000\000\007\021\000\000\006\025\000\000\000\000\007\021\007\021\006\025\000\000\000\000\006\025\000\000\000\000\000\000\000\000\000\000\000\000\017n\000\000\000\000\006\025\007\021\000\000\000\000\006\025\007\021\006\025\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\021\007\021\016\206\006\025\007\021\007\021\000\000\007\021\000\000\006\025\000\000\005\129\007*\000\000\000\000\000\000\005\129\000\000\006\025\005\129\000\000\006\025\007\021\000\000\000\000\000\000\006\025\006\025\000\000\005\129\000\000\000\000\000\000\005\129\000\000\005\129\000\000\000\000\000\000\000\000\012!\000\000\006\025\000\000\000\000\012!\006\025\005\129\012!\000\000\000\000\000\000\000\000\005\129\007\150\000\000\006\025\006\025\012!\000\000\006\025\006\025\012!\006\025\012!\005\129\000\000\000\000\000\000\000\000\005\129\005\129\000\238\000\000\000\000\000\000\012!\000\000\006\025\000\000\000\000\000\000\012!\000\000\004Q\000\000\005\129\000\000\000\000\004Q\000\000\012!\004Q\000\000\012!\000\000\000\000\000\000\000\000\012!\005\129\005\129\004Q\000\000\005\129\005\129\004Q\005\129\004Q\000\000\000\000\000\000\000\000\000\000\000\000\012!\t\202\000\000\000\000\012!\004Q\000\000\005\129\000\000\000\000\000\000\004Q\000\000\000\000\012!\012!\000\000\000\000\012!\012!\004Q\012!\000\000\004Q\000\000\000\000\000\000\000\000\004Q\000\000\000\000\000\000\000\000\004y\000\000\000\000\012!\000\000\004y\000\000\000\000\004y\000\000\000\000\004Q\000\000\000\000\n\174\004Q\000\000\000\000\004y\000\000\000\000\000\000\004y\000\000\004y\004Q\004Q\000\000\000\000\004Q\004Q\000\000\004Q\000\000\000\000\000\000\004y\000\000\000\000\000\000\000\000\000\000\004y\000\000\004I\000\000\000\000\004Q\004B\004I\000\000\000\000\004I\000\000\004y\000\000\000\000\000\000\016\246\004y\002\226\000\000\004I\000\000\000\000\000\000\004I\000\000\004I\000\000\000\000\000\000\000\000\000\000\000\000\004y\000\000\000\000\000\000\000\000\004I\000\000\000\000\000\000\000\000\000\000\004I\000\000\000\000\004y\004y\000\000\000\000\004y\004y\004I\004y\000\000\004I\000\000\004R\000\000\000\000\004I\000\000\000\000\000\000\000\000\004i\000\000\000\000\004y\000\000\004i\000\000\000\000\004i\000\000\000\000\004I\000\000\000\000\000\000\004I\000\000\000\000\004i\000\000\000\000\000\000\004i\000\000\004i\004I\004I\000\000\000\000\004I\004I\000\000\004I\000\000\000\000\000\000\004i\000\000\000\000\000\000\000\000\000\000\004i\000\000\0049\000\000\000\000\004I\000\000\0049\000\000\004i\0049\000\000\004i\000\000\000\000\000\000\020>\004i\000\000\000\000\0049\000\000\000\000\000\000\0049\000\000\0049\000\000\000\000\000\000\000\000\000\000\000\000\004i\000\000\000\000\000\000\004i\0049\000\000\000\000\000\000\000\000\000\000\0049\000\000\000\000\004i\004i\000\000\000\000\004i\004i\0049\004i\000\000\0049\000\000\000\000\000\000\000\000\0049\000\000\000\000\000\000\000\000\004y\000\000\000\000\004i\000\000\004y\000\000\000\000\004y\000\000\000\000\0049\000\000\000\000\021\030\0049\000\000\000\000\004y\000\000\000\000\000\000\004y\000\000\004y\0049\0049\000\000\000\000\0049\0049\000\000\0049\000\000\000\000\000\000\004y\000\000\000\000\000\000\000\000\000\000\004y\004A\000\000\000\000\000\000\0049\004A\000\000\000\000\004A\000\000\000\000\004y\000\000\000\000\000\000\024\150\004y\002\226\004A\000\000\000\000\000\000\004A\000\000\004A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004y\000\000\000\000\000\000\004A\000\000\000\000\000\000\000\000\000\000\004A\000\000\000\000\000\000\004y\004y\000\000\000\000\004y\004y\000\000\004y\004A\000\000\004q\000\000\000\000\004A\000\000\004q\000\000\000\000\004q\000\000\000\000\000\000\004y\000\000\000\000\000\000\000\000\021\130\004q\004A\000\000\000\000\004q\000\000\004q\000\000\000\000\004\141\000\000\000\000\000\000\000\000\000\246\004A\004A\002\194\004q\004A\004A\000\000\004A\000\000\004q\000\000\000\000\003\178\000\000\000\000\000\000\004\141\000\000\003\182\000\000\000\000\004q\004A\000\000\000\000\000\000\004q\000\000\000\000\000\000\003\186\000\000\000\000\020\202\000\000\000\000\016\186\000\000\000\000\000\000\000\000\000\000\004q\000\000\000\000\024\194\000\000\000\000\017\030\000\000\000\000\001\202\001\206\0176\000\000\000\000\004q\004q\000\000\000\000\004q\004q\000\000\004q\000\000\000\000\000\000\003\254\000\000\017>\001\210\001\214\001\230\000\000\000\000\000\000\000\000\000\000\004q\000\000\001\242\000\000\000\000\017R\017~\000\000\000\000\004\141\004\141\021F\017\186\000\000\000\000\001\246\002\146\000\000\012\133\000\000\002\158\012\133\002\178\004\030\004*\007\161\000\000\022\002\007\161\0046\000\000\012\133\000\000\000\000\000\000\000\000\000\000\012\133\000\000\000\000\000\000\000\000\000\000\000\000\007\161\007\161\004:\007\161\007\161\012\133\000\000\007\185\000\000\000\000\007\185\012\133\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012\133\000\000\000\000\012\133\007\161\000\000\007\185\007\185\012\133\007\185\007\185\000\000\000\000\007\141\000\000\000\000\007\141\000\000\000\000\004n\000\000\004r\007\161\000\000\012\133\000\000\000\000\000\000\012\133\000\000\007\185\000\000\007\141\007\141\000\000\007\141\007\141\000\000\012\133\012\133\000\000\000\000\012\133\000\000\000\000\012\133\000\000\000\000\000\238\028Z\000\000\000\000\007\161\000\000\007\161\000\000\007\141\000\000\000\000\000\000\012\133\000\000\000\000\000\000\000\000\007\189\000\000\005\250\007\189\000\000\007\161\007\161\000\000\000\000\007\141\007\161\000\000\007\161\007\185\000\000\007\185\007\161\000\000\000\000\007\189\007\189\000\000\007\189\007\189\000\000\000\000\007\169\000\000\007\185\007\169\000\000\006\002\007\185\000\000\000\000\000\000\007\185\000\000\007\185\007\141\000\000\007\141\007\185\007\189\000\000\007\169\007\169\000\000\007\169\007\169\000\000\000\000\001\202\001\206\007\141\000\000\000\000\006\002\007\141\000\000\000\000\000\238\007\141\000\000\007\141\000\000\000\000\000\000\007\141\007\169\000\000\001\210\001\214\001\230\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\242\000\000\000\000\019\022\000\000\000\000\000\238\000\000\000\000\000\000\007\189\000\000\007\189\001\246\020~\000\000\019\158\000\000\002\158\000\000\002\178\004\030\004*\000\000\000\000\007\189\000\000\020\142\006\002\007\189\000\000\000\000\000\000\007\189\000\000\007\189\007\169\000\246\007\169\007\189\002\194\000\000\000\000\000\000\004:\000\000\000\000\000\000\000\000\000\000\028\178\006:\000\000\000\000\006\002\007\169\003\182\000\000\000\000\007\169\000\000\007\169\000\000\000\000\000\000\007\169\000\000\000\000\003\186\000\000\000\000\000\000\000\000\000\000\016\186\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\024\194\ru\ru\017\030\000\000\000\000\n\222\000\000\0176\000\000\000\000\000\000\001\202\001\206\000\000\000\000\000\000\000\000\000\000\000\000\ru\ru\ru\007>\017>\000\000\000\000\000\000\028b\000\000\ru\001\210\001\214\001\230\000\000\000\000\000\000\000\000\017R\017~\n\234\001\242\004\181\ru\ru\017\186\001\202\001\206\ru\000\000\ru\ru\ru\000\000\001\246\002\146\000\000\ru\000\000\002\158\022\002\002\178\004\030\004*\000\000\001\210\001\214\001\230\0046\000\000\000\000\000\000\000\000\0116\ru\001\242\000\000\000\000\000\000\001\202\001\206\000\000\000\000\000\000\000\000\004:\000\000\000\000\001\246\002\146\000\000\000\000\000\000\002\158\000\000\002\178\004\030\004*\001\210\001\214\001\230\000\000\0046\000\000\001\202\001\206\022\182\000\000\001\242\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004:\000\000\001\246\002\146\001\210\002\170\001\230\002\158\000\000\002\178\004\030\004*\000\000\000\000\001\242\000\000\0046\000\000\001\202\001\206\023\022\000\000\000\000\000\000\000\000\000\000\000\000\001\246\002\146\000\000\000\000\000\000\002\158\004:\002\178\004\030\004*\001\210\002\170\001\230\000\246\0046\000\000\002\194\000\000\000\000\000\000\001\242\000\000\000\000\000\000\000\000\000\000\004\173\000\000\000\000\000\000\000\000\004:\003\182\001\246\002\146\000\000\000\000\000\000\002\158\000\000\002\178\004\030\004*\000\000\003\186\000\000\000\000\0046\000\000\000\000\016\186\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\024\194\000\000\000\000\017\030\000\000\004:\000\000\000\000\0176\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017>\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\017R\017~\000\000\000\000\000\000\000\000\000\000\017\186\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\022\002")) and lhs = - (8, "\012\011\n\t\b\007\006\005\004\003\002\001\000\216\216\215\215\214\213\213\212\212\212\212\212\212\212\212\212\212\212\212\212\212\212\212\212\212\212\212\211\211\210\209\209\209\209\209\209\209\209\208\208\208\208\208\208\208\208\207\207\207\206\206\205\204\204\204\203\203\202\202\202\202\202\202\201\201\201\201\201\201\201\201\200\200\200\200\200\200\200\200\199\199\199\199\198\197\196\196\196\196\195\195\195\195\194\194\194\193\193\193\193\192\191\191\191\190\190\189\189\188\188\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\186\186\185\185\184\183\182\181\181\180\180\179\179\179\179\178\178\178\178\177\177\176\176\176\176\175\174\173\173\172\172\171\171\170\169\169\168\167\167\166\165\164\164\164\163\163\162\161\161\161\161\161\160\160\160\160\160\160\160\160\159\159\159\159\159\159\158\158\157\157\157\156\156\155\155\155\154\154\153\153\152\152\151\151\150\150\149\149\148\148\147\147\146\146\145\145\144\144\144\143\143\143\143\142\142\141\141\140\140\139\139\139\139\139\138\138\138\138\137\137\137\136\136\136\136\136\136\136\135\135\135\135\135\135\135\134\134\133\133\132\132\132\132\132\132\131\131\130\130\129\129\128\128\127\127\127~}}}||{{{{{{{{{zzyyxxxxxxxxxxxwvuutttttsrrqqppppppppppppppoonnmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmllkkjjiihhggffeeddccbbaaaaaaaaaaa`_^]\\[ZYXWWWWWWWWWWVVVUUUTTTTSSSSSSSSSRRQQQQQPPOONMLLKKKKKJJIIHHHGGGGGGFFFEEDDCCBBAA@@@??>>==<<;;::9988776655544433322211110/..................-----,,,,,,,+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++**))))))))))))))))))))))(((((((((((((((((((((((((((((((((((((((((((((((((((''&&&%%$$$$$$$$$$$$$$$$##\"\"!!!!!!! \031\031\030\030\030\030\030\029\029\028\027\026\026\026\025\025\024\024\024\024\024\024\024\024\024\024\023\023\022\022\022\022\021\021\020\019\019\019\019\019\018\017\017\016\016\016\015\015\015\014\014\014\014\r\r") + (8, "\012\011\n\t\b\007\006\005\004\003\002\001\000\221\221\220\220\219\218\218\217\217\217\217\217\217\217\217\217\217\217\217\217\217\217\217\217\217\217\217\216\216\215\214\214\214\214\214\214\214\214\213\213\213\213\213\213\213\213\212\212\212\211\211\210\209\209\209\208\208\207\207\207\207\207\207\206\206\206\206\206\206\206\206\205\205\205\205\205\205\205\205\204\204\204\204\203\202\201\201\201\201\200\200\200\200\199\199\199\198\198\198\198\197\196\196\196\195\195\194\194\193\193\192\192\191\190\189\189\188\188\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\187\186\186\185\185\184\183\182\181\181\180\180\179\179\179\179\178\178\178\178\177\177\176\176\176\176\175\174\173\173\172\172\171\171\170\169\169\168\167\167\166\165\164\164\164\163\163\162\161\161\161\161\161\160\160\160\160\160\160\160\160\159\159\159\159\159\159\158\158\157\157\157\156\156\155\155\155\154\154\153\153\152\152\151\151\150\150\149\149\148\148\147\147\146\146\145\145\144\144\144\143\143\143\143\142\142\141\141\140\140\139\139\139\139\139\138\138\138\138\137\137\137\136\136\136\136\136\136\136\135\135\135\135\135\135\135\134\134\133\133\132\132\132\132\132\132\131\131\130\130\129\129\128\128\127\127\127~}}}||{{{{{{{{{zzyyxxxxxxxxxxxwvuutttttsrrqqppppppppppppppoonnmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmllkkjjiihhggffeeddccbbaaaaaaaaaaa`_^]\\[ZYXWWWWWWWWWWWVVVUUUTTTTSSSSSSSSSRRQQQQQPPOONMLLKKKKKJJIIHHHGGGGGGFFFEEDDCCBBAA@@@??>>==<<;;::9988776655544433322211110/...................-----,,,,,,,+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++**))))))))))))))))))))))(((((((((((((((((((((((((((((((((((((((((((((((((((''&&&%%$$$$$$$$$$$$$$$$$##\"\"!!!!!!! \031\031\030\030\030\030\030\029\029\028\027\026\026\026\025\025\024\024\024\024\024\024\024\024\024\024\023\023\022\022\022\022\021\021\020\019\019\019\019\019\018\017\017\016\016\016\015\015\015\014\014\014\014\r\r") and goto = - ((16, "\000%\000\193\000G\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\012\000\000\000\000\000\129\001\152\000\030\0003\000#\000\004\000\190\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000b\000\000\000\000\000\000\000\000\000\000\000t\000\000\000\000\000\000\000\242\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000=2\000\000\000\000\000\000\000\254\000\000\000\000\000\000\000\000\000\000\000\000\000\000'\238\001T\001>\000\223\000\000\001B9\220\001\236\001\218\000:\000\000\000\000\000\000\001x\000\000\000\000\000\182\000\000\000\000\000\000\000\000\003\156\000\000\002\150\000\000\000\000\000\000\000\000\000\000\001\022\000\000\000\218\003\202\bf\000\000\000\000\011\018'\238\000\000\000\000\001\254\000\000\000\027\000\000:~\002\184\000\000\001\156\001r\000\000\000\000\002\172\002\142\002\208\003b\001\226\003\202\004\142\000f\001\194\0022\003\216\002\152\011b\000\000\005(\003\244\003\188\002h\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004r\000\000\t>\005(\011\194\000\000\000\000\004.\005d\004\0301\236\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007\148\000\000\004\168\005l\005@\000\000\000\000\000\000\000\000\000\173\000\000\000\000\005\144\000\167\006\018\006(\007\214\000\000\0050\005H\006*\000Q\004\228\006L \232\000\000\000\000\005X\006\254\011\204\000\000!\b\001\244!\026\"V\000\000\003B\000\000\000\000\000\000\000\000\006\018=F\006\020\000\000\001\012\0064\000\000\004P6\150\000\131\000\000\001\172\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0002:\005\190\000\000\000\000\000\000\000\192\000\000\tD\000\000\000\000\002\164\000o\000\000\000\000\003\248\000\000\006n\000\000\002\164\t\148\002\164\000\000\000\000\000\000\000\000\000\0007 \000\000\007\"\006@\000\000=\168\007N\030`\000\000\000\000\000\000\0062\000\000\000\000\000\000\000\000\006F\000\000\000\000\000\000\000\000\000\0002L\000\000\000\000\000\000\000\000\000\000\000\000\001\158\007N\000\000\000\000\000\000\006F\007\1342\146\006\224\007p\015\214\000\000\003\014\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000(\000\000\000\000\000\000\000\000\b\0122\160\000\000\000\000\007\030\b\0042\214\000\000\000\000\000\00038\007\0143\152\000\000\007\014\000\0003\164\007\014\000\0003\228\007\014\000\000\007\014\000\000\000\000\007\014\000\000\000\0004J\000\000\007\0144\138\000\000\007\014\002|\000\000\000\000\"V\000\000\000\000\000\000\000\000\007\014\"z\000\000\000\000\000\000\007\014\000\000\006F\007\246\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\016\000\000\007\136\000\000=\132\006F\000\000\000\000\000\000\000\000\b\b\b\184\012$\b\026\b\030\b@\b\028\005\014\b`\0001\t\006\000\000\000\000\000\029\005\136\b\160\001\172\b\200\bL\000\000\000\145\004\138\005\180\007\136\n\"\000\000\000\000C\158\000\000C\224\t\212\000\000=\198\006F>@\006F\000\000\003\"\000\000\003x\000\000\000\000\003\220\000\000\000\000\000\000\nt\000\000\n\030\000\145\000\000\000\000\t>\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\145\000\000\000\000\000\145\000\000\b\200\007\014\000\000\002\182\004\228\000\000\002\182\000\000\000\000\n\206\000\145\000\000\000\000\000\000\000\000\000\000\000\000\002\182\012\132\rL\n4\t\218\"\152\000n\000\000\t\130\b\182\r\158\t\234\b\228\025X1N\000\000\000\000\000\000\000\000\000\000\0032\t\188\000\000\000\000\000\000\t\250\b\244\007V\002\182\011\240\000\000\000\145\000\000\000\000\000\000\001\244\000\000>T\006F\r\166\n\018\t\030\r\254\n \t0\014\180\"\186\007\014\015\024\n\"\t89\190\n\244\000\000#\002\007\014>x\006F\n\238\000\000\000\000\000\000\000\000\007\148\011&\011L\000\000\000\000\b\176\015 \n\208\t>4\172\007\014\015t\n\222\tF6(\000\000>\172\000\000\000\000\015|\"\244\018\\\000\000\000\000\000\000\000\000>\208\000\000\000\000\000\000\007\172\016B\000\000\000\000\000\000\000\000#^>\222\000\000\000\000\000\000\000\000\000\000\n\170\016\150\000\000\n\180$\"\n\180$,\n\180\000\000?\026\000\000$\128\n\180\016\234\004\152\016\244\000\000\000\000$\136\n\180%\022\n\180%\030\n\180%\250\n\180&\002\n\180&\026\n\180&\152\n\180&\246\n\180&\254\n\180'\140\n\180'\148\n\180'\232\n\180(v\n\180(\128\n\180)\014\n\180)^\n\180)h\n\180)\246\n\180*F\n\180*\212\n\180\t\170*\2484\232\007\148\011x\000\000+8;l\000\000\017N\000\000?,\000\000\006F;\166\000\000\006F?P\006F\000\000\017\184\000\000\000\000\000\000+\\\000\000\000\000\000\000\000\000\000\000\007\014\000\000\000\000?\210\000\000\006F\000\000\000\000;\166\011\136\000\000@6\006F\018\018\000\000\000\000\011\"\000\000@H\006F\018\160\000\000\000\000\018\196\000\000\000\000\000\000@Z\006F\019\028\000\000\n\252\019\132\000\0005J\000\000\007\0145\142\000\000\007\0145\176\000\000\007\014\003d\000\000\000\000\000\000\000\000\000\0005\240\007\014\004\222\005\022\000\000\000\000\000\000\n\180\019\222\000\000\000\000\000\000+\150\n\180\000\000\000\000\000\000\000\000\0206\000\000\000\000\000\000\n\180\020D\000\000\020\158\000\000\000\000\000\000\021\004\000\000\000\000\000\000\000\000@\146\000\000\000\000\021^\000\000\000\000\000\000,H\n\180\021l\000\000\000\000\000\000,\138\n\180\021\196\000\000\000\000,\176\n\180\n\180\000\000\007\228\022\030\000\000\000\000-\b\n\180\022l\000\000\000\000-(\n\180-v\n\180\000\000.\004\n\180\000\000\000\000\022\250\000\000\000\000.\152\n\180\023,\000\000\000\000.\200\n\180\023\\\000\000\000\000.\232\n\180\000\000/\000\n\180\000\000;\138\000\000\000\000\n\180\000\000\000\000\023\142\000\000\000\000\023\192\000\000\000\000\011D\000\000\000\000\024\028\000\000\024$\000\000\000\000\000\000\007\148\011\226\000\0007\022\n<\002\164\025\004\000\0007r\000\000\000\000\000\0007\194\000\000\000\000\025$\000\000\025\146\000\000\000\000\000\000\000\000/\n\000\000\000\000\000\000/f\n\1800r\n\180\000\000\n\252\025\156\000\000\000\000\025\236\000\0000T\000\000\000\0001N\000\000\000\000\000\000\026\134\000\000\000\000\000\000\000\000\026\144\000\000\000\000\000\000\000\000\012\152\000\000\000\000\000\000\003\154\000\000\000<\000\000\000;\000\000\0128\000\000\004\144\000\000\000\000\000\000\000\000\000\000\000\000\0032\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\180\000\000\012\164\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\t\184\007\232\002\182\027T\000\000\011\166\t\224\012*\001\144\t\136\002\182\r@\000\145\t\176\002\182\000\000\027x\000\000\004\142\000\000\011\194\t\238\004X\000\000\000\000\000\000\000\000\000\000\011\218\001.\000\146\000\000\000\000\000\000;\222\000\000C\240\000\000\t\246\000\000\n\016\000\000\000\000\000\000\000\000\002\158\000\000\000\000\000\000\011*\002\164\000\000\002\164\001\178\000\000\rv\002\164\002\164\n\024\000\000\027\186\000\000\000\000\n8\012\172\000\0000\180\005$\000\000\000\000\000\000\000\000\000\000\000\000\n\180\000\000\028\180\000\000\n\180\000\000\000\000\014\242\000\000\000\145\000\000\016H\000\000\000\145\000\000\017\012\000\145\000\000\003Z\000\000\n<\n\022\005`\000\000\011\226\011\234\nV\012\024\012\164\017T\000\145\006\012\000\000\nZ\012\134\012\188\005\024\006\184\012\150\n\130\r\014\006\146\b\132\012\228\000\000\000\000\007\188\b\148\000\000\004\168\002\2426N\007\014\028\028\000\000\007X\003\178\012\158\n\154\011^\005\224\000\000\012\168\n\158\006\200\000\000@\172\006F\rZ\r\132\000\000\t:\000\000\012\244\n\166\006>\r2\003V\000\000\000\000\000\000\000\000\n\216\tZ\000\000\n\222\tl\000\000\bb\0164\rF\rP\n\228\006\216\t\172\000\000\n\230\007\138\n\018\000\000\rR\n\238\r\220\000\000\t\028\000\000\n\132\000\000\r\252\000\000\018\024\000\145\r\216\011\002\014\022\000\000\018\202\0056\r\236\000\000\000\000\003j\006\160\011$\000\000\019\228\000\145\011F\000\000\004\022\000\000\r\210\011\016\0212\006\154\000\000\r\222\011>\007\176\r2\r\230\r\240\011L\015F\000\000\014\000\001\200\000\000\000\000\000\000\000\000\000\171\011X\r\226@\190\006F\000\000\002\200\011\142\014\148\000\000\000\000\000\000\000\000\000\000\000\000A\000\006\164\000\000\011\182\014\246\000\000\000\000\000\000\000\000\000\000\000\000\006\174\000\000A\030\006F\011\226\000\000\006F\011\218\000\184\000\000\011\230\011\232\007\024\000\000\001\004\004L\000\000\002\190\000\000A\"\006F\006F\000\000\000\000\007\b\000\000\b\252\000\000\001\186\007\b\007\b\000\000\011\236;\204\006FA\152\006F\012\b\000\000\000\000\000\000\000\000\012\014\000\000\000\000\007N\000\000\007l\014`\011\240\015p\014*\000\000\000\000\001\196\b|\014h\000\000\000\000\011\250\015\128\014@\000\000\000\000\029\018\000\000\012\222\000\000!(6H\006F\000\000,N\018\132\000\000A\252\000\000\000\000\000\000\007\b\000\000\000\000\012:\014|\012\000\015\144\014J\000\000\000\000B\014\012\144\014\140\000\000\000\000\000\000<:\000\000\000\000\000\000\000\000\000\000\000\000\012\146\000\000\014\152\012\020\006\162\000\000\015\134\015>\012\180\014\166\000\000\000\000\014\170\012>\b*\000\000\000\000\tl6\150\005|\000\000\000\000\000\000\bL\014p\012p\000\000\014z\bL\000\000\015V\012\188\014\196\000\000\000\000\000\000\006F\003v\004(\005\180\000\000\000\000\000\000\000\000\014\138\012t\000\000\006\128\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006F\014z\012\128\015\208\014\138\000\0007\224\000\237\012\146\014^\003\156\000\019\012\150\015\016\000\000\015\200\028\130\000\000\000\000\029J\000\000\012\208\000\000\nL\000\000\000\000\000\000\000\000\000\000\000\000B\018\006F\000\000\015\204\029l\000\000\000\000\030\002\000\000\000\245\012\156\015r\000\000\000\0007\250:\020\015(\000\000B0\006F\0302\000\000\000\000\030T\000\000\000\000\r0\000\000\000\\\000\000\000\000\000\000\000\000\000\000\000\000:\204\000\000\000\0008\188:\208\015*\000\000BP\006F\030\234\000\000\000\000\031\028\000\000\000\000\012\184\031<\r<\000\000\012\190\012\198\002\016\002\208\012\200\t&\012\214\015|0\214\r\\\000\000\r\016\r2\tf\000\000\004*<Z\000\000\004.\000\000\rH9\0069Z\005\236\014j\006l\000\000\020\144;\138\000\000\0001\000\000\000\000\0001\000\000\000\000\0001\n\002\000\000\011\000\0001\015\1380\238\rh\000\000\0001\000\000\000\000Br\000\000\000\000\000\000\0001\000\000\000\000\r\166\000\000\r\030\005\190\r\200\000\000\rJ<\174\r\248\000\000\000\000\000\000\000\000\014\000\000\000\000\000\006\018\000\000\0001B\232\000\000\014\216\00019h\000\000\014\b\014\242\rN\016\n\014\200\000\0009r\014\014\015\002\000\000\000\000\000\000\019\012\b\026\000\000\000\000\000\000\000\000\000\000\000\000\n\170\014\020\000\000\015\018\000\000\000\000\000\000\000\000\014\026\027F\000\000\000\000\000\000\000\000\n\170\000\000\000\000\014.\031\170\000\000\000\000\000\000\000\000\000\000\002\182\000\145\000\000\000\000\007\014\000\000Bn\006F\000\000\007\212\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\014\202\rP\011\246\002\182\000\000\022\n\000\000\000\145\000\000\016\004\000\000\000\000\000\000\000\000\000\000 (\000\000\000\000\000\000\000\000\000\000\000\000\015\170\002\022\t\210\014p\003\144\r\148\000\000\000\226\000\000\000\000\000\000\000\000\000\000\000\000\000\000\014\138\005^\r\176\000\000\007$\016\n\015\188\014J\000\000\000\000\015\180\002\202\b\150\000\000\000\000\000\000\r\180\000\000\r\206\000\240\000\000\000\000\002\164\b\128\000\000\000\000\000\000\000\000\000\000.\226\000\000\000\000\007h\007\238\000\000\000\000C(\006F\006F\000\000CJ\006F\bP\000\000\000\000\000\000\006F\000\000\000\000\t\246\015\196\014\\\000\000\000\000\015\184\000\170\001\200\000\000\000\000\000\000\000\000\b\002\016\n\nl\015\200\014h\000\000\000\000\015\190\004\188\003\142\000\000\000\000\000\000\000\000\000\145\000\000\b\222\000\000\000\000\000\000 \004\000\000 \182\000\000\000\000\000\000\000\000\000\000-\226\000\000\000\000\000\000\005\022\000\190\000\000\000\000\000\000\000\000\000\000\002V\000\190\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0050\000\000\000\000\000\000<\198\000\000\006F\000\000\n*\000\000\000\000\000\000\001\030\000\000\000\000\000\000\001\214\000\000\000\000\000\000\0001\000\000\000\000\000\0000\250\007\014\000\000\000\000\000\014\000\000\000\000\000\000\000\000\0032\004\128\015\b\004D\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000=.\000\000\014v\000\000\000\000\000\000\000\000\005H\006\246\r@+\182\000\000\000\000\014\150/~\000\000\000\000\000\000\014\162;\020\000\000\000\000\000\000\000\000"), (16, "\006\021\003\169\002\020\002\021\001e\0007\002\251\001\198\000\196\006\184\005{\000\200\000\201\005\158\001\246\001\031\001\230\002X\006\022\006\195\001\234\006\024\001\023\000q\001e\002Y\005\160\006\249\002\021\001e\006\025\006&\001\198\006\021\0067\002\020\002\021\001e\002g\005\210\0066\001\230\001\016\002\003\001\244\001\234\000\200\001\023\001\023\001\026\002X\006\022\006%\000\147\006\024\006\170\001\215\001\246\002Y\006\026\001\235\005\165\001\016\006\025\006&\001k\006\241\005\212\001\023\001\026\003\170\002g\001\016\004\132\001\236\002\020\002\021\001e\001\023\001\026\003\167\005\241\005\213\004&\006\190\001\235\002\003\005\215\000\203\000\200\000;\006\003\006\026\006\027\006\242\006\251\006\188\002i\003\165\001\236\004\219\006\028\002\004\001\230\001\198\003\174\001\242\001\234\002\024\001\023\002k\000\200\004\220\001\230\001\016\000\147\004\244\001\234\000\152\001\023\001\023\001$\005\169\006\135\001\031\006+\006\027\001 \003\187\002\251\002i\000@\001\027\006\252\006\028\002k\000\200\006\162\001\229\005}\006,\002\024\001(\002k\000\200\002\004\000\203\001\235\001\031\006\031\000\153\001\"\006\197\001\238\006!\006\165\000\196\001\235\006+\000\200\001\002\000?\001\031\000\147\006#\001 \000\156\002l\0012\002r\002\023\001\236\001%\006,\0007\002x\000:\001\132\002n\001\031\006$\003\178\006\031\002k\000\200\001\002\005\217\006!\0013\001\"\003\234\002\251\003\168\000\203\001*\001Q\006\\\006#\002z\006\131\002l\000\203\002r\006\021\000m\002\020\002\021\001e\002x\003\250\001\132\002n\000\147\006$\000\157\001\215\001l\003\168\000\\\001\016\002X\006\022\006%\001\016\006\024\001\023\001\026\000`\002Y\001\023\001$\002z\001*\006\025\006&\006\233\001\016\003\245\003\247\003\249\002l\002g\001\023\001$\0007\001\031\0007\001\016\002m\0018\001\132\002n\000\147\001\023\001$\000\152\006\130\001\016\006f\006\168\006\169\001\016\006\026\001\023\001\026\0007\006{\001\023\001$\006]\006\234\001\169\001e\001T\0011\003\250\001\023\004\219\001\016\005W\004\b\001%\001\196\001\031\001\023\001$\006\137\004\167\006g\004\220\000d\001f\002)\004\227\001h\001i\006\027\006h\000y\006\021\002i\002\020\002\021\001e\006\028\001%\002\251\000\129\001.\000\132\001\"\002\024\001>\002k\000\200\004\219\002X\006\022\006%\001%\006\024\006\213\001W\001F\002Y\003\217\006\237\004\220\006+\006\025\006&\004\221\006\131\003\137\002\246\002\247\001%\002g\006e\001\147\001e\001\019\003\253\006,\001\016\0009\001.\001\023\001\016\001H\001\023\001$\006\031\001\016\001\023\001\026\000\128\006!\006\026\001\023\001\026\006\238\006Z\003\254\000\200\001\127\001)\006#\001\016\000\203\002l\000\203\002r\006\166\001\023\001$\001n\003\220\002x\000\200\001\132\002n\001\016\006$\000\147\000\135\006q\001\215\001\023\001$\000\196\001\238\006\027\000\200\000\201\006\021\002i\002\020\002\021\001e\006\028\002z\001%\006\167\003\140\003\145\004\219\002\024\004\000\002k\000\200\004\219\002X\006\022\006%\000=\006\024\000\174\004\220\001`\002Y\005\210\004\226\004\220\006+\006\025\006&\004\252\006y\004\003\003\181\001e\000\134\002g\000\196\001\129\000\186\000\200\000\201\006,\001%\006i\006j\001\130\002\001\001\132\001l\000\203\006\031\005\212\006k\006l\003\234\006!\006\026\002\244\001e\000\147\006-\000\181\001\215\006m\004\b\006#\005\213\001\016\002l\001.\002r\005\215\006\214\001\023\001$\005\238\002x\000\179\001\132\002n\001\016\006$\000\189\002\020\002\021\001e\001\023\001\026\000\196\000\151\006\027\000\200\000\201\006\021\002i\002\020\002\021\001e\006\028\002z\004\236\003\248\003\247\003\249\000\150\002\024\003\165\002k\000\200\002\251\002X\006\022\006%\003\174\006\024\000\202\000\183\005F\002Y\005\210\001\016\000\172\006+\006\025\006&\004\239\001\023\001$\002\001\001\217\000\178\002g\000\200\006i\006j\002\251\003\175\006,\001\031\000\203\004\241\001+\006k\006l\000\203\000\196\006\031\005\212\000\200\001\002\004\215\006!\006\026\006m\004\b\004c\006)\001\003\000\200\002\002\004\242\006#\005\213\004\147\002l\001\"\002r\005\215\007\005\002\021\001e\005\231\002x\001\219\001\132\002n\004'\006$\002\023\001\023\001\031\001\006\001\031\001 \004c\001 \006\027\000\200\0012\003\178\002i\002k\000\200\001\002\006\028\002z\006\021\001\223\002\020\002\021\001e\002\024\006\180\002k\000\200\005\251\005F\001\"\0013\001\"\007\b\007\t\004\213\002X\007\011\001O\004\149\006\024\006+\005M\005N\002Y\004f\001\222\001\132\003\168\006\025\007\r\000\194\001\023\0007\005\254\006\167\006,\002g\005^\003\173\001\016\0007\005W\004\b\002\002\006\031\001\023\001$\001\224\006\000\006!\002l\004\150\001*\006c\001*\001\132\000\184\006\026\002m\006#\001\132\002n\002l\000\196\002r\000\196\000\200\000\201\000\200\000\201\002x\0018\001\132\002n\006\001\006$\007\006\006\206\002k\000\200\006\179\001\016\000\188\001\016\002\020\002\021\001e\001\023\001$\001\023\001$\006\027\000\203\002z\005\210\002i\000\193\001%\006\021\006\028\002\020\002\021\001e\007\028\004\149\002\251\002\024\006G\002k\000\200\005M\005N\003\221\007\020\000\196\002X\007\021\000\200\001\002\006\024\007\016\000\204\005\212\002Y\001.\000\211\005V\001\246\006\025\007\029\005W\004\b\001>\002\251\001>\006?\002g\005\213\006,\001%\002\251\001%\005\215\004\218\005\205\001F\005\222\006\031\001\246\002\251\003\168\006\207\006!\001\250\003\230\004\b\002\003\006\026\000\147\000\200\001\202\001\215\006#\006\221\003\220\002l\001.\002r\001.\001H\002\251\001H\002\253\002x\002\005\001\132\002n\002\003\006$\002\023\000\200\0049\006\208\000\203\006\168\006\169\000\224\006\215\001\023\002\001\002\024\006\027\002k\000\200\004c\002i\002z\000\200\000\228\006\028\002\252\001d\001e\002~\005W\004\b\002\024\004\014\002k\000\200\006\021\004F\002\020\002\021\001e\002\004\004\138\004c\004\019\007!\000\200\001f\002\192\003\234\001h\001i\006\216\002X\006\022\0063\001\198\006\024\001\239\003\220\002\251\002Y\002\004\004+\006,\001\230\006\025\006&\000\212\001\234\005\245\001\023\000\225\006\031\002g\002l\006\217\003\234\006!\002\001\004(\001\031\002\251\002m\001 \001\132\002n\006\222\006#\001\132\000\234\002l\000\241\002r\006\218\006\026\005?\003\247\003\249\002x\000\249\001\132\002n\000\147\006$\0050\001\215\001\229\001\"\001\235\006o\001Y\001\132\001\031\000\196\001\n\001 \000\200\000\201\004U\001e\001m\002z\001\236\005S\003\247\003\249\004Q\002\002\006\027\000\203\001\r\001n\002i\000\203\000\200\001\030\006\028\001;\006\021\001\"\002\020\002\021\001e\002\024\005\210\002k\000\200\006\002\0044\004\198\001*\000\203\002\251\007\020\000\236\002X\007\021\002\251\000\196\006\024\006+\000\200\001\002\002Y\004\201\002\193\000\242\002\251\006\025\007\024\001\164\006v\005\212\005\254\005\217\006,\002g\000\196\003\234\001\016\000\200\000\201\001*\000\245\006\031\001\023\001$\005\213\006\000\006!\001\129\002\002\005\215\001B\001\006\004>\005\219\006\026\001\157\006#\001\132\001l\002l\004\143\002r\006\144\000\200\002\251\005\210\0007\002x\001\016\001\132\002n\006\001\006$\000\203\001\023\001$\004\155\001d\001e\004`\004\b\004\188\005[\003\247\003\249\000\203\001\246\001-\006\027\004r\002z\004:\002i\005\212\001%\001\023\006\028\001f\001v\001G\001h\001i\000\203\002\024\003\220\002k\000\200\006\021\005\213\002\020\002\021\001e\001\247\005\215\002\251\002\003\007\027\005\216\000\200\001>\004\210\001.\001\246\000\200\002X\006\022\001%\001\016\006\024\000\250\004\203\004\228\002Y\001\023\001$\006,\001V\006\025\006/\006\176\001w\001\229\001x\002\199\006\031\002g\001G\001E\002!\006!\001\159\002\003\001\\\001.\000\200\000\147\001H\005:\001\215\006#\001\156\001\016\002l\004\243\002r\000m\006\026\001\023\001$\001C\002x\001\127\001\132\002n\002\004\006$\000\196\005#\004v\000\200\001\002\004\245\001n\001t\001\023\000\200\001]\001\031\004\239\001\031\001 \000\203\001 \002z\003\b\001\246\004\222\000\200\001\002\001~\006\027\004C\001\031\004\241\002i\005$\005d\005%\006\028\000\203\002\004\001\163\001\203\001\175\001\"\002\024\001\"\002k\000\200\001d\001e\003\204\003@\004\242\002\003\000\200\001\002\000\200\001\016\006@\003\025\000\203\0062\005F\001\023\001\026\005&\004L\001\016\001f\002\192\001\129\001h\001i\001\023\001$\004\222\006,\000\203\001\130\002\251\001\132\001l\003\220\002\251\005\254\006\031\001*\003Q\001*\001u\006!\002\251\002\251\004\159\004\b\001\198\003\234\001\199\005'\006\000\006#\001\186\006\157\002l\001\230\002r\001\180\005(\001\234\005)\001\023\002x\002\004\001\132\002n\001\016\006$\001\016\002\020\002\021\001e\001\023\001$\001\023\001$\006\001\0007\006\143\002\251\001\031\001\016\004\016\005e\002X\002z\001\188\001\023\001$\004\t\006\133\003\202\002Y\001m\006\152\003\247\003\249\004\253\006Q\001\235\001\031\004?\000\203\001 \001n\002g\005+\000\200\001\185\004D\006z\005-\0057\001\236\000\203\005M\005N\001>\001\195\001>\001\031\005a\005C\004\b\001%\002\251\001%\001\"\005f\002\015\005O\005_\002\020\002\021\001e\005W\004\b\005b\003r\001%\006g\002\251\004\224\001\191\005F\000\200\006\187\002X\000\203\006h\002\251\001.\002\018\001.\001H\002Y\001H\003u\000m\004~\002 \003\147\004\222\001\129\002i\001\023\006\131\001\237\002g\001\031\001*\001\157\001 \001\132\001l\002\024\001\208\002k\000\200\001\016\000\203\002/\002\251\001\246\005I\001\023\001$\002\020\002\021\001e\0022\000\203\004\\\001\210\0028\005\200\001\"\002M\000\200\001\016\005\130\002R\002X\001\246\001\031\001\023\001$\002o\004h\003\212\002Y\001G\002\003\005F\000\203\000\200\006\229\004k\001\226\001\016\001\233\000m\000\203\002g\003\195\001\023\001$\002i\001\031\003\216\003\191\001 \002\003\002\251\002l\000\200\002r\001%\002\024\001*\002k\000\200\002x\000\203\001\132\002n\005M\005N\005\192\004s\001>\002\170\000\203\006\159\001\246\001\"\000\203\001%\003\203\000\203\006\231\005O\005_\000\203\001&\002z\005W\004\b\001\016\002\014\002o\002\004\005F\005\224\001\023\001$\000\200\001%\003\209\001\198\004*\001\228\002i\002\003\001.\003\224\000\200\001H\001\230\003\241\002\251\002\004\001\234\002\024\001\023\002k\000\200\002l\001*\002r\004w\005\134\003\243\001\016\0010\002x\004\005\001\132\002n\001\023\001$\001\031\006\173\000\203\001 \005M\005N\006a\004\b\001>\000\203\002\017\004\n\001\031\004)\002o\001%\001\016\002z\002\031\005O\005_\001\235\001\023\001$\005W\004\b\004/\001\"\0046\000\203\002.\002\004\002\020\002\021\001e\001\236\000\203\0021\0027\002C\000\203\002l\001.\002r\005F\001H\004\127\002X\004<\002x\001%\001\132\002n\000\203\002@\002Y\001\198\000\203\001\254\002\251\004O\006V\004T\005M\005N\001\230\004_\001>\002g\001\234\001*\001\023\002z\000\203\001%\000\203\002\251\003o\005O\005_\002\020\002\021\001e\005W\004\b\002\020\002\021\001e\000\203\000\196\000\203\004g\000\200\000\201\004j\002X\002H\004q\004u\001\016\002X\001.\004z\002Y\001H\001\023\001$\001\246\002Y\001\235\000\203\001\016\004\134\006D\004\021\002G\002g\001\023\001$\004\153\005\210\002g\000\203\001\236\000\203\002L\004\144\002i\000\203\002\020\002\021\001e\002Q\004P\002\254\002w\002\003\002\174\002\024\000\200\002k\000\200\004\158\004\148\002X\002\209\005M\005N\005\212\004\163\001>\002\216\002Y\000\203\002\251\004\173\000\203\001%\004\015\000\203\000\203\006\155\006\156\005\213\000\203\002g\005W\004\b\005\215\001%\002o\002\245\005\226\002\251\000\203\002i\002\251\002\020\002\021\001e\002i\000\203\004\179\001\246\001.\003d\002\024\001H\002k\000\200\003l\002\024\002X\002k\000\200\002\004\003\252\002l\002\251\002r\002Y\001\198\004\190\002$\000\203\002x\003\201\001\132\002n\006K\001\230\000\203\002\003\002g\001\234\000\200\001\023\000\203\002o\003\161\004\205\004\202\003\171\002o\002i\003\193\004\223\004\209\002z\004\230\001\031\004\247\003\208\005\b\003\210\002\024\005\001\002k\000\200\005\026\004\235\002\251\002\251\004\240\000\203\002l\003\223\003\014\004\004\005/\002l\004\012\002r\002x\001\235\001\132\002n\001\"\002x\002\251\001\132\002n\0045\002\251\000\203\005\024\004.\002o\001\236\006\021\0059\002\004\002i\002\251\0040\0043\002z\002\020\002\021\001e\004B\002z\000\203\002\024\007\020\002k\000\200\007\021\000\203\000\203\006\024\000\203\002X\000\203\002l\005E\002r\005Y\000\203\006\025\002Y\000\203\002x\005i\001\132\002n\001\031\0048\005 \005,\003\198\000\203\005o\002g\005s\002o\004A\005\143\002\020\002\021\001e\002\251\002\020\002\021\001e\002z\0054\002\251\006\026\001\016\005K\005\183\000\203\002X\005\243\001\023\001$\002X\005\188\005\227\005|\002Y\002l\002\251\002r\002Y\005\193\003\184\004=\002\251\002x\003\136\001\132\002n\002g\004@\004N\000\203\002g\000\203\000\196\004S\006\027\000\200\000\201\000\203\002\020\002\021\001e\001\198\006\028\003\214\002i\002z\000\203\005\223\000\203\004[\001\230\000\203\002\251\002X\001\234\002\024\001\023\002k\000\200\001%\005\159\002Y\007\023\005\210\005\199\000\203\005\185\003\131\000\203\002\251\004Z\004^\000\203\000\203\002g\005\207\005\248\001\016\006\r\006J\000\203\006\030\005\196\001\023\001$\002i\001.\002o\005\230\002i\006\031\005\212\004i\002\251\001\235\006!\002\024\002\251\002k\000\200\002\024\002\251\002k\000\200\002\251\006#\005\213\002\251\001\236\000\203\002\251\005\215\004t\006d\002l\005\244\003\014\004p\004y\005\242\002\251\006$\002x\004\141\001\132\002n\000\203\006p\002o\006~\001d\001e\002o\002i\002\251\001%\005\246\000\203\000\203\004\129\000\203\000\203\006\128\002\251\002\024\002z\002k\000\200\004\140\002\251\001f\001v\004\135\001h\001i\002l\002\251\002r\004\139\002l\005\250\002r\004\002\002x\005\255\001\132\002n\002x\006\011\001\132\002n\006\018\002\251\003\127\006 \000\203\002o\006'\002\251\002\020\002\021\001e\004\152\002\020\002\021\001e\002z\0060\004\157\000\203\002z\000\203\005\000\001w\002X\001x\0024\004\162\002X\004\165\004\169\006u\002Y\002l\000\203\002r\002Y\004\177\003x\004\184\006\161\002x\003i\001\132\002n\002g\006\175\004\195\004\255\002g\004\248\004\249\004\254\007\014\001\127\002\020\002\021\001e\005\002\002\020\002\021\001e\005\003\005\"\002z\001n\005\027\005\028\000\200\007\025\002X\005!\0056\0052\002X\007\030\003\130\0053\002Y\0055\005`\005D\002Y\000\196\003a\005H\000\200\000\201\001\198\005J\004\029\002g\003Y\005L\005X\002g\005h\001\230\005j\005k\005p\001\234\005t\001\023\002i\001d\001e\005x\002i\005\138\005\145\005\149\005\173\005\194\005\210\002\024\005\218\002k\000\200\002\024\005\228\002k\000\200\006\020\001\129\001f\001g\006\014\001h\001i\006\015\006\019\001\130\006\"\001\132\001l\006I\006T\006_\006s\006t\001\235\005\212\006x\006\160\006\164\006\174\002o\006\178\005#\002i\002o\007\000\000\000\002i\001\236\000\000\005\213\002\020\002\021\001e\002\024\005\215\002k\000\200\002\024\006\007\002k\000\200\000\000\000\000\000\000\000\000\002X\002l\000\000\002r\005$\002l\005%\002r\002Y\002x\000\000\001\132\002n\002x\002d\001\132\002n\000\000\000\000\000\000\002o\002g\000\000\000\000\002o\000\000\001m\002\020\002\021\001e\000\000\000\000\002z\000\000\000\000\005&\002z\001n\000\000\000\000\000\200\000\000\002X\000\000\000\000\000\000\000\000\002l\000\000\002r\002Y\002l\000\000\003\014\000\000\002x\002q\001\132\002n\002x\000\000\001\132\002n\002g\000\000\000\000\000\000\000\000\005'\002\020\002\021\001e\000\000\000\000\002\020\002\021\001e\005(\002z\005)\002i\000\000\002z\000\000\002X\000\000\001\198\000\000\004!\002X\000\000\002\024\002Y\002k\000\200\001\230\001\129\002Y\002\128\001\234\000\000\001\023\005c\002\127\001\157\002g\001\132\001l\000\000\000\000\002g\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\020\002\021\001e\002i\002o\000\000\005+\000\000\000\000\000\000\000\000\005-\0057\000\000\002\024\002X\002k\000\200\000\000\000\000\001\235\005a\000\000\002Y\000\000\000\000\000\000\000\000\000\000\002\179\000\000\002l\000\000\002r\001\236\000\000\002g\005b\000\000\002x\000\000\001\132\002n\000\000\000\000\002i\002o\000\000\000\000\000\000\002i\000\000\000\000\002\020\002\021\001e\002\024\000\000\002k\000\200\000\000\002\024\002z\002k\000\200\001\198\000\000\004$\002X\000\000\000\000\000\000\000\000\002l\001\230\002r\002Y\000\000\001\234\000\000\001\023\002x\002\190\001\132\002n\000\000\000\000\000\000\002o\002g\000\000\000\000\000\000\002o\000\000\002i\000\000\000\000\002\020\002\021\001e\001\198\000\000\0042\002z\000\000\002\024\000\000\002k\000\200\001\230\000\000\000\000\002X\001\234\002l\001\023\002r\001\235\000\000\002l\002Y\002r\002x\000\000\001\132\002n\002\213\002x\000\000\001\132\002n\001\236\000\000\002g\002\020\002\021\001e\002o\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002z\000\000\002i\000\000\000\000\002z\000\000\000\000\001\235\000\000\000\000\000\000\003T\002\024\000\000\002k\000\200\001\031\000\000\002l\005\015\002r\001\236\002\020\002\021\001e\000\000\002x\000\000\001\132\002n\000\000\000\000\000\000\000\000\000\000\003U\000\000\002X\000\000\000\000\002\020\002\021\001e\001\"\002o\002Y\002i\000\000\000\000\002z\000\000\002\220\001\198\000\000\004\131\002X\000\000\002\024\002g\002k\000\200\001\230\000\000\002Y\000\000\001\234\000\000\001\023\000\000\002\223\000\000\002l\000\000\002r\006\021\000\000\002g\000\000\000\000\002x\000\000\001\132\002n\002\023\002\020\002\021\001e\000\000\000\000\002o\000\000\000\000\006\022\000\000\002\024\006\024\002k\000\200\000\000\002X\000\000\000\000\002z\000\000\006\025\001\235\000\000\002Y\000\000\000\000\000\000\000\000\000\000\002\229\000\000\001\016\002l\002i\002r\001\236\002g\001\023\001$\000\000\002x\000\000\001\132\002n\002\024\003W\002k\000\200\000\000\006\026\000\000\002i\002\020\002\021\001e\000\000\000\000\001\198\000\000\004\137\000\000\000\000\002\024\002z\002k\000\200\001\230\002X\000\000\002l\001\234\000\000\001\023\000\000\000\000\002Y\002o\002m\000\000\001\132\002n\002\232\000\000\006\027\000\000\000\000\000\000\000\000\002g\001%\000\000\006\028\000\000\000\000\002o\002i\000\000\002\020\002\021\001e\000\000\000\000\000\000\002l\000\000\002r\002\024\000\000\002k\000\200\001\235\002x\002X\001\132\002n\006\029\001.\000\000\000\000\000\000\002Y\002l\000\000\002r\001\236\000\000\003\001\000\000\000\000\002x\006\030\001\132\002n\002g\002z\000\000\000\000\000\000\002o\006\031\000\000\002\020\002\021\001e\006!\000\000\000\000\002i\002\020\002\021\001e\000\000\002z\000\000\006#\000\000\002X\000\000\002\024\000\000\002k\000\200\000\000\002X\002Y\002l\000\000\002r\000\000\000\000\006$\002Y\000\000\002x\003\011\001\132\002n\002g\000\000\000\000\000\000\003\016\000\000\000\000\002g\000\000\002\020\002\021\001e\000\000\002o\000\000\002i\002\020\002\021\001e\002z\000\000\001\198\000\000\004\146\000\000\000\000\002\024\000\000\002k\000\200\001\230\002X\003T\000\000\001\234\000\000\001\023\000\000\000\000\002Y\002l\000\000\002r\000\000\000\000\000\000\000\000\000\000\002x\003\018\001\132\002n\002g\000\000\000\000\000\000\005\214\000\000\002o\002i\000\000\000\000\000\000\000\000\000\000\000\000\002i\002\020\002\021\001e\002\024\002z\002k\000\200\001\235\000\000\000\000\002\024\000\000\002k\000\200\000\000\002X\000\000\000\000\002l\000\000\002r\001\236\000\000\002Y\000\000\000\000\002x\000\000\001\132\002n\000\000\000\000\000\000\003\022\000\000\002o\002g\002\023\000\000\000\000\000\000\000\000\002o\000\000\002i\002\020\002\021\001e\002\024\002z\002k\000\200\002\020\002\021\001e\002\024\000\000\002k\000\200\000\000\002X\000\000\002l\000\000\003\014\000\000\000\000\002X\002Y\002l\002x\003\014\001\132\002n\000\000\002Y\000\000\002x\003\030\001\132\002n\002g\000\000\003W\000\000\003$\000\000\002o\002g\000\000\000\000\000\000\000\000\002z\000\000\002i\002\020\002\021\001e\000\000\002z\000\000\000\000\000\000\000\000\000\000\002\024\002l\002k\000\200\000\000\002X\000\000\000\000\002l\002m\003\014\001\132\002n\002Y\000\000\001\198\002x\004\154\001\132\002n\000\000\000\000\000\000\003*\001\230\000\000\002g\000\000\001\234\000\000\001\023\000\000\002o\000\000\002i\002\020\002\021\001e\000\000\002z\000\000\002i\000\000\000\000\000\000\002\024\000\000\002k\000\200\000\000\002X\000\000\002\024\000\000\002k\000\200\000\000\000\000\002Y\002l\000\000\003\014\000\000\000\000\0032\000\000\000\000\002x\001\235\001\132\002n\002g\000\000\000\000\002\020\002\021\001e\002o\000\000\000\000\000\000\000\000\001\236\000\000\002o\002i\000\000\000\000\000\000\002X\002z\000\000\000\000\000\000\000\000\000\000\002\024\002Y\002k\000\200\000\000\000\000\000\000\0037\002l\000\000\003\014\000\000\000\000\000\000\002g\002l\002x\003\014\001\132\002n\000\000\000\000\000\000\002x\000\000\001\132\002n\001\198\000\000\006O\000\000\000\000\002o\000\000\002i\000\000\001\230\000\000\000\000\002z\001\234\000\000\001\023\000\000\000\000\002\024\002z\002k\000\200\002\020\002\021\001e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002l\000\000\003.\000\000\000\000\002X\000\000\000\000\002x\000\000\001\132\002n\000\000\002Y\002i\002\020\002\021\001e\002o\000\000\000\000\001\235\000\000\003C\000\000\002\024\002g\002k\000\200\000\000\002X\002z\000\000\000\000\000\000\001\236\000\000\000\000\002Y\002\020\002\021\001e\000\000\000\000\000\000\002l\000\000\002r\003H\000\000\000\000\002g\000\000\002x\002X\001\132\002n\002o\000\000\000\000\000\000\000\000\002Y\000\000\002\020\002\021\001e\000\000\000\000\000\000\000\000\000\000\003M\000\000\000\000\002g\002z\000\000\000\000\002X\000\000\000\000\000\000\000\000\002l\002i\002r\002Y\000\000\002\020\002\021\001e\002x\000\000\001\132\002n\002\024\003\\\002k\000\200\002g\000\000\000\000\000\000\002X\000\000\000\000\000\000\000\000\000\000\002i\000\000\002Y\000\000\000\000\002z\000\000\000\000\000\000\000\000\000\000\002\024\003_\002k\000\200\002g\000\000\000\000\002o\000\000\000\000\000\000\000\000\000\000\002i\002\020\002\021\001e\000\000\002\020\002\021\001e\000\000\000\000\000\000\002\024\000\000\002k\000\200\000\000\002X\000\000\000\000\002o\002X\002l\000\000\003\014\002Y\002i\000\000\000\000\002Y\002x\003e\001\132\002n\000\000\003g\000\000\002\024\002g\002k\000\200\000\000\002g\000\000\002o\000\000\000\000\002l\000\000\003\014\000\000\002i\000\000\002z\000\000\002x\000\000\001\132\002n\000\000\000\000\000\000\002\024\000\000\002k\000\200\000\000\000\000\000\000\002o\000\000\002l\000\000\003\014\000\000\000\000\000\000\000\000\002z\002x\000\000\001\132\002n\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002o\000\000\002l\002i\003\014\000\000\000\000\002i\002z\000\000\002x\000\000\001\132\002n\002\024\000\000\002k\000\200\002\024\000\000\002k\000\200\000\000\000\000\002\020\002\021\001e\002l\000\000\003.\000\000\000\000\000\000\002z\000\000\002x\000\000\001\132\002n\002X\002\020\002\021\001e\000\000\000\000\000\000\002o\002Y\000\000\000\000\002o\000\000\000\000\003q\000\000\002X\000\000\000\000\002z\000\000\002g\000\000\000\000\002Y\000\000\000\000\002\020\002\021\001e\003z\000\000\000\000\000\000\002l\000\000\002r\002g\002l\000\000\002r\000\000\002x\000\000\001\132\002n\002x\000\000\001\132\002n\003\182\000\000\000\000\000\000\000\000\000\000\002\020\002\021\001e\000\000\000\000\002\020\002\021\001e\000\000\002z\000\000\000\000\000\000\002z\000\000\002X\000\000\000\000\000\000\000\000\002X\000\000\000\000\002Y\002i\000\000\000\000\000\000\002Y\003}\000\000\000\000\000\000\000\000\003\139\002\024\002g\002k\000\200\000\000\002i\002g\000\000\000\000\000\000\002\020\002\021\001e\000\000\000\000\000\000\002\024\000\000\002k\000\200\000\000\000\000\000\000\000\000\000\000\002X\000\000\000\000\000\000\000\000\000\000\002\023\002o\002Y\000\000\000\000\000\000\000\000\000\000\003\142\000\000\000\000\002\024\000\000\002k\000\200\002g\000\000\002o\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002l\002i\002r\000\000\000\000\000\000\002i\000\000\002x\000\000\001\132\002n\002\024\000\000\002k\000\200\002l\002\024\002r\002k\000\200\000\000\000\000\000\000\002x\000\000\001\132\002n\002\020\002\021\001e\002z\000\000\002\020\002\021\001e\000\000\000\000\000\000\000\000\000\000\000\000\002l\002X\002o\000\000\002i\002z\002X\002o\002m\002Y\001\132\002n\000\000\000\000\002Y\002\024\000\000\002k\000\200\003\152\000\000\000\000\002g\000\000\003\157\000\000\000\000\002g\000\000\002l\000\000\002r\000\000\000\000\002l\000\000\002r\002x\000\000\001\132\002n\000\000\002x\000\000\001\132\002n\000\000\002o\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002z\000\000\000\000\000\000\000\000\002z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002l\000\000\002r\000\000\000\000\000\000\006\021\002i\002x\000\000\001\132\002n\002i\000\000\000\000\002\020\002\021\001e\002\024\000\000\002k\000\200\000\000\002\024\006\022\002k\000\200\006\024\000\000\000\000\002X\002z\000\000\002\020\002\021\001e\006\025\000\000\002Y\000\000\000\000\000\000\000\000\000\000\003\206\000\000\000\000\000\000\002X\000\000\002o\002g\000\000\000\000\000\000\002o\002Y\000\000\000\000\000\000\000\000\000\000\003\219\000\000\000\000\006\026\002\020\002\021\001e\002g\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002l\000\000\003\014\000\000\002X\002l\000\000\003\014\002x\000\000\001\132\002n\002Y\002x\000\000\001\132\002n\000\000\004\007\000\000\000\000\000\000\006\027\000\000\000\000\002g\000\000\000\000\000\000\000\000\006\028\002z\000\000\002i\000\000\000\000\002z\000\000\002\020\002\021\001e\000\000\000\000\000\000\002\024\000\000\002k\000\200\000\000\000\000\000\000\002i\000\000\002X\006(\000\000\000\000\000\000\000\000\000\000\000\000\002Y\002\024\000\000\002k\000\200\000\000\004J\000\000\006\030\000\000\000\000\000\000\000\000\002g\000\000\002o\000\000\006\031\000\000\000\000\000\000\000\000\006!\002i\000\000\000\000\000\000\000\000\002\020\002\021\001e\000\000\006#\002o\002\024\000\000\002k\000\200\000\000\000\000\000\000\000\000\002l\002X\002r\000\000\000\000\000\000\006$\000\000\002x\002Y\001\132\002n\001d\001e\000\000\005w\000\000\000\000\002l\000\000\002r\000\000\002g\000\000\002o\000\000\002x\000\000\001\132\002n\002i\002z\001f\001v\000\000\001h\001i\000\000\000\000\000\000\000\000\002\024\000\000\002k\000\200\000\000\000\000\000\000\000\000\002z\000\000\002l\000\000\002r\000\000\004\023\000\000\000\000\000\000\002x\000\000\001\132\002n\000\000\000\000\000\000\001\031\000\000\000\000\005\012\000\000\000\000\000\000\002o\000\000\001w\000\000\001x\0024\000\000\000\000\002i\002z\000\000\000\000\000\000\002\020\002\021\001e\000\000\000\000\000\000\002\024\001\"\002k\000\200\000\000\000\000\000\000\000\000\002l\002X\002r\002\020\002\021\001e\001\127\000\000\002x\002Y\001\132\002n\000\000\000\000\000\000\005z\000\000\001n\002X\000\000\000\200\000\000\002g\000\000\002o\000\000\002Y\000\000\003\130\000\000\000\000\002z\005\137\000\000\000\000\000\000\005\014\000\000\000\000\002g\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002l\000\000\002r\000\000\000\000\000\000\000\000\000\000\002x\000\000\001\132\002n\000\000\000\000\001\016\000\000\000\000\000\000\000\000\000\000\001\023\005\017\000\000\000\000\000\000\001\129\000\000\002\020\002\021\001e\002i\002z\000\000\001\130\000\000\001\132\001l\000\000\000\000\000\000\000\000\002\024\002X\002k\000\200\000\000\000\000\002i\000\000\000\000\002Y\002\020\002\021\001e\000\000\000\000\005\140\000\000\002\024\000\000\002k\000\200\000\000\002g\000\000\000\000\002X\000\000\002\020\002\021\001e\000\000\005\018\002o\002Y\000\000\000\000\000\000\000\000\000\000\005\153\000\000\001\031\002X\004\220\001 \005\023\002g\005\020\000\000\002o\002Y\000\000\000\000\000\000\000\000\000\000\005\156\000\000\001.\002l\000\000\002r\000\000\002g\000\000\000\000\000\000\002x\001\"\001\132\002n\000\000\000\000\000\000\000\000\000\000\002l\000\000\002r\000\000\000\000\002i\000\000\000\000\002x\000\000\001\132\002n\000\000\000\000\002z\000\000\002\024\000\000\002k\000\200\000\000\000\000\000\000\000\000\000\000\000\000\002\020\002\021\001e\002i\000\000\002z\000\000\000\000\000\000\001*\000\000\000\000\000\000\000\000\002\024\002X\002k\000\200\000\000\000\000\002i\000\000\002o\002Y\000\000\002\020\002\021\001e\000\000\005\177\000\000\002\024\000\000\002k\000\200\000\000\002g\000\000\001\016\000\000\002X\002\020\002\021\001e\001\023\001$\002o\000\000\002Y\002l\000\000\002r\000\000\000\000\005\180\000\000\002X\002x\000\000\001\132\002n\002g\000\000\002o\002Y\000\000\000\000\000\000\000\000\000\000\005\184\000\000\000\000\002l\000\000\002r\000\000\002g\000\000\000\000\002z\002x\000\000\001\132\002n\000\000\000\000\000\000\000\000\001>\002l\000\000\002r\000\000\006\021\002i\001%\000\000\002x\000\000\001\132\002n\000\000\000\000\002z\000\000\002\024\000\000\002k\000\200\000\000\000\000\006\022\000\000\000\000\006\024\000\000\000\000\000\000\000\000\002i\002z\000\000\001.\006\025\000\000\001?\000\000\000\000\000\000\000\000\002\024\000\000\002k\000\200\000\000\002i\000\000\002o\000\000\000\000\002\020\002\021\001e\000\000\000\000\000\000\002\024\000\000\002k\000\200\000\000\000\000\006\026\000\000\000\000\002X\000\000\000\000\000\000\001d\001e\000\000\002o\002Y\002l\000\000\002r\000\000\000\000\006\191\000\000\000\000\002x\000\000\001\132\002n\002g\000\000\002o\001f\001v\000\000\001h\001i\000\000\000\000\006\027\000\000\000\000\002l\000\000\002r\000\000\000\000\006\028\002z\000\000\002x\000\000\001\132\002n\000\000\006Y\000\000\000\000\002l\000\000\002r\000\000\000\000\000\000\000\000\000\000\002x\000\000\001\132\002n\000\000\0061\000\000\002z\000\000\001w\000\000\001x\0024\000\000\000\000\000\000\002\020\002\021\001e\000\000\006\030\000\000\002i\002z\000\000\000\000\000\000\000\000\000\000\006\031\000\000\002X\000\000\002\024\006!\002k\000\200\000\000\000\000\002Y\001\127\002\020\002\021\001e\006#\006\193\000\000\000\000\000\000\000\000\000\000\001n\002g\000\000\000\200\000\000\002X\002\020\002\021\001e\006$\000\000\003\130\000\000\002Y\002o\000\000\001d\001e\000\000\000\000\000\000\002X\000\000\000\000\000\000\000\000\002g\000\000\000\000\002Y\001\031\000\000\000\000\005\012\000\000\000\000\001f\001v\000\000\001h\001i\002l\002g\002r\000\000\000\000\001\166\000\000\000\000\002x\000\000\001\132\002n\000\000\000\000\000\000\000\000\001\"\000\000\001\129\002i\000\000\000\000\000\000\000\000\000\000\000\000\001\130\000\000\001\132\001l\002\024\002z\002k\000\200\000\000\000\000\000\000\000\000\001w\000\000\001x\001\153\000\000\000\000\002i\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\024\000\000\002k\000\200\005\014\002i\000\000\002o\000\000\000\000\000\000\000\000\000\000\000\000\001\127\000\000\002\024\000\000\002k\000\200\000\000\000\000\000\000\000\000\000\000\001n\000\000\000\000\000\200\000\000\000\000\000\000\002o\001\016\002l\000\000\002r\000\000\000\000\001\023\005\017\000\000\002x\000\000\001\132\002n\000\000\000\000\002o\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002l\000\000\004\024\000\000\000\000\000\000\002z\000\000\002x\000\000\001\132\002n\000\000\000\000\000\000\000\000\002l\000\000\004\020\001d\001e\000\000\000\000\000\000\002x\001\129\001\132\002n\000\000\000\000\000\000\002z\005\018\001\130\000\000\001\132\001l\001d\001e\001f\001v\000\000\001h\001i\004\220\000\000\005\022\002z\005\020\001\150\000\000\002\020\002\021\001e\000\000\000\000\000\000\001f\001v\001.\001h\001i\000\000\000\000\000\000\000\000\002X\001\155\000\000\001d\001e\000\000\000\000\000\000\002Y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001w\000\000\001x\001\153\000\000\002g\000\000\001f\001v\000\000\001h\001i\000\000\000\000\000\000\002\020\002\021\001e\001w\000\000\001x\001\153\000\000\001d\001e\000\000\000\000\000\000\000\000\000\000\002X\001\127\000\000\000\000\000\000\000\000\000\000\000\000\002Y\000\000\000\000\000\000\001n\001f\001v\000\200\001h\001i\000\000\001\127\001w\002g\001x\0024\000\000\000\000\000\000\000\000\000\000\000\000\001n\000\000\000\000\000\200\002i\000\000\000\000\000\000\002\020\002\021\001e\000\000\000\000\000\000\000\000\002\024\000\000\002k\000\200\000\000\000\000\001\127\000\000\002X\000\000\000\000\001w\000\000\001x\002<\000\000\002Y\001n\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\001\129\000\000\003~\002g\000\000\000\000\002o\000\000\001\130\002i\001\132\001l\000\000\000\000\000\000\000\000\001\127\000\000\001\129\000\000\002\024\000\000\002k\000\200\000\000\000\000\001\130\001n\001\132\001l\000\200\000\000\000\000\002l\000\000\003\190\000\000\000\000\000\000\000\000\000\000\002x\000\000\001\132\002n\000\000\000\000\000\000\000\000\000\000\001\129\000\000\002o\000\000\000\000\000\000\000\000\002?\001\130\000\000\001\132\001l\002i\000\000\002z\002\020\002\021\001e\000\000\000\000\002\020\002\021\001e\002\024\000\000\002k\000\200\000\000\000\000\002l\002X\003X\000\000\000\000\000\000\002X\001\129\002x\002Y\001\132\002n\000\000\000\000\002Y\001\130\000\000\001\132\001l\000\000\000\000\000\000\002g\000\000\000\000\000\000\002o\002g\000\000\000\000\000\000\002z\000\000\002\020\002\021\001e\000\000\002\020\002\021\001e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002X\000\000\000\000\000\000\002X\002l\000\000\002\255\002Y\000\000\000\000\000\000\002Y\002x\000\000\001\132\002n\000\000\000\000\000\000\000\000\002g\000\000\000\000\000\000\002g\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002i\000\000\000\000\002z\000\000\002i\000\000\000\000\000\000\000\000\000\000\002\024\000\000\002k\000\200\000\000\002\024\000\000\002k\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\020\002\021\001e\000\000\002\020\002\021\001e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002X\002o\000\000\000\000\002X\002i\002o\000\000\002Y\002i\000\000\000\000\002Y\000\000\000\000\000\000\002\024\000\000\002k\000\200\002\024\002g\002k\000\200\000\000\002g\000\000\000\000\002l\000\000\002t\000\000\000\000\002l\000\000\002v\002x\000\000\001\132\002n\000\000\002x\000\000\001\132\002n\000\000\000\000\000\000\002o\000\000\000\000\000\000\002o\000\000\000\000\000\000\000\000\000\000\000\000\002z\000\000\000\000\000\000\000\000\002z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002l\000\000\002{\000\000\002l\002i\002\130\000\000\002x\002i\001\132\002n\002x\000\000\001\132\002n\002\024\000\000\002k\000\200\002\024\000\000\002k\000\200\002\020\002\021\001e\000\000\002\020\002\021\001e\002z\000\000\000\000\000\000\002z\000\000\000\000\000\000\002X\002\020\002\021\001e\002X\000\000\000\000\000\000\002Y\002o\000\000\000\000\002Y\002o\000\000\000\000\002X\000\000\000\000\000\000\000\000\002g\000\000\000\000\002Y\002g\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002l\002g\002\132\000\000\002l\000\000\002\134\000\000\002x\000\000\001\132\002n\002x\000\000\001\132\002n\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\020\002\021\001e\002z\000\000\000\000\000\000\002z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002X\002i\000\000\000\000\000\000\002i\000\000\000\000\002Y\000\000\000\000\000\000\002\024\000\000\002k\000\200\002\024\002i\002k\000\200\000\000\002g\000\000\000\000\000\000\000\000\000\000\000\000\002\024\000\000\002k\000\200\002\020\002\021\001e\000\000\002\020\002\021\001e\000\000\000\000\000\000\000\000\000\000\002o\000\000\000\000\002X\002o\000\000\000\000\002X\000\000\000\000\000\000\002Y\000\000\000\000\000\000\002Y\002o\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002g\000\000\000\000\002l\002g\002\136\000\000\002l\000\000\002\138\000\000\002x\002i\001\132\002n\002x\000\000\001\132\002n\002l\000\000\002\140\000\000\002\024\000\000\002k\000\200\002x\000\000\001\132\002n\000\000\000\000\000\000\002z\000\000\000\000\000\000\002z\002\020\002\021\001e\000\000\002\020\002\021\001e\000\000\000\000\000\000\000\000\002z\000\000\000\000\000\000\002X\002o\000\000\000\000\002X\002i\000\000\000\000\002Y\002i\000\000\000\000\002Y\000\000\000\000\000\000\002\024\000\000\002k\000\200\002\024\002g\002k\000\200\000\000\002g\000\000\000\000\002l\000\000\002\142\002\020\002\021\001e\000\000\000\000\002x\000\000\001\132\002n\000\000\000\000\001\031\000\000\000\000\001 \002X\000\000\002o\000\000\000\000\000\000\002o\000\000\002Y\000\000\000\000\000\000\000\000\002z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002g\000\000\001\"\000\000\006\140\000\000\000\000\000\000\002l\000\000\002\144\000\000\002l\002i\002\146\000\000\002x\002i\001\132\002n\002x\000\000\001\132\002n\002\024\000\000\002k\000\200\002\024\000\000\002k\000\200\000\000\000\000\000\000\002\020\002\021\001e\000\000\002z\002\020\002\021\001e\002z\000\000\001*\000\000\000\000\000\000\000\000\002X\000\000\000\000\000\000\000\000\002X\002o\000\000\002Y\002i\002o\000\000\000\000\002Y\000\000\000\000\000\000\000\000\000\000\000\000\002\024\002g\002k\000\200\001\016\000\000\002g\000\000\000\000\000\000\001\023\001$\000\000\002l\000\000\002\148\000\000\002l\000\000\002\150\000\000\002x\000\000\001\132\002n\002x\000\000\001\132\002n\000\000\000\000\000\000\002o\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\020\002\021\001e\002z\000\000\000\000\000\000\002z\000\000\000\000\000\000\000\000\000\000\000\000\001>\002X\000\000\000\000\002l\002i\002\152\001%\000\000\002Y\002i\006\147\002x\000\000\001\132\002n\002\024\000\000\002k\000\200\000\000\002\024\002g\002k\000\200\000\000\002\020\002\021\001e\000\000\000\000\002\020\002\021\001e\001.\002z\000\000\001H\000\000\000\000\000\000\002X\000\000\000\000\000\000\000\000\002X\000\000\002o\002Y\000\000\000\000\000\000\002o\002Y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002g\000\000\000\000\000\000\000\000\002g\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002l\000\000\002\154\000\000\000\000\002l\002i\002\156\002x\000\000\001\132\002n\000\000\002x\000\000\001\132\002n\002\024\000\000\002k\000\200\000\000\000\000\000\000\000\000\000\000\000\000\002\020\002\021\001e\000\000\002z\000\000\000\000\000\000\000\000\002z\000\000\000\000\000\000\000\000\000\000\002X\000\000\000\000\000\000\002i\000\000\000\000\002o\002Y\002i\000\000\000\000\000\000\000\000\000\000\002\024\000\000\002k\000\200\000\000\002\024\002g\002k\000\200\000\000\002\020\002\021\001e\000\000\000\000\000\000\000\000\000\000\000\000\002l\000\000\002\158\000\000\000\000\000\000\002X\000\000\002x\000\000\001\132\002n\000\000\002o\002Y\000\000\000\000\000\000\002o\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002g\000\000\000\000\000\000\002z\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002l\000\000\002\160\000\000\000\000\002l\002i\002\162\002x\000\000\001\132\002n\000\000\002x\000\000\001\132\002n\002\024\000\000\002k\000\200\000\000\002\020\002\021\001e\000\000\000\000\000\000\000\000\000\000\000\000\002z\000\000\000\000\000\000\000\000\002z\002X\000\000\000\000\000\000\002\171\001e\000\000\000\000\002Y\002i\000\000\000\000\002o\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\024\002g\002k\000\200\002\225\001v\000\000\001h\001i\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001d\001e\000\000\002l\000\000\002\164\000\000\000\000\000\000\002\188\000\000\002x\000\000\001\132\002n\000\000\002o\002\191\001d\001e\001f\002\192\000\000\001h\001i\000\000\000\000\002\188\000\000\000\000\002\230\002\246\002\247\000\000\002z\002\191\000\000\000\000\001f\002\192\000\000\001h\001i\002l\002i\002\166\002\020\002\021\001e\000\000\000\000\002x\000\000\001\132\002n\002\024\000\000\002k\000\200\000\000\006\021\002X\001\127\000\000\000\000\000\000\000\000\000\000\000\000\002Y\000\000\000\000\000\000\001n\002z\007\020\000\200\000\000\007\021\000\000\000\000\006\024\002g\000\000\000\000\000\000\000\000\002o\000\000\000\000\006\025\000\000\000\000\000\000\001m\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001n\002\250\000\000\000\200\000\000\000\000\000\000\001m\000\000\002l\000\000\002\168\000\000\000\000\006\026\000\000\000\000\002x\001n\001\132\002n\000\200\000\000\000\000\000\000\000\000\000\000\001\129\000\000\000\000\002\020\002\021\001e\000\000\002\193\001\130\002i\001\132\001l\000\000\002z\001\031\000\000\000\000\005\012\002X\000\000\002\024\006\027\002k\000\200\000\000\002\193\002Y\002\195\000\000\006\028\000\000\000\000\001\129\000\000\000\000\000\000\002\020\002\021\001e\002g\001\157\001\"\001\132\001l\000\000\002\194\000\000\000\000\000\000\007\022\001\129\002X\002o\000\000\000\000\002\020\002\021\001e\001\157\002Y\001\132\001l\000\000\000\000\000\000\000\000\000\000\000\000\006\030\000\000\002X\000\000\002g\000\000\000\000\000\000\000\000\006\031\002Y\002l\000\000\003\005\006!\000\000\005\014\000\000\000\000\002x\000\000\001\132\002n\002g\006#\000\000\000\000\000\000\000\000\000\000\002i\002\020\002\021\001e\000\000\000\000\000\000\000\000\000\000\000\000\006$\002\024\002z\002k\000\200\001\016\002X\002\020\002\021\001e\000\000\001\023\005\017\000\000\002Y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002X\002i\000\000\000\000\000\000\002g\000\000\000\000\002Y\000\000\000\000\002o\002\024\000\000\002k\000\200\000\000\000\000\000\000\000\000\002i\002g\000\000\000\000\002\020\002\021\001e\000\000\000\000\000\000\000\000\002\024\000\000\002k\000\200\000\000\000\000\000\000\002l\002X\003\"\005\018\000\000\000\000\002o\000\000\002x\002Y\001\132\002n\000\000\000\000\000\000\004\220\000\000\005\021\000\000\005\020\000\000\000\000\002g\000\000\000\000\002o\002i\000\000\000\000\000\000\001.\002z\000\000\002l\000\000\003(\000\000\002\024\005#\002k\000\200\002x\002i\001\132\002n\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002l\002\024\003-\002k\000\200\002\020\002\021\001e\002x\000\000\001\132\002n\002z\000\000\005$\006\199\005%\002o\000\000\000\000\002X\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002Y\002i\000\000\002z\000\000\002o\000\000\000\000\000\000\000\000\000\000\000\000\002\024\002g\002k\000\200\002l\005&\0035\000\000\000\000\000\000\000\000\000\000\002x\000\000\001\132\002n\000\000\000\000\000\000\000\000\002l\000\000\003:\000\000\000\000\000\000\000\000\000\000\002x\000\000\001\132\002n\002o\000\000\000\000\002z\000\000\000\000\005'\002\020\002\021\001e\000\000\000\000\000\000\000\000\000\000\005(\000\000\005)\000\000\002z\000\000\000\000\002X\000\000\000\000\000\000\000\000\002l\002i\003<\002Y\002\020\002\021\001e\000\000\002x\000\000\001\132\002n\002\024\005e\002k\000\200\002g\000\000\000\000\002X\002\020\002\021\001e\000\000\000\000\001\031\000\000\002Y\001 \000\000\000\000\002z\002\020\002\021\001e\002X\005+\006\201\001d\001e\002g\005-\0057\002Y\002o\000\000\000\000\002X\000\000\000\000\000\000\005a\001\"\000\000\000\000\002Y\002g\000\000\001f\001v\000\000\001h\001i\000\000\000\000\000\000\000\000\005b\002g\000\000\000\000\002l\000\000\003?\000\000\002i\000\000\000\000\000\000\002x\000\000\001\132\002n\002\020\002\021\001e\002\024\000\000\002k\000\200\000\000\000\000\000\000\006\021\000\000\001*\000\000\000\000\002X\002i\000\000\001w\002z\001x\0024\000\000\002Y\000\000\007\020\000\000\002\024\007\021\002k\000\200\006\024\002i\000\000\000\000\002o\002g\000\000\000\000\000\000\006\025\001\016\000\000\002\024\002i\002k\000\200\001\023\001$\001\127\000\000\000\000\000\000\000\000\000\000\002\024\000\000\002k\000\200\002o\001n\000\000\002l\000\200\003F\000\000\000\000\000\000\000\000\006\026\002x\003\129\001\132\002n\000\000\002o\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002l\002o\003K\000\000\000\000\000\000\006\139\002z\002x\002i\001\132\002n\000\000\001%\000\000\000\000\002l\006\027\003P\000\000\002\024\000\000\002k\000\200\002x\006\028\001\132\002n\002l\000\000\003S\002z\000\000\001\129\002\171\001e\002x\000\000\001\132\002n\001.\001\130\000\000\001\132\001l\007\026\000\000\002z\002\020\002\021\001e\000\000\002o\000\000\002\225\001v\000\000\001h\001i\002z\000\000\000\000\000\000\002X\006\030\000\000\000\000\000\000\000\000\000\000\000\000\002Y\000\000\006\031\000\000\000\000\000\000\000\000\006!\002l\000\000\003\133\002\171\001e\002g\000\000\000\000\002x\006#\001\132\002n\000\000\000\000\000\000\000\000\000\000\002\230\002\246\002\247\002\171\001e\000\000\002\225\001v\006$\001h\001i\000\000\000\000\000\000\002z\002\171\001e\000\000\000\000\000\000\000\000\001d\001e\002\225\001v\000\000\001h\001i\000\000\000\000\000\000\000\000\001\127\000\000\000\000\002\225\001v\000\000\001h\001i\000\000\001f\001v\001n\001h\001i\000\200\002i\002\230\002\246\002\247\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\024\000\000\002k\000\200\002\020\002\021\001e\002\230\002\246\002\247\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\144\002\230\002\246\002\247\001\127\000\000\000\000\000\000\001w\002\022\001x\006\245\000\000\006\247\002o\001n\000\000\000\000\000\200\000\000\000\000\001\127\000\000\000\000\000\000\000\000\001\129\000\000\000\000\000\000\000\000\000\000\001n\001\127\001\130\000\200\001\132\001l\000\000\001\127\000\000\002l\000\000\003\135\001n\000\000\000\000\000\200\004\r\002x\001n\001\132\002n\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005\195\001d\001e\000\000\000\000\000\000\000\000\002z\000\000\001\129\000\000\000\000\005\229\000\000\000\000\000\000\002\023\001\130\000\000\001\132\001l\001f\001v\000\000\001h\001i\001\129\002\024\000\000\002k\000\200\000\000\000\000\000\000\001\130\000\000\001\132\001l\001\129\000\000\000\000\000\000\000\000\000\000\001\129\000\000\001\130\001\031\001\132\001l\001 \000\000\001\130\0012\001\132\001l\001\031\000\000\000\000\001 \000\000\000\000\0012\000\000\001w\000\000\001x\006:\000\000\000\000\000\000\000\000\000\000\0013\001\"\000\000\000\000\000\000\000\000\000\000\0014\000\000\0013\001\"\001d\001e\002l\000\000\000\000\001M\000\000\001d\001e\000\000\002m\001\127\001\132\002n\000\000\000\000\000\000\000\000\000\000\000\000\001f\001v\001n\001h\001i\000\200\000\000\001f\001v\000\000\001h\001i\000\000\001*\001d\001e\000\000\000\000\000\000\000\000\000\000\000\000\001*\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0018\000\000\000\000\000\000\001f\001v\000\000\001h\001i\0018\000\000\000\000\001\016\001w\000\000\001x\001\158\000\000\001\023\001$\001w\001\016\001x\001\136\000\000\000\000\000\000\001\023\001$\000\000\000\000\001\129\000\000\001d\001e\000\000\000\000\000\000\000\000\001\130\000\000\001\132\001l\000\000\001\127\000\000\000\000\001w\000\000\001x\001\133\001\127\000\000\001f\001v\001n\001h\001i\000\200\000\000\000\000\000\000\001n\001>\000\000\000\200\000\000\000\000\000\000\000\000\001%\000\000\001>\000\000\001F\000\000\000\000\000\000\001\127\001%\000\000\001d\001e\001F\000\000\000\000\000\000\001d\001e\001n\000\000\000\000\000\200\000\000\000\000\000\000\001w\001.\001x\001z\001H\001f\001v\000\000\001h\001i\001.\001f\001v\001H\001h\001i\000\000\000\000\001\129\000\000\000\000\000\000\000\000\001d\001e\001\129\001\130\000\000\001\132\001l\000\000\001\127\000\000\001\130\000\000\001\132\001l\000\000\000\000\000\000\000\000\000\000\001n\001f\001v\000\200\001h\001i\001w\000\000\001x\001}\001\129\000\000\001w\000\000\001x\001\128\000\000\000\000\001\130\000\000\001\132\001l\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001d\001e\000\000\000\000\000\000\001\127\000\000\000\000\000\000\000\000\000\000\001\127\001w\000\000\001x\001\131\001n\000\000\000\000\000\200\001f\001v\001n\001h\001i\000\200\000\000\001\129\000\000\000\000\000\000\000\000\001d\001e\000\000\001\130\000\000\001\132\001l\000\000\000\000\000\000\000\000\001\127\000\000\000\000\000\000\000\000\000\000\001d\001e\000\000\001f\001v\001n\001h\001i\000\200\000\000\000\000\000\000\000\000\000\000\001w\000\000\001x\001\141\000\000\000\000\001f\001v\000\000\001h\001i\000\000\001\129\000\000\000\000\000\000\001d\001e\001\129\000\000\001\130\000\000\001\132\001l\000\000\002\221\001\130\000\000\001\132\001l\000\000\001\127\001w\002\224\001x\001\144\001f\002\192\000\000\001h\001i\000\000\001n\000\000\000\000\000\200\000\000\000\000\000\000\001w\001\129\001x\002N\000\000\000\000\000\000\000\000\000\000\001\130\000\000\001\132\001l\000\000\001\127\000\000\001d\001e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001n\000\000\000\000\000\200\000\000\000\000\001\127\000\000\000\000\000\000\000\000\001f\001v\000\000\001h\001i\000\000\001n\000\000\000\000\000\200\000\000\000\000\000\000\000\000\001d\001e\001\129\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\130\001m\001\132\001l\000\000\000\000\000\000\001d\001e\000\000\001f\001v\001n\001h\001i\000\200\000\000\000\000\000\000\001w\000\000\001x\002\235\000\000\001\129\000\000\000\000\001f\001v\000\000\001h\001i\001\130\000\000\001\132\001l\000\000\000\000\000\000\001d\001e\001\129\000\000\000\000\000\000\000\000\002\193\000\000\000\000\001\130\001\127\001\132\001l\001w\000\000\001x\002\238\000\000\000\000\001f\001v\001n\001h\001i\000\200\000\000\002\020\002\021\001e\000\000\001w\001\129\001x\002\241\000\000\000\000\000\000\000\000\000\000\001\157\000\000\001\132\001l\000\000\001\127\000\000\001d\001e\000\000\002S\001\031\000\000\000\000\001 \000\000\001n\001I\000\000\000\200\000\000\000\000\001\127\001w\000\000\001x\002\249\001f\001v\000\000\001h\001i\000\000\001n\000\000\000\000\000\200\001K\001\"\000\000\000\000\001\129\000\000\004\213\000\000\000\000\000\000\000\000\000\000\001\130\001\031\001\132\001l\001 \001\127\000\000\001I\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001n\000\000\000\000\000\200\000\000\001w\000\000\001x\004H\000\000\001\129\001K\001\"\000\000\000\000\000\000\001*\002\023\001\130\000\000\001\132\001l\000\000\000\000\000\000\000\000\000\000\001\129\002\024\000\000\002k\000\200\000\000\0018\000\000\001\130\001\127\001\132\001l\000\000\000\000\000\000\001d\001e\000\000\001\016\000\000\001n\000\000\000\000\000\200\001\023\001$\000\000\001\031\001*\000\000\001 \000\000\001\129\0012\000\000\001f\002\192\000\000\001h\001i\001\130\000\000\001\132\001l\000\000\0018\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0017\001\"\000\000\000\000\001\016\000\000\000\000\002l\001d\001e\001\023\001$\000\000\000\000\000\000\002m\001>\001\132\002n\000\000\000\000\000\000\000\000\001%\000\000\000\000\001\129\005\011\001f\002\192\000\000\001h\001i\000\000\001\130\000\000\001\132\001l\000\000\000\000\000\000\000\000\000\000\000\000\001*\000\000\000\000\000\000\001d\001e\001.\000\000\000\000\001H\000\000\001>\001m\000\000\000\000\000\000\000\000\0018\001%\001d\001e\000\000\001F\001n\001f\002\192\000\200\001h\001i\001\016\000\000\000\000\001d\001e\000\000\001\023\001$\000\000\000\000\001f\002\192\000\000\001h\001i\000\000\001.\000\000\000\000\001H\005\157\000\000\000\000\001f\002\192\000\000\001h\001i\003r\001m\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001n\000\000\000\000\000\200\000\000\000\000\000\000\003t\000\000\000\000\000\000\001>\000\000\001\129\000\000\000\000\000\000\000\000\001%\000\000\000\000\001\157\001F\001\132\001l\000\000\000\000\000\000\000\000\001m\000\000\000\000\000\000\000\000\003r\000\000\000\000\000\000\000\000\000\000\001n\000\000\000\000\000\200\001m\001.\000\000\000\000\001H\000\000\000\000\000\000\000\000\003s\000\000\001n\000\000\001m\000\200\001\129\001d\001e\000\000\000\000\000\000\000\000\000\000\001\157\001n\001\132\001l\000\200\000\000\000\000\003r\000\000\000\000\005\181\000\000\000\000\001f\002\192\000\000\001h\001i\000\000\000\000\000\000\000\000\006\b\000\000\000\000\000\000\003w\000\000\000\000\000\000\001d\001e\001\129\000\000\000\000\002\193\000\000\000\000\000\000\000\000\001\157\000\000\001\132\001l\000\000\000\000\000\000\001\129\000\000\000\000\001f\002\192\000\000\001h\001i\001\157\000\000\001\132\001l\000\000\001\129\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\157\006\n\001\132\001l\001d\001e\000\000\000\000\000\000\000\000\000\000\001d\001e\000\000\000\000\000\000\001d\001e\000\000\001m\000\000\000\000\000\000\000\000\001f\002\192\000\000\001h\001i\000\000\001n\001f\002\192\000\200\001h\001i\001f\002\192\000\000\001h\001i\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001d\001e\001m\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\193\000\000\005#\001n\000\000\000\000\000\200\000\000\000\000\000\000\001f\002\192\000\000\001h\001i\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\129\000\000\000\000\000\000\000\000\005$\006\181\005%\001\157\001m\001\132\001l\005\208\000\000\000\000\001\031\001m\000\000\001 \000\000\001n\001m\000\000\000\200\000\000\000\000\000\000\001n\000\000\000\000\000\200\000\000\001n\000\000\000\000\000\200\005&\001\129\000\000\000\000\000\000\000\000\001\"\000\000\000\000\001\157\000\000\001\132\001l\000\000\000\000\000\000\004\198\000\000\005\208\000\000\000\000\000\000\005\221\001m\000\000\006\b\000\000\000\000\000\000\000\000\006\b\005\154\001\031\005'\001n\001 \000\000\000\200\000\000\000\000\000\000\000\000\005(\001\129\005)\000\000\000\000\000\000\000\000\001*\001\129\001\157\000\000\001\132\001l\001\129\000\000\000\000\001\157\001\"\001\132\001l\000\000\001\157\005\220\001\132\001l\005e\003v\003\237\000\000\001\031\006\t\001\031\001 \000\000\001 \006\017\001\016\000\000\000\000\000\000\000\000\006}\001\023\001$\000\000\000\000\000\000\000\000\005+\000\000\000\000\001\129\000\000\005-\0057\006\021\001\"\000\000\001\"\001\157\001*\001\132\001l\005a\000\000\000\000\004\198\000\000\004\198\000\000\007\020\000\000\000\000\007\021\000\000\000\000\006\024\000\000\000\000\005b\000\000\005\168\000\000\005\178\000\000\006\025\000\000\001>\000\000\001\016\000\000\000\000\000\000\000\000\001%\001\023\001$\000\000\004\203\001*\000\000\001*\001d\001e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\026\000\000\002\020\002\021\001e\000\000\000\000\001.\001f\002\177\001H\001h\001i\000\000\001\016\000\000\001\016\000\000\000\000\000\000\001\023\001$\001\023\001$\001\031\003T\001>\001 \000\000\000\000\000\000\000\000\000\000\001%\006\027\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\028\001\031\000\000\000\000\001 \000\000\000\000\000\000\000\000\001\"\001\031\000\000\000\000\001 \000\000\000\000\000\000\000\000\001.\002\214\007\031\003\244\000\000\001>\000\000\001>\000\000\000\000\001\"\000\000\001%\000\000\001%\000\000\004\203\000\000\004\203\001\"\000\000\006\030\001m\000\000\000\000\000\000\000\000\000\000\005#\003\237\006\031\000\000\000\000\001n\001*\006!\000\200\002\023\000\000\001.\000\000\001.\001H\003\240\001H\006#\000\000\000\000\002\024\000\000\002k\000\200\000\000\001*\001\031\000\000\005$\001 \005%\000\000\000\000\006$\001*\001\016\000\000\000\000\000\000\000\000\000\000\001\023\001$\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\"\001\016\003V\000\000\000\000\005\203\005&\001\023\001$\000\000\001\016\001\129\000\000\000\000\000\000\001\031\001\023\001$\001 \001\157\000\000\001\132\001l\000\000\000\000\000\000\002l\001\031\000\000\000\000\001 \000\000\000\000\001>\002m\000\000\001\132\002n\000\000\005'\001%\000\000\001\"\001*\002\185\000\000\000\000\000\000\005(\000\000\005)\000\000\001>\000\000\001\"\000\000\000\000\000\000\000\000\001%\000\000\001>\000\000\004\231\000\000\000\000\004\234\001.\001%\006\021\001H\000\000\001\016\005*\000\000\000\000\000\000\000\000\001\023\001$\000\000\001\031\000\000\000\000\001 \001*\001.\007\011\000\000\001H\006\024\001\031\000\000\006\225\001 \001.\005+\001*\003\244\006\025\000\000\005-\0057\000\000\000\000\000\000\000\000\000\000\001\"\000\000\000\000\005a\000\000\000\000\001\016\000\000\000\000\000\000\001\"\000\000\001\023\001$\001\031\001>\000\000\001 \001\016\005b\006\026\000\000\001%\000\000\001\023\001$\004\218\000\000\000\000\000\000\000\000\000\000\001\031\000\000\000\000\001 \000\000\000\000\000\000\000\000\000\000\001\"\000\000\001*\000\000\000\000\000\000\001\031\000\000\001.\001 \000\000\001H\001*\006\027\000\000\000\000\001>\000\000\001\"\000\000\000\000\006\028\000\000\001%\000\000\000\000\001<\004\231\001>\000\000\005\249\001\016\000\000\001\"\000\000\001%\000\000\001\023\001$\006\226\000\000\001\016\007\012\001*\000\000\000\000\000\000\001\023\001$\000\000\001.\000\000\000\000\001H\000\000\000\000\000\000\000\000\000\000\000\000\006\030\001*\001.\000\000\000\000\001H\000\000\001\031\000\000\006\031\001 \000\000\001\016\000\000\006!\000\000\001*\001\031\001\023\001$\001 \000\000\001>\000\000\006#\000\000\000\000\000\000\000\000\001%\001\016\000\000\001>\006\186\001\"\001\031\001\023\001$\001 \001%\006$\000\000\000\000\001X\001\"\001\016\000\000\000\000\000\000\000\000\000\000\001\023\001$\002\020\002\021\001e\001.\000\000\000\000\001H\000\000\000\000\001\"\001>\000\000\000\000\001.\000\000\000\000\001H\001%\002\020\002\021\001e\001\174\000\000\002U\001*\002\020\002\021\001e\001>\000\000\000\000\000\000\000\000\000\000\001*\001%\000\000\000\000\000\000\000\000\000\000\002_\000\000\001>\001.\000\000\000\000\001H\002j\000\000\001%\000\000\001*\001\016\001\212\002\020\002\021\001e\000\000\001\023\001$\000\000\001.\001\016\000\000\001D\000\000\000\000\000\000\001\023\001$\000\000\001\031\000\000\000\000\001 \000\000\001.\002y\000\000\001H\001\016\000\000\000\000\000\000\000\000\000\000\001\023\001$\000\000\001\031\000\000\000\000\001 \000\000\002\023\000\000\000\000\000\000\001\"\000\000\000\000\000\000\000\000\001>\000\000\002\024\000\000\002k\000\200\000\000\001%\000\000\002\023\001>\001\214\000\000\001\"\000\000\000\000\002\023\001%\000\000\000\000\002\024\002+\002k\000\200\000\000\000\000\000\000\002\024\001>\002k\000\200\000\000\000\000\000\000\001.\001%\000\000\001H\001*\002>\000\000\000\000\000\000\000\000\001.\000\000\002\023\001H\000\000\000\000\000\000\001\031\000\000\000\000\001 \000\000\001*\002\024\000\000\002k\000\200\002l\001.\000\000\000\000\001H\000\000\001\016\000\000\002m\000\000\001\132\002n\001\023\001$\000\000\000\000\000\000\001\"\002l\000\000\000\000\000\000\000\000\000\000\001\016\002l\002m\000\000\001\132\002n\001\023\001$\000\000\002m\000\000\001\132\002n\000\000\000\000\000\000\001\031\000\000\000\000\001 \000\000\000\000\000\000\000\000\000\000\001\031\000\000\000\000\001 \000\000\000\000\002l\000\000\001>\001\031\000\000\001*\001 \000\000\002m\001%\001\132\002n\001\"\002\182\000\000\000\000\000\000\000\000\000\000\000\000\001>\001\"\000\000\002\020\002\021\001e\000\000\001%\000\000\000\000\001\"\002\187\000\000\000\000\001\016\000\000\001.\000\000\000\000\001H\001\023\001$\000\000\000\000\001\031\000\000\003\027\001 \000\000\000\000\000\000\000\000\000\000\001\031\001.\001*\001 \001H\000\000\000\000\000\000\000\000\000\000\000\000\001*\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\001*\000\000\000\000\000\000\000\000\000\000\000\000\001\"\000\000\000\000\000\000\001\016\001>\001\031\000\000\000\000\001 \001\023\001$\001%\001\016\000\000\000\000\002\204\000\000\000\000\001\023\001$\001\031\001\016\001\031\001 \000\000\001 \000\000\001\023\001$\000\000\000\000\000\000\001\"\001*\000\000\000\000\000\000\002\023\001.\000\000\000\000\001H\001*\000\000\000\000\000\000\000\000\001\"\002\024\001\"\002k\000\200\000\000\000\000\001>\000\000\000\000\000\000\000\000\000\000\000\000\001%\001\016\001>\000\000\002\211\000\000\000\000\001\023\001$\001%\001\016\001>\000\000\002\218\001*\000\000\001\023\001$\001%\000\000\001\031\000\000\002\227\001 \000\000\000\000\000\000\001.\000\000\001*\001H\001*\000\000\000\000\000\000\000\000\001.\000\000\000\000\001H\000\000\000\000\000\000\001\016\000\000\001.\002l\001\"\001H\001\023\001$\000\000\001>\000\000\002m\000\000\001\132\002n\001\016\001%\001\016\001>\000\000\004W\001\023\001$\001\023\001$\001%\000\000\001\031\000\000\004\175\005\012\000\000\000\000\000\000\000\000\000\000\001\031\000\000\001\031\005\012\000\000\001 \000\000\001.\000\000\000\000\001H\001*\000\000\000\000\000\000\001>\001.\001\031\001\"\001H\001 \000\000\001%\000\000\000\000\000\000\004\187\001\"\000\000\001\"\001>\000\000\001>\001\031\000\000\000\000\001 \001%\000\000\001%\001\016\004\200\000\000\004\217\001\"\000\000\001\023\001$\001\031\001.\001\031\001 \001H\005\012\000\000\000\000\000\000\000\000\000\000\000\000\001\"\005\014\000\000\000\000\001.\000\000\001.\001H\000\000\001H\005\014\000\000\001*\000\000\000\000\001\"\000\000\001\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001*\000\000\000\000\001\016\001>\000\000\000\000\000\000\000\000\001\023\005\017\001%\001\016\000\000\001\016\004\233\001*\000\000\001\023\005\017\001\023\001$\001\031\000\000\000\000\005\012\000\000\000\000\000\000\001\016\000\000\001*\000\000\005\014\000\000\001\023\001$\000\000\001.\000\000\000\000\001H\000\000\000\000\000\000\001\016\000\000\000\000\000\000\001\"\000\000\001\023\001$\000\000\001\031\000\000\000\000\001 \000\000\000\000\001\016\005\018\001\016\000\000\000\000\001>\001\023\001$\001\023\005\017\005\018\001\031\001%\004\220\001 \005\019\005\133\005\020\000\000\000\000\001>\001\"\004\220\000\000\005\031\000\000\005\020\001%\001.\000\000\000\000\005\151\005\014\000\000\000\000\000\000\001>\001.\001\"\001.\000\000\000\000\001H\001%\000\000\000\000\000\000\005\175\000\000\000\000\000\000\001>\000\000\001\031\001.\000\000\001 \001H\001%\000\000\005\018\001\016\006=\000\000\001*\000\000\000\000\001\023\005\017\000\000\001.\000\000\004\220\001H\005\235\000\000\005\020\000\000\000\000\000\000\001\"\001*\000\000\000\000\000\000\001.\001\031\001.\001H\001 \000\000\000\000\000\000\001\016\001\031\000\000\000\000\001 \000\000\001\023\001$\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\016\000\000\000\000\001\"\000\000\000\000\001\023\001$\000\000\005\018\000\000\001\"\000\000\001*\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\220\000\000\006\005\000\000\005\020\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001>\000\000\001.\000\000\000\000\000\000\000\000\001%\001\016\000\000\000\000\006\146\001*\000\000\001\023\001$\000\000\001>\000\000\000\000\001*\000\000\000\000\000\000\001%\000\000\000\000\000\000\006\150\000\000\000\000\000\000\000\000\000\000\001.\000\000\000\000\001H\000\000\000\000\000\000\001\016\000\000\000\000\000\000\000\000\000\000\001\023\001$\001\016\000\000\001.\000\000\000\000\001H\001\023\001$\000\000\000\000\001>\000\000\000\000\000\000\000\000\000\000\000\000\001%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001>\001.\000\000\000\000\001\207\000\000\000\000\001%\001>\000\000\000\000\000\000\000\000\000\000\000\000\001%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001.\000\000\000\000\001\209\000\000\000\000\000\000\000\000\001.\000\000\000\000\003\239")) + ((16, "\000%\001E\000A\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0009\000\000\000\000\000\183\000\n\000&\001\021\000(\001\152\000'\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000A\000\000\000\000\000\000\000\000\000\000\001\"\000\000\000\000\000\000\001\170\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\027p\000\000\000\000\000\000\001\176\000\000\000\000\000\000\000\000\000\000\000\000\000\000!\142\001\200\000\220\001H\000\000\002\1306\224\001\216\002\188\000Z\000\000\000\000\000\000\001\234\000\000\000\000\002R\000\000\000\000\000\000\000\000\003j\000\000\002f\000\000\000\000\000\000\000\000\000\000\000\184\000\000\000+\004\026\007\226\000\000\000\000\n\198!\142\000\000\000\000\001&\000\000\rb\000\000#\244\003\012\000\000\000L\001^\000\000\000\000\003J\002\226\004\178\005\182\000\027\004\026\004\228\003\164\000\246\001\168\004V\003\\\n\240\000\0007\134\004\204\003\134\001|\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\200\000\000\b\1647\134\000\014\000\000\000\000\004\212\003\246\004\188+j\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\250\000\000\005d\005<\005\252\000\000\000\000\000\000\000\000\001\134\000\000\000\000\005j\000k\007\018\005\228\007f\000\000\005\132\005\170\007\224\000]\001Z\b\018\030\186\000\000\000\000\005\192\b:\n\250\000\000\031\020\000X\002\020\003\150\000\000\001&\000\000\000\000\000\000\000\000\006p;~\006t\000\000(\012\006\130\000\000.\1443\206\003\024\000\000\001\150\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000/\026\006\014\000\000\000\000\000\000\tZ\000\000\007r\000\000\000\000\001\b\004P\000\000\000\000\002\174\000\000\t\134\000\000\001\b\t\128\001\b\000\000\000\000\000\000\000\000\000\0004D\000\000\bL\006\148\000\000<\024\b\140A\226\000\000\000\000\000\000\006.\000\000\000\000\000\000\000\000\000\244\000\000\000\000\000\000\000\000\000\000/F\000\000\000\000\000\000\000\000\000\000\000\000\001\236\006\174\000\000\000\000\000\000\000\244\007\018/t\006x\b\178\016\n\000\000\002\202\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\160\000\000\000\000\000\000\000\000\007\166/\220\000\000\000\000\006\148\b\1900\0148\1629Z\000\000\000\000\000\000\000\000\000\000\000\000\000\0000@\006`0N\000\000\006`\000\0001\000\006`1\012\006`\006`\000\000\000\000\006`\000\000\000\0001j\000\000\006`1\204\000\000\006`\003R\000\000\000\000\003\150\000\000\000\000\000\000\000\000\006`\005\024\000\000\000\000\006`\000\000\001\222\007`\000\000\000\000\000\000\000\000\000\000\000\000\000\0005\n\000\000\007\000\000\000;\240\000\244\000\000\000\000\000\000\000\000\007\004\007\166\011\018\007\002\007\006\007\030\b\202\002\220\b\218\003\220\007\168\000\000\000\000\003\b\005\168\b\248\003\246\007F\0078\000\000\000W\001J\007\232\005v\b\192\000\000\000\000B.\000\000BT\bT\000\000<:\000\244<b\000\244\000\000\000\007\000\000\003v\000\000\000\000\003\138\000\000\000\000\000\000\b\198\000\000\b\188\000W\000\000\000\000\007\144\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000W\000\000\000\000\000W\000\000\007F\004\030\000\000\000\143\001Z\000\000\000\143\000\000\000\000\012\030\000W\000\000\000\000\000\000\000\000\000\000\000\000\000\143\011\238\012f\b\136\bb\031 ,z\000\000\007\214\t\000\012p\007\226\t\002<\146<\220\000\000\000\000\000\000\000\000\000\000\003l\t\n\000\000\000\000\000\000\007\250\t\004\004\138\000\143\0122\000\000\000W\000\000\000\000\000\000\000X\000\000<\166\000\244\012\150\b\004\t2\012\202\b\028\t:\r2\031|\006`\r\142\b6\t\2307L\t\024\000\000\006\154\006`<\240\000\244\t\016\000\000\000\000\000\000\000\000\006\250\b\254\t\006\000\000\000\000\007\014\r\242\bx\n\b2\002\006`\014<\b\130\n6=\184\000\000>\004\000\000\000\000\014P\031\200\024\220\000\000\000\000\000\000\000\000>\014\000\000\000\000\000\000\006\180\014\180\000\000\000\000\000\000\000\000 \020>\028\000\000\000\000\000\000\000\000\000\000\bB\014\254\000\000\bV ,\bV \140\bV\000\000>P\000\000 \150\bV\0150\001\150\015\172\000\000\000\000 \240\bV!:\bV!\232\bV\"\024\bV\"H\bV\"\176\bV\"\224\bV#\016\bV#\190\bV#\238\bV$\030\bV$\134\bV$\182\bV$\230\bV%\148\bV%\196\bV%\244\bV&\\\bV&\140\bV&\188\bV\nF'\1782j\006\250\t0\000\000'\2329\144\000\000\015\246\000\000=\212\000\000\000\2449\168\000\000\000\244>\024\000\244\000\000\016N\000\000\000\000\000\000(6\000\000\000\000\000\000\000\000\000\000\006`\000\000\000\000>V\000\000\000\244\000\000\000\0009\168\t4\000\000>\186\000\244\016\166\000\000\000\000\b\198\000\000?6\000\244\016\184\000\000\000\000\017\002\000\000\000\000\000\000?x\000\244\017f\000\000\bx\017\164\000\0002\194\000\000\006`2\214\000\000\006`3\\\000\000\006`\0040\000\000\000\000\000\000\000\000\000\0003t\006`\n\228\n\250\000\000\000\000\000\000\bV\018&\000\000\000\000\000\000(*\bV\000\000\000\000\000\000\000\000\018V\000\000\000\000\000\000\bV\018\168\000\000\018\216\000\000\000\000\000\000\019D\000\000\000\000\000\000\000\000?\148\000\000\000\000\019P\000\000\000\000\000\000(\150\bV\020,\000\000\000\000\000\000(\174\bV\0204\000\000\000\000)\\\bV\bV\000\000\006\238\019\204\000\000\000\000)\174\bV\020\148\000\000\000\000)\212\bV*\012\bV\000\000*V\bV\000\000\000\000\020\246\000\000\000\000*\210\bV\021B\000\000\000\000+\006\bV\021\170\000\000\000\000+\174\bV\000\000+\198\bV\000\000\000\023\000\000\000\000\bV\000\000\000\000\022\004\000\000\000\000\022\012\000\000\000\000\b\176\000\000\000\000\022\180\000\000\022\232\000\000\000\000\000\000\006\250\tX\000\0004\206\012\196\001\b\023\000\000\0005B\000\000\000\000\000\0005L\000\000\000\000\023\152\000\000\023\176\000\000\000\000\000\000\000\000+\210\000\000\000\000\000\000,\018\bV,J\bV\000\000\bx\023\242\000\000\000\000\024^\000\000-@\000\000\000\000<\220\000\000\000\000\000\000\025 \000\000\000\000\000\000\000\000\025F\000\000\000\000\000\000\000\000\t\216\000\000\000\000\000\0003\186\000\000\005\188\000\000\001.\000\000\tv\000\000\005\210\000\000\000\000\000\000\000\000\000\000\000\000\003l\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bV\000\000\t\224\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\n\140\005\138\000\143\025P\000\000\b\224\n\144\tb\000\249\005\160\000\143\016T\000W\006|\000\143\000\000\025\162\000\000\002\148\000\000\b\250\n\148\003:\000\000\000\000\000\000\000\000\000\000\t\022\007$\000/\000\000\000\000\000\0009\230\000\000Bf\000\000\n\152\000\000\n\182\000\000\000\000\000\000\000\000\000\196\000\000\000\000\000\000\017\184\001\b\000\000\001\b\b\004\000\000\018\150\001\b\001\b\n\186\000\000\026\016\000\000\000\000\n\198\t\230\000\000-\158\011t\000\000\000\000\000\000\000\000\000\000\000\000\bV\000\000\026\208\000\000\bV\000\000\000\000\0176\000\000\000W\000\000\017\220\000\000\000W\000\000\018x\000W\000\000\000\002\000\000\011\000\n\004\002L\000\000\t\018\t \011\n\tB\t\232\019\030\000W\011\192\000\000\0118\t\204\t\226\004\022\011\222\t\178\011l\t\242\004Z\012\020\t\196\000\000\000\000\004\\\012\030\000\000\005\134\002\2244n\006`\026\218\000\000\0062\003*\t\148\011\160\014\160\005\014\000\000\t\150\011\166\005\252\000\000?\186\000\244\n2\nF\000\000\012H\000\000\t\182\011\192\006J\t\204\000\187\000\000\000\000\000\000\000\000\011\224\012|\000\000\012\026\r\n\000\000\001\204\000\000\000\000\000\000\012\156\t\204\000[\rN\000\000\0000\000\000\019\232\001\b\000\000\020x\001\b\001\b\r^\000\000\007\1669.\t\218\t\224\012\230\004\168\rv\000\000\r\b\005\b\r\150\000\000\t\230\r\026\nn\000\000\005\012\000\000\r\176\000\000\nr\000\000\020\158\000W\nT\rB\n\148\000\000\021z\000*\nh\000\000\000\000\000+\004d\r\234\000\000\021\194\000W\r\236\000\000\003R\000\000\n,\rd\022b\000>\000\000\n2\r\130\007(\t\204\001u\000\000\r\134\t\204\n4\nN\r\140\011\166\000\000\n`\002\136\000\000\000\000\000\000\000\000\000\223\r\148\n.?\196\000\244\000\000\005\192\r\168\n\244\000\000\000\000\000\000\000\000\000\000\000\000?\216\000\244\000\000\r\218\011P\000\000\000\000\000\000\000\000\000\000\000\000\"\244\000\000@6\000\244\014\150\000\000\000\244\014>\003\224\000\000\014J\014X\004\146\000\000\007\1769\234\000\000\005b\000\000@N\000\244\000\244\000\000\000\000\002\248\000\000\005\158\000\000\t\208\002\248\002\248\000\000\014l:\006\000\244@\154\000\244\015\012\000\000\000\000\000\000\000\000\015 \000\000\000\000\007\204\000\000\004v\n\188\014\156\011\220\n\150\000\000\000\000\n\146\007\022\n\218\000\000\000\000\014\162\011\232\n\162\000\000\000\000\r\216\000\000\0040\000\000\023L,\170\000\244\000\000\025V\005^\000\000\031\142\000\000\000\000\000\000\002\248\000\000\000\000\0154\n\238\014\178\012\014\n\210\000\000\000\000(^\015`\011\016\000\000\000\000\000\000:t\000\000\000\000\000\000\000\000\000\000\000\000\015t\000\000\0112\014\240\b\248\000\000\0120\011\228\015\136\011L\000\000\000\000\011R\015*\t\154\000\000\000\000\tD3\206\006\132\000\000\000\000\000\000\007:\011R\015@\000\000\011f\007:\000\000\012@\015\224\011\180\000\000\000\000\000\000\000\244\002\002\003p\007\016\000\000\000\000\000\000\000\000\011z\015V\000\000\b<\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\244\011\134\015\\\012\220\011\152\000\0005\130\001*\015d\011b\000\243\0010\015r\012<\000\000\012\242\026\242\000\000\000\000\027\024\000\000\016\004\000\000\003H\000\000\000\000\000\000\000\000\000\000\000\000@\192\000\244\000\000\012\246\027\154\000\000\000\000\027\188\000\000\002\004\015\140\012\156\000\000\000\0005\190$\202\012`\000\000@\216\000\244\028\134\000\000\000\000\028\152\000\000\000\000\016*\000\000\002\024\000\000\000\000\000\000\000\000\000\000\000\000&p\000\000\000\0005\2007\162\012b\000\000AJ\000\244\028\240\000\000\000\000\029:\000\000\000\000\015\174\029x\016>\000\000\015\204\016.\002h\002\172\016H\006\180\016N\012\190-\168\016\232\000\000\016l\016p\005\230\000\000\004.:\200\000\000\0038\000\000\016\1706\1966\206\n\174\011\162\011\164\000\0008f\000\023\000\000\005\030\000\000\000\000\005\030\000\000\000\000\005\030\006&\000\000\012\016\005\030\012\198.\006\0178\000\000\005\030\000\000\000\000,\162\000\000\000\000\000\000\005\030\000\000\000\000\017<\000\000\016|\0068\017H\000\000\016\216:\230\017v\000\000\000\000\000\000\000\000\017\136\000\000\000\000\002\n\000\000\005\030Ar\000\000\019\170\005\0307\n\000\000\017\144\012D\017<\rV\012*\000\0007\024\017\210\012j\000\000\000\000\000\000;\022\007\002\000\000\000\000\000\000\000\000\000\000\000\000\bB\017\218\000\000\012z\000\000\000\000\000\000\000\000\017\232;`\000\000\000\000\000\000\000\000\bB\000\000\000\000\018\002;\136\000\000\000\000\000\000\000\000\000\000\000\143\000W\000\000\000\000\006`\000\000A\150\000\244\000\000\003\222\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\012:\017\140\015R\000\143\000\000\022\162\000\000\000W\000\000\r\130\000\000\000\000\000\000\000\000\000\000\029\240\000\000\000\000\000\000\000\000\000\000\000\000\r(\003\168\007\142\011R\005N\017\144\000\000\002\148\000\000\000\000\000\000\000\000\000\000\000\000\000\000\011z\006\134\017\146\000\000\005\252\r\156\r^\018\"\000\000\000\000\rT\n\030\007\244\000\000\000\000\000\000\017\162\000\000\017\174\r\220\000\000\000\000\001\b\r\236\000\000\000\000\000\000\000\000\000\000\021\144\000\000\000\000\007T\b\164\000\000\000\000A\188\000\244\000\244\000\000A\210\000\244\b\180\000\000\000\000\000\000\000\244\000\000\000\000\t^\rd\018P\000\000\000\000\r\\\004&\000\029\000\000\000\000\000\000\000\000\bP\r\156\n\020\rz\018^\000\000\000\000\rr\b\128\002\202\000\000\000\000\000\000\000\000\000W\000\000\007&\000\000\000\000\000\000\029\220\000\000\030x\000\000\000\000\000\000\000\000\000\0003<\000\000\000\000\000\000\004\248\000'\000\000\000\000\000\000\000\000\000\000\b*\000'\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\bF\000\000\000\000\000\000;\200\000\000\000\244\000\000\nH\000\000\000\000\000\000\001J\000\000\000\000\000\000\002\206\000\000\000\000\000\000\000\169\000\000\000\000\000\000.f\006`\000\000\000\000\001\178\000\000\000\000\000\000\000\000\003l\004b\012\228\005\180\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000;\210\000\000\018j\000\000\000\000\000\000\000\000\004\172\006.8 8\130\000\000\000\000\018\1748\162\000\000\000\000\000\000\018\1769\022\000\000\000\000\000\000\000\000"), (16, "\006/\003\220\002\023\002\024\001e\004\183\007\011\006\188\0007\002\023\002\024\001e\0007\004\184\004\011\006w\001\016\002[\0060\006\221\006\021\0062\001\023\001\026\000;\002\\\002\004\002\023\002\024\001e\0063\006@\003W\004f\007\012\002\254\000\200\006/\002j\002\023\002\024\001e\002[\001\233\001\249\0007\006\024\001\237\000?\001\023\002\\\001\249\001\031\003\223\002[\0060\006?\006\216\0062\0064\006^\006\026\002\\\002j\002\254\001\172\001e\0063\006@\000\147\006P\006\196\001\218\002\006\004\245\002j\000\200\004)\0007\002\254\002\006\004f\004y\000\200\000\200\001f\002,\001\238\001h\001i\000m\004\246\006\027\0065\003\237\005\014\0064\002l\002\004\002\254\006\214\0066\004\154\004\169\002\026\004i\001\016\001{\002\027\002\254\002n\000\200\001\023\001$\001\016\002\027\000\147\002n\000\200\000\156\001\023\001$\002l\001\220\000\203\006E\000\200\003\140\002\249\002\250\0065\006\192\002\007\002\027\002l\002n\000\200\000\\\0066\002\007\006F\003\248\003\250\003\252\002\005\002\027\004*\002n\000\200\0069\003Y\001\016\006\223\004v\006;\001{\004\171\001\023\001$\001\133\001)\006\193\006E\0007\006=\002r\004\160\002o\000@\002u\001n\005\149\001\232\000\200\002o\001\031\004\177\006F\006\163\001\226\002{\003\172\001{\002q\000:\006>\0069\002p\0009\001{\002q\006;\002o\006/\003\017\002\023\002\024\001e\003\143\003\148\002\254\006=\001\"\002}\002o\002{\002u\001{\002q\001%\002[\0060\006?\004|\0062\003\237\002\005\002{\002\\\001{\002q\000=\006>\0063\006@\000q\001e\001\227\002}\001y\006/\002j\002\023\002\024\001e\000\203\001\232\007\019\002\024\001e\002}\004\127\001\135\0007\001{\001l\001\232\002[\0060\006?\003\173\0062\0064\001k\000\174\002\\\006\149\007\003\000\129\001\016\0063\006@\003\251\003\250\003\252\001\023\001$\004\214\002j\000\147\001\249\000\157\001\218\000\196\001\016\000\196\000\200\001\002\000\200\000\201\001\023\001$\001\201\005\191\006\210\001\003\0065\001d\001e\0064\002l\001\233\007\004\006t\0066\001\237\001\253\001\023\001\023\002\006\005\151\002\027\000\200\002n\000\200\007\021\005\236\001f\001|\001\006\001h\001i\001T\001\201\000`\006Q\000\196\001\169\006E\000\200\000\201\000\147\001\233\0065\000\152\000\203\001\237\002l\001\023\005`\001\019\0066\001%\006F\005\238\001\238\001\023\001G\002\027\000\186\002n\000\200\0069\007\022\005\195\002n\000\200\006;\000\147\001\239\001}\000\152\001~\001\157\005\239\006E\000\153\006=\002\007\005\241\002o\001W\002u\006\029\001.\000\196\001\238\000\203\000\200\001\002\006F\001\031\002\254\002{\001+\001{\002q\001\167\006>\0069\001\239\001\133\000d\004\193\006;\001`\006/\000y\002\023\002\024\001e\002\004\001n\005\184\006=\000\200\002}\002o\001\"\002u\000\202\001\006\006\028\002[\0060\006?\005\186\0062\002\254\001l\002{\002\\\001{\002q\000\128\006>\0063\006@\004p\002\129\004q\004r\000\134\006/\002j\002\023\002\024\001e\006\024\004s\004\011\005g\005h\002}\000\196\002\254\005\156\000\200\000\201\004.\002[\0060\006?\006\026\0062\0064\001\151\001e\002\\\006G\007\007\001y\005x\0063\006@\003\224\005q\004\011\002\254\003\184\001e\002j\000\151\001\249\001\135\005\236\001{\001l\000\196\000\132\001\016\000\200\000\201\000\203\006\027\006\128\001\023\001$\000\150\0065\001d\001e\0064\002l\001\016\007\b\006C\0066\000\200\002\b\001\023\001$\002\006\005\238\002\027\000\200\002n\000\200\000\135\005\236\001f\001|\006\206\001h\001i\006\129\001\201\003\223\001\245\002\005\001\154\006E\005`\005\239\006\130\001\233\0065\000\179\005\241\001\237\002l\001\023\006\b\001\016\0066\004\254\006F\005\238\001%\001\023\001\026\002\027\006\193\002n\000\200\0069\000\203\005\160\000\196\006\127\006;\000\200\000\201\001}\002\254\001~\001\157\005\239\006E\004\172\006=\002\007\005\241\002o\000\183\002u\006\001\002\247\001e\001\238\001.\000\172\001\247\006F\001\031\000\203\002{\005\"\001{\002q\001\222\006>\0069\001\239\001\133\001\199\001\023\006;\000\189\006/\001\225\002\023\002\024\001e\000\203\001n\001\023\006=\000\200\002}\002o\001\"\002u\007\"\007#\004\248\002[\007%\001\027\000\194\0062\006\191\004\171\002{\002\\\001{\002q\000\178\006>\0063\007'\006v\003\233\004\011\005g\005h\006/\002j\002\023\002\024\001e\0076\005\231\001\016\001\249\000\147\002}\006\139\001\218\001\023\001\026\007.\000\204\002[\007/\005p\006Z\0062\0064\005q\004\011\002\\\006\131\006\132\001y\000\203\0063\0077\004<\002\254\001\250\006\133\006\134\002\006\002j\000\212\000\200\001\135\006\232\001{\001l\000\196\006\024\001\016\000\200\000\201\000\203\006\135\004\011\001\023\001$\001\241\0065\001d\001e\0064\002l\006\026\001\249\001\016\0066\004\245\004A\004F\001\241\001\023\001\026\002\027\004\165\002n\000\200\000\200\005\236\001f\001|\000\184\001h\001i\004\246\000\203\003\223\007*\004\253\001\159\002$\006\194\006\195\002\006\006\027\0065\000\200\004\236\002\007\002l\000\200\001\031\005\015\0066\005)\006F\005\238\001%\000\203\004\136\002\027\002\254\002n\000\200\0069\001\023\005q\004\011\006\233\006;\003\223\003\223\001}\007;\001~\001\157\005\239\000\188\001\"\006=\002\004\005\241\002o\0007\002u\005\248\007\031\002\024\001e\001.\001(\000\147\006F\000\181\001\218\002{\006\011\001{\002q\006\234\006>\0069\002\007\001\133\006\241\001\023\006;\004\140\006/\004\148\002\023\002\024\001e\001\023\001n\001\023\006=\000\200\002}\002o\003\170\002u\004\248\004X\001e\002[\0060\006M\004T\0062\006\144\003\176\002{\002\\\001{\002q\000\193\006>\0063\006@\000\211\004f\001\249\006\242\000\200\006/\002j\002\023\002\024\001e\001\016\006Y\001\016\001\249\000\225\002}\001\023\001$\001\023\001\026\007.\000\196\002[\007/\000\200\001\002\0062\0064\003\207\0007\002\\\002\006\006\243\001y\000\200\0063\0072\000\234\001\201\003\215\001\242\004\250\002\006\002j\000\200\000\200\001\135\001\233\001{\001l\006\244\001\237\007 \001\023\002n\000\200\000\196\001\206\002\005\000\200\001\002\0065\001d\001e\0064\002l\005\243\000\196\001%\0066\000\200\001\002\000\224\006}\005\006\001{\002\027\005\226\002n\000\200\000\200\000\203\001f\001|\000\228\001h\001i\004\241\004+\001\016\002\007\001\238\003\171\006E\0007\001\023\001$\006\015\0065\005\t\001.\002\007\002l\003\171\000\203\001\239\0066\000\241\006F\005\250\001d\001e\000\200\002\027\005\011\002n\000\200\0069\000\249\004I\001d\001e\006;\001\249\001Y\001}\0075\001~\002?\001\n\001f\001|\006=\001h\001i\002o\001\r\002u\001\031\005\012\001f\002\195\001\030\001h\001i\006F\001;\003\237\002{\003\219\001{\002q\002\006\006>\0069\000\200\001\133\004f\001B\006;\000\200\006/\006\170\002\023\002\024\001e\001V\001n\003\253\006=\000\200\002}\002o\001}\002u\001~\002\202\001\031\002[\0060\003\011\002\254\0062\000\200\001\002\002{\002\\\001{\002q\002\254\006>\0063\006I\005=\005Y\003\250\003\252\002B\000m\002j\004c\004\011\001\162\001\031\001\133\004O\001 \005\243\002}\003C\001\\\002\007\000\200\001\002\001m\001n\003\028\003\237\000\200\001\160\0064\005>\005~\005?\001t\001n\001y\001\132\000\200\006\137\001\"\001{\000\147\001\031\001\205\001\218\001 \001\016\001\201\001\135\001\202\001{\001l\001\023\001$\003T\001\166\001\233\005\023\000\236\001\031\001\237\005@\001\023\0065\001\178\006\213\001\183\002l\003u\001\"\001\016\0066\006\239\005m\003\250\003\252\001\023\001$\002\027\005\218\002n\000\200\001*\001y\004\019\001\016\005`\003x\004\012\003\253\003\205\001\023\001$\001y\005A\006L\001\135\006\202\001{\001l\001\238\002\254\001\188\005B\001%\005C\001z\001\194\001{\001l\006F\001\016\001*\001\240\001\239\004\000\001\016\001\023\001$\0069\004\181\004\011\001\023\001\026\006;\000\203\006\183\004\248\005\127\005]\004\011\002\023\002\024\001e\006=\001G\004\001\002o\001\211\002u\001\213\001\016\001\229\001%\001\236\005\r\002[\001\023\001$\003\198\002{\005E\001{\002q\002\\\006>\005G\005Q\001\016\006\247\006k\000\242\001>\006\205\001\023\001$\005{\002j\006\148\001%\005\t\006{\004\011\002}\004\245\001&\003\237\000\147\005\128\005J\001\218\003\194\002\023\002\024\001e\005\011\000\245\005|\005g\005h\004f\004\246\001>\000\200\002\017\004\247\001\016\002[\006\129\001%\002\020\001.\001\023\001$\001H\002\\\000\250\006\130\005i\005y\005\012\003\150\002\"\005q\004\011\001E\001%\0021\002j\001\031\000m\006\240\001 \005u\003\250\003\252\002l\004\003\000\203\0024\001\031\001.\001\031\001 \001H\001 \003\237\002\027\001\016\002n\000\200\001\201\002:\001\231\001\023\001\026\001\"\001C\004\006\001\031\001\233\002F\001\031\000\203\001\237\001 \001\023\001\"\000\147\001\"\005T\001\218\006\248\005`\001{\002C\001]\006\194\006\195\002r\002K\000m\001u\000\203\002J\002O\005`\002l\001\189\001\"\002T\003\001\000\203\006\178\003\250\003\252\001\191\002z\002\027\001*\002n\000\200\005q\004\011\001\238\002\177\002o\002\212\002u\002\219\001*\001\198\001*\005c\002\248\002\018\002\021\002#\001\239\002{\003g\001{\002q\006\169\000\203\003o\006\185\003\164\001\016\003\174\002r\003\196\001*\001\031\001\023\001$\001 \003\211\003\213\001\016\0022\001\016\002}\000\203\0025\001\023\001$\001\023\001$\000\203\003\226\002\023\002\024\001e\004\007\000\203\004\015\002o\001\016\002u\001\"\001\016\0048\000\203\001\023\001$\002[\001\023\001$\0041\002{\0043\001{\002q\002\\\005g\005h\005`\000\203\001>\006\255\006\147\000\203\000\203\000\203\0046\001%\002j\005g\005h\0011\004E\001>\002}\001\249\005i\005y\001%\001\016\001%\005q\004\011\004;\001*\001\023\001\026\004D\000\203\005i\005y\004@\000\203\001-\005q\004\011\004C\001%\006\199\001.\001%\004-\001H\001\031\002\006\007\001\001 \000\200\004Q\004V\001.\002;\001.\001\016\004^\001H\002\023\002\024\001e\001\023\001$\002\023\002\024\001e\004]\004a\004l\002l\002P\0010\001\"\002[\001.\002\023\002\024\001e\002[\004\245\002\027\002\\\002n\000\200\004\128\004\138\002\\\006p\004\134\005`\002[\004\143\004\024\002U\002j\004\163\004\246\004\151\002\\\002j\004\252\002\173\005g\005h\004\018\002\007\001>\006\131\006\132\004\162\002\254\002j\002r\001%\004\157\001*\006\133\006\134\001\016\004\161\000\203\002\254\005i\005y\001\023\001\026\004\174\005q\004\011\004\179\005\026\000\196\006\135\004\011\000\200\000\201\003\206\000\203\003\212\002o\003\227\002u\003\244\004\188\001\016\001.\004\191\004\195\001H\004\203\001\023\001$\002{\002l\001{\002q\004\210\003\246\002l\004\b\000\203\004\221\005\236\005\025\002\027\004\r\002n\000\200\000\203\002\027\002l\002n\000\200\005\018\005\019\002}\004\245\003\000\005\024\005\028\005\029\002\027\002\254\002n\000\200\002\023\002\024\001e\002\255\005<\005\238\005g\005h\004\246\004,\001>\002r\005\022\0055\0042\002[\002r\001%\000\203\0056\000\203\005;\000\203\002\\\000\203\005\239\006\181\006\182\002r\003\204\005\241\005q\004\011\005P\005\245\002\254\002j\0049\002o\000\203\002u\000\203\005L\002o\005M\002u\005O\000\203\005z\001.\002\254\002{\001H\001{\002q\002o\002{\002u\001{\002q\002\023\002\024\001e\004?\004\017\002\023\002\024\001e\002{\000\196\001{\002q\000\200\000\201\002}\002[\000\203\002\254\005^\002}\002[\000\203\002\254\002\\\002\023\002\024\001e\005b\002\\\004R\005d\002}\004W\003\201\003\187\002l\002j\005f\005r\002[\005\236\002j\0047\002\254\000\203\004b\002\027\002\\\002n\000\200\002\023\002\024\001e\003\139\005\130\001\031\005\132\004=\005\133\005\138\002j\004j\001\201\000\196\002\001\002[\000\200\000\201\005\238\002\254\000\203\001\233\001\201\002\\\002'\001\237\005\142\001\023\002r\003\134\005\146\001\233\005\164\005\171\004B\001\237\002j\001\023\005\239\004G\004m\005\175\005\199\005\241\005\236\002l\000\203\005\242\005\220\000\203\002l\005\244\005\254\001d\001e\002o\002\027\002u\002n\000\200\004_\002\027\000\203\002n\000\200\001\238\006.\006(\002{\002l\001{\002q\005\238\001f\001|\001\238\001h\001i\000\203\001\239\002\027\006)\002n\000\200\001\031\006-\004k\006<\002r\001\239\002\254\002}\005\239\002r\006c\002l\003\130\005\241\002\023\002\024\001e\005\252\006n\006y\001\016\004t\002\027\000\203\002n\000\200\001\023\001$\002r\002[\006\141\002o\001}\003\017\001~\0027\002o\002\\\002u\006\142\002\254\006\146\006\186\003{\002{\006\190\001{\002q\002\254\002{\002j\001{\002q\006\200\002r\002o\006\204\002u\004\135\001\031\002\254\001\031\005&\001\133\002\023\002\024\001e\002}\002{\001\031\001{\002q\002}\004n\001n\004\139\002\254\000\200\001%\002[\007\026\002o\000\000\002u\004\144\003\133\001\"\002\\\000\203\002\254\000\000\002}\000\000\003l\002{\000\000\001{\002q\000\000\001\016\002j\002\023\002\024\001e\004\156\001\023\001$\004w\006\161\002l\003r\002\023\002\024\001e\000\000\004\129\002[\002}\002\254\002\254\002\027\004\175\002n\000\200\002\\\000\203\002[\004\137\000\000\005(\003d\000\000\000\000\001y\002\\\000\000\004\180\002j\004\185\000\000\000\000\004\189\000\203\004\141\003\\\004\199\001\135\002j\001{\001l\000\000\000\203\002r\000\000\000\000\004\205\004\149\001%\001\016\002l\001\016\002\023\002\024\001e\001\023\005+\001\023\001$\001\016\006\156\002\027\000\203\002n\000\200\001\023\001$\002[\006\159\000\000\002o\004\216\002u\000\000\000\000\002\\\004\166\004\170\000\000\000\203\006\157\002g\000\000\002{\000\000\001{\002q\002l\002j\002\023\002\024\001e\000\000\002r\000\203\002\254\000\203\002l\002\027\000\203\002n\000\200\000\000\000\203\002[\000\000\002}\005,\002\027\001%\002n\000\200\002\\\000\203\002\023\002\024\001e\001%\002t\001\249\002o\004\231\002u\000\000\004\246\002j\0051\004\249\005.\002[\002r\000\000\000\000\002{\004\235\001{\002q\002\\\000\203\001.\002r\006\157\000\000\002\131\005\000\004S\000\000\002l\002\006\006\157\002j\000\200\000\000\000\000\002\254\000\000\002}\002o\002\027\002u\002n\000\200\004\228\000\000\002\254\000\000\000\000\002o\005\017\003\017\002{\005\027\001{\002q\002\254\000\000\002\023\002\024\001e\0054\002{\000\000\001{\002q\002l\000\000\000\000\000\000\000\203\000\000\002r\002[\000\000\002}\000\203\002\027\002\254\002n\000\200\002\\\000\000\000\203\000\000\002}\000\000\002\130\002\254\002\007\001\249\002l\005I\000\203\002j\002\023\002\024\001e\002\254\002o\000\000\002u\002\027\005\005\002n\000\200\001d\001e\000\000\002r\002[\000\000\002{\005\n\001{\002q\006e\000\203\002\\\002\006\000\203\005S\000\200\0052\002\182\000\000\001f\001g\000\203\001h\001i\002j\005_\000\000\002r\002}\002o\000\000\002u\002\023\002\024\001e\002\254\005s\000\000\005:\005\131\000\000\000\000\002{\005\137\001{\002q\002l\002[\005F\000\000\005\141\000\000\000\203\002\254\002o\002\\\002u\002\027\005N\002n\000\200\002\193\000\000\005\169\000\000\002}\000\000\002{\002j\001{\002q\002\007\002\254\000\000\000\000\000\000\002\023\002\024\001e\000\000\005\209\000\203\002\254\002l\000\000\002\023\002\024\001e\000\000\002r\002}\002[\000\203\001m\002\027\006\r\002n\000\200\000\000\002\\\002[\000\000\005e\000\203\001n\002\216\000\203\000\200\002\\\000\000\000\203\000\000\002j\000\000\002\223\000\000\002o\000\203\002u\000\000\005\150\002j\002\023\002\024\001e\000\000\002r\002l\000\000\002{\000\203\001{\002q\001\201\000\000\003\217\000\000\002[\002\027\005\185\002n\000\200\001\233\000\000\005\214\002\\\001\237\000\203\001\023\005\211\000\000\002\226\002}\002o\000\000\002u\000\000\005\253\002j\000\000\005\219\000\196\000\203\001y\000\200\000\201\002{\002\254\001{\002q\002r\002l\002\023\002\024\001e\005\249\001z\005\225\001{\001l\002l\000\000\002\027\000\000\002n\000\200\001\238\002[\000\000\002}\000\000\002\027\005\236\002n\000\200\002\\\000\000\002o\000\000\002u\001\239\002\232\000\000\002\023\002\024\001e\005\233\002\254\002j\002\254\002{\000\203\001{\002q\002r\002\254\000\000\002l\002[\000\000\005\238\001\031\000\000\002r\000\203\000\000\002\\\000\203\002\027\006\018\002n\000\200\002\235\002}\005\222\000\000\000\000\000\000\002\254\002j\005\239\002o\000\203\002u\000\203\005\241\001\201\002\254\004 \006\014\002o\002\254\002u\000\000\002{\001\233\001{\002q\000\000\001\237\002r\001\023\000\000\002{\000\000\001{\002q\002l\002\023\002\024\001e\000\000\000\000\000\203\006\000\000\000\006\012\002}\002\027\006'\002n\000\200\006\016\002[\002\254\000\000\002}\002o\002\254\002u\000\000\002\\\002\023\002\024\001e\002\254\000\203\003\004\002l\001\238\002{\000\000\001{\002q\002j\006\020\000\000\002[\002\254\002\027\002r\002n\000\200\001\239\006\025\002\\\000\000\000\000\006%\006d\001\016\006~\006\138\002}\002\254\003\014\001\023\001$\002j\001\201\006\152\004$\001\031\002\023\002\024\001e\006\154\002o\001\233\002u\000\000\002r\001\237\000\000\001\023\000\000\000\203\002\254\002[\000\000\002{\006,\001{\002q\002\254\006:\002\\\002\023\002\024\001e\002\254\000\000\006A\002l\000\000\000\000\003\019\000\000\002o\002j\002u\000\000\002[\002}\002\027\006J\002n\000\200\001%\000\000\002\\\002{\001\238\001{\002q\000\000\000\203\002l\000\203\000\203\003\021\006\143\000\000\002j\002\254\002\254\001\239\000\203\002\027\000\000\002n\000\200\000\000\000\203\002}\000\000\002r\001\201\000\000\004'\003\255\002\023\002\024\001e\006\187\000\000\001\233\002\023\002\024\001e\001\237\006\201\001\023\000\000\000\000\000\000\002[\007(\002l\000\000\002r\001\016\002[\002o\002\\\002u\000\000\001\023\001$\002\027\002\\\002n\000\200\000\000\003\025\000\000\002{\002j\001{\002q\003!\000\000\002l\002j\000\000\000\000\000\000\002o\000\000\003\017\001\238\0073\0078\002\027\000\000\002n\000\200\000\000\000\000\002}\002{\002r\001{\002q\001\239\000\000\000\000\000\000\000\000\002\023\002\024\001e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001%\001\201\000\000\0045\002}\002[\002r\000\000\000\000\002o\001\233\003\017\001\031\002\\\001\237\000\000\001\023\002l\000\000\0035\000\000\000\000\002{\002l\001{\002q\002j\000\000\002\027\000\000\002n\000\200\004\005\002o\002\027\003\017\002n\000\200\002\023\002\024\001e\000\000\002\023\002\024\001e\002}\002{\000\000\001{\002q\000\000\000\000\000\000\002[\001\238\000\000\000\000\002[\000\000\000\000\002r\002\\\000\000\000\000\000\000\002\\\002r\000\000\001\239\002}\000\000\003'\000\000\000\000\002j\003-\000\000\000\000\002j\000\196\000\000\000\000\000\200\000\201\001\031\002l\000\000\002o\000\000\003\017\002\023\002\024\001e\002o\000\000\003\017\002\027\000\000\002n\000\200\002{\000\000\001{\002q\000\000\002[\002{\000\000\001{\002q\005\236\001\016\000\000\002\\\000\000\000\000\000\000\001\023\001$\003:\000\000\000\000\000\000\002}\000\000\000\000\002j\000\000\002r\002}\000\000\000\000\000\000\002l\000\000\000\000\000\000\002l\005\238\002\023\002\024\001e\000\000\000\000\002\027\000\000\002n\000\200\002\027\000\000\002n\000\200\000\000\000\000\002[\002o\000\000\002u\005\239\000\000\000\000\000\000\002\\\005\241\000\000\000\000\000\000\006!\002{\001%\001{\002q\003F\000\000\000\000\002j\002r\002\023\002\024\001e\002r\000\000\000\000\001\016\000\000\002l\000\000\000\000\000\000\001\023\001$\002}\002[\001\201\000\000\004\153\002\027\000\000\002n\000\200\002\\\004{\001\233\002o\000\000\003\017\001\237\002o\001\023\0031\003K\000\000\000\000\002j\000\000\000\000\002{\000\000\001{\002q\002{\000\000\001{\002q\001\031\000\000\000\000\001 \002r\002\023\002\024\001e\000\000\000\000\002l\000\000\000\000\000\000\000\000\002}\000\000\001%\000\000\002}\002[\002\027\001\238\002n\000\200\000\000\000\000\001\"\002\\\000\000\000\000\002o\000\000\002u\000\000\000\000\001\239\000\000\003P\000\000\000\000\002j\000\000\000\000\002{\000\000\001{\002q\002l\004~\002\023\002\024\001e\002r\002\023\002\024\001e\000\000\000\000\002\027\000\000\002n\000\200\000\000\000\000\002[\000\000\002}\000\000\002[\001*\000\000\000\000\002\\\000\000\000\000\000\000\002\\\000\000\001\201\002o\004\159\003\017\003_\000\000\000\000\002j\003b\001\233\000\000\002j\002r\001\237\002{\001\023\001{\002q\000\000\000\000\001\016\002l\000\000\000\000\000\000\000\000\001\023\001$\000\000\000\000\000\000\000\000\002\027\000\000\002n\000\200\001\201\002}\004\168\002o\000\000\003\017\000\000\000\000\000\000\001\233\000\000\000\000\000\000\001\237\000\000\001\023\002{\001\238\001{\002q\000\000\000\000\000\000\002\023\002\024\001e\000\000\000\000\002r\000\000\002l\001\239\000\000\000\000\002l\006\165\000\000\000\000\002[\002}\000\000\002\027\001%\002n\000\200\002\027\002\\\002n\000\200\002\023\002\024\001e\003h\001\238\000\000\002o\000\000\003\017\000\000\002j\000\000\002\023\002\024\001e\002[\000\000\000\000\001\239\002{\000\000\001{\002q\002\\\002r\001.\000\000\002[\002r\003j\000\000\001\201\000\000\004\176\000\000\002\\\002j\000\000\000\000\000\000\001\233\003t\002}\000\000\001\237\000\000\001\023\000\000\002j\000\000\000\000\002o\000\000\003\017\000\000\002o\000\000\0031\001\031\000\000\000\000\005&\000\000\001\201\002{\006i\001{\002q\002{\002l\001{\002q\001\233\000\000\000\000\000\000\001\237\000\000\001\023\000\000\002\027\000\000\002n\000\200\001\238\001\"\000\000\002}\002\023\002\024\001e\002}\000\000\000\000\000\000\002l\000\000\000\000\001\239\000\000\002\023\002\024\001e\002[\000\000\000\000\002\027\002l\002n\000\200\000\000\002\\\002r\000\000\000\000\002[\001\238\003}\002\027\000\000\002n\000\200\000\000\002\\\002j\000\000\000\000\000\000\005(\003\128\001\239\000\000\000\000\002\023\002\024\001e\002j\000\000\002r\002o\000\000\002u\000\000\000\000\000\000\000\000\000\000\000\000\002[\000\000\002r\000\000\002{\000\000\001{\002q\002\\\001\016\000\000\000\000\000\000\000\000\003\142\001\023\005+\002o\000\000\002u\000\000\002j\000\000\000\000\000\000\000\000\000\000\002}\000\000\002o\002{\002u\001{\002q\000\000\002l\000\000\000\000\000\000\002\023\002\024\001e\002{\000\000\001{\002q\002\027\002l\002n\000\200\000\000\000\000\000\000\002}\002[\000\000\000\000\000\000\002\027\000\000\002n\000\200\002\\\000\000\000\000\002}\000\000\005,\003\145\000\000\000\000\000\000\000\000\000\000\000\000\002j\000\000\000\000\002r\000\000\002l\000\000\000\000\000\000\004\246\000\000\0050\000\000\005.\000\000\002r\002\027\000\000\002n\000\200\000\000\000\000\000\000\000\000\001.\000\000\000\000\002\023\002\024\001e\002o\000\000\002u\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002o\002{\002u\001{\002q\000\000\002r\000\000\003W\000\000\000\000\000\000\000\000\002{\000\000\001{\002q\002l\000\000\002\023\002\024\001e\000\000\000\000\002}\000\000\000\000\000\000\002\027\000\000\002n\000\200\003X\002o\002[\002u\002}\000\000\002\023\002\024\001e\000\000\002\\\002\023\002\024\001e\002{\000\000\001{\002q\000\000\000\000\003\155\002[\001\031\002j\000\000\005&\002[\000\000\002r\002\\\000\000\000\000\000\000\000\000\002\\\000\000\000\000\002}\000\000\003\160\003\209\000\000\002j\000\000\000\000\000\000\000\000\002j\002\026\001\"\000\000\000\000\002\023\002\024\001e\002o\000\000\002u\000\000\002\027\000\000\002n\000\200\000\000\000\000\000\000\000\000\002[\002{\000\000\001{\002q\000\000\000\000\000\000\002\\\000\000\000\000\000\000\000\000\000\000\003\222\002l\000\000\000\000\000\000\000\000\000\000\002j\000\000\000\000\002}\005(\002\027\003Z\002n\000\200\000\000\000\000\000\000\000\000\002l\000\000\000\000\000\000\000\000\002l\002\023\002\024\001e\000\000\000\000\002\027\000\000\002n\000\200\000\000\002\027\002o\002n\000\200\001\016\002[\000\000\000\000\002r\000\000\001\023\005+\000\000\002\\\002p\000\000\001{\002q\000\000\004\n\000\000\000\000\000\000\000\000\000\000\000\000\002j\002r\000\000\000\000\002l\000\000\002r\000\000\000\000\002o\000\000\003\017\000\000\000\000\000\000\002\027\000\000\002n\000\200\000\000\000\000\000\000\002{\000\000\001{\002q\000\000\000\000\002o\000\000\003\017\000\000\000\000\002o\000\000\002u\005,\000\000\000\000\000\000\000\000\002{\000\000\001{\002q\002}\002{\002r\001{\002q\000\000\000\000\000\000\004\246\000\000\005/\000\000\005.\000\000\002l\000\000\001d\001e\000\000\002}\002\023\002\024\001e\001.\002}\002\027\000\000\002n\000\200\002o\000\000\002u\002\023\002\024\001e\002[\001f\001|\000\000\001h\001i\000\000\002{\002\\\001{\002q\000\000\002[\000\000\004M\000\000\002\023\002\024\001e\000\000\002\\\002j\002r\000\000\004\026\000\000\005\145\000\000\000\000\000\000\002}\002[\000\000\002j\000\000\000\000\000\000\000\000\000\000\002\\\000\000\000\000\000\000\000\000\001}\005\148\001~\0027\000\000\002o\000\000\002u\002j\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002{\000\000\001{\002q\000\000\000\000\001\031\000\000\000\000\001 \000\000\000\000\000\000\001\133\000\000\000\000\000\000\000\000\002l\002\023\002\024\001e\000\000\002}\001n\000\000\000\000\000\200\000\000\002\027\002l\002n\000\200\001\"\002[\003\133\002\023\002\024\001e\000\000\000\000\002\027\002\\\002n\000\200\000\000\000\000\000\000\005\163\002l\000\000\002[\000\000\000\000\000\000\002j\000\000\000\000\000\000\002\\\002\027\002r\002n\000\200\000\000\005\166\000\000\000\000\000\000\000\000\000\000\000\000\002j\002r\000\000\000\000\001*\000\000\000\000\000\000\000\000\000\000\000\000\001y\000\000\000\000\000\000\000\000\002o\000\000\002u\000\000\002r\000\000\000\000\000\000\001\135\000\000\001{\001l\002o\002{\002u\001{\002q\001\016\000\000\000\000\000\000\000\000\000\000\001\023\001$\002{\002l\001{\002q\000\000\000\000\002o\000\000\002u\000\000\000\000\002}\002\027\000\000\002n\000\200\000\000\000\000\002l\002{\000\000\001{\002q\002}\002\023\002\024\001e\000\000\000\000\002\027\000\000\002n\000\200\002\023\002\024\001e\000\000\000\000\000\000\002[\000\000\000\000\002}\001>\002r\000\000\000\000\002\\\002[\000\000\001%\000\000\000\000\005\179\000\000\000\000\002\\\000\000\000\000\006\212\002j\002r\005\182\000\000\000\000\000\000\000\000\000\000\000\000\002j\000\000\002o\000\000\002u\000\000\000\000\000\000\002\023\002\024\001e\000\000\000\000\001.\000\000\002{\001H\001{\002q\002o\000\000\002u\000\000\002[\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\\\002{\000\000\001{\002q\000\000\005\203\002}\000\000\000\000\000\000\000\000\000\000\002j\002\023\002\024\001e\000\000\000\000\002l\000\000\000\000\000\000\000\000\002}\000\000\000\000\000\000\002l\002[\002\027\000\000\002n\000\200\000\000\000\000\000\000\002\\\000\000\002\027\000\000\002n\000\200\005\206\000\000\002\023\002\024\001e\000\000\000\000\002j\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002[\000\000\002r\000\000\000\000\000\000\000\000\000\000\002\\\000\000\000\000\002r\002l\000\000\005\210\000\000\000\000\000\000\000\000\000\000\000\000\002j\000\000\002\027\000\000\002n\000\200\000\000\000\000\002o\000\000\002u\000\000\000\000\000\000\002\023\002\024\001e\002o\000\000\002u\000\000\002{\000\000\001{\002q\001d\001e\000\000\002l\002[\002{\000\000\001{\002q\002r\000\000\000\000\002\\\000\000\002\027\000\000\002n\000\200\006\217\002}\001f\001|\000\000\001h\001i\002j\000\000\000\000\002}\000\000\000\000\000\000\000\000\000\000\002l\000\000\002o\000\000\002u\000\000\000\000\000\000\000\000\006s\000\000\002\027\002r\002n\000\200\002{\000\000\001{\002q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001}\000\000\001~\0027\002\023\002\024\001e\000\000\000\000\002}\002o\000\000\002u\000\000\002r\000\000\000\000\000\000\000\000\002[\000\000\002l\000\000\002{\000\000\001{\002q\002\\\000\000\000\000\000\000\001\133\002\027\006\219\002n\000\200\000\000\002\023\002\024\001e\002j\002o\001n\002u\000\000\000\200\002}\000\000\000\000\000\000\000\000\000\000\002[\003\133\002{\000\000\001{\002q\000\000\000\000\002\\\000\000\000\000\000\000\002r\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002j\000\000\000\000\000\000\002}\000\000\000\000\000\000\000\000\002\023\002\024\001e\000\000\000\000\000\000\002\023\002\024\001e\002o\000\000\002u\000\000\000\000\000\000\002[\000\000\002l\000\000\001y\000\000\002[\002{\002\\\001{\002q\000\000\000\000\002\027\002\\\002n\000\200\001\135\000\000\001{\001l\002j\000\000\000\000\000\000\000\000\000\000\002j\000\000\000\000\002}\000\000\000\000\000\000\000\000\002l\000\000\000\000\001d\001e\000\000\000\000\000\000\000\000\000\000\002r\002\027\000\000\002n\000\200\000\000\000\000\000\000\000\000\001\031\000\000\000\000\005&\001f\001|\000\000\001h\001i\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002o\000\000\002u\002\023\002\024\001e\002r\000\000\002l\001\"\000\000\000\000\000\000\002{\002l\001{\002q\000\000\002[\002\027\000\000\002n\000\200\000\000\000\000\002\027\002\\\002n\000\200\001}\000\000\001~\0027\002o\000\000\004\027\002}\000\000\000\000\002j\000\000\002\023\002\024\001e\000\000\000\000\002{\000\000\001{\002q\000\000\002r\005(\002\023\002\024\001e\002[\002r\000\000\000\000\001\133\000\000\000\000\000\000\002\\\000\000\000\000\000\000\002[\002}\000\000\001n\000\000\000\000\000\200\000\000\002\\\002j\002o\000\000\004\023\001\016\003\129\000\000\002o\000\000\003\193\001\023\005+\002j\000\000\002{\000\000\001{\002q\000\000\000\000\002{\002l\001{\002q\002\023\002\024\001e\000\000\000\000\002\023\002\024\001e\002\027\000\000\002n\000\200\000\000\002}\000\000\002[\000\000\000\000\000\000\002}\002[\000\000\000\000\002\\\000\000\000\000\000\000\000\000\002\\\001y\000\000\000\000\000\000\000\000\000\000\002l\002j\000\000\005,\000\000\002r\002j\001\135\000\000\001{\001l\002\027\002l\002n\000\200\002\023\002\024\001e\000\000\000\000\004\246\000\000\005-\002\027\005.\002n\000\200\000\000\000\000\000\000\002[\000\000\002o\000\000\003[\001.\000\000\000\000\002\\\000\000\000\000\000\000\000\000\002r\000\000\002{\000\000\001{\002q\000\000\000\000\002j\002\023\002\024\001e\002r\000\000\000\000\000\000\000\000\002l\000\000\000\000\000\000\000\000\002l\000\000\002[\002}\000\000\002o\002\027\003\002\002n\000\200\002\\\002\027\000\000\002n\000\200\000\000\000\000\002o\002{\002w\001{\002q\000\000\002j\000\000\000\000\000\000\000\000\000\000\000\000\002{\000\000\001{\002q\000\000\000\000\000\000\001\031\002r\000\000\001 \002}\000\000\002r\000\000\002l\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002}\000\000\000\000\002\027\000\000\002n\000\200\000\000\000\000\000\000\000\000\001\"\002o\006\166\002y\000\000\000\000\002o\000\000\002~\000\000\002\023\002\024\001e\000\000\002{\000\000\001{\002q\002l\002{\000\000\001{\002q\000\000\002r\002[\000\000\000\000\000\000\002\027\000\000\002n\000\200\002\\\002\023\002\024\001e\002}\000\000\000\000\000\000\000\000\002}\001*\000\000\000\000\002j\000\000\000\000\002[\000\000\002o\000\000\002\133\000\000\000\000\000\000\002\\\002\023\002\024\001e\002r\000\000\000\000\002{\000\000\001{\002q\000\000\000\000\002j\000\000\001\016\002[\000\000\000\000\000\000\000\000\001\023\001$\000\000\002\\\000\000\000\000\000\000\000\000\000\000\002}\002o\000\000\002\135\000\000\000\000\000\000\002j\000\000\000\000\000\000\000\000\000\000\000\000\002{\000\000\001{\002q\002l\000\000\000\000\000\000\000\000\002\023\002\024\001e\000\000\000\000\000\000\002\027\000\000\002n\000\200\000\000\000\000\000\000\001>\002}\002[\000\000\000\000\000\000\002l\001%\000\000\000\000\002\\\002\023\002\024\001e\000\000\000\000\006\173\002\027\000\000\002n\000\200\000\000\000\000\002j\000\000\002r\002[\000\000\000\000\001\031\002l\000\000\001 \000\000\002\\\002\023\002\024\001e\000\000\001.\000\000\002\027\001H\002n\000\200\000\000\000\000\002j\000\000\002r\002[\000\000\002o\000\000\002\137\000\000\001\"\000\000\002\\\000\000\000\000\000\000\000\000\000\000\000\000\002{\004\224\001{\002q\000\000\000\000\002j\000\000\002r\000\000\000\000\002o\000\000\002\139\000\000\000\000\004\227\002l\000\000\000\000\000\000\000\000\000\000\002}\002{\000\000\001{\002q\002\027\000\000\002n\000\200\000\000\000\000\001*\002o\000\000\002\141\000\000\000\000\000\000\002l\000\000\000\000\000\000\000\000\000\000\002}\002{\000\000\001{\002q\002\027\000\000\002n\000\200\000\000\002\023\002\024\001e\002r\000\000\000\000\001\016\000\000\002l\000\000\000\000\000\000\001\023\001$\002}\002[\000\000\000\000\000\000\002\027\000\000\002n\000\200\002\\\002\023\002\024\001e\002r\000\000\000\000\002o\000\000\002\143\000\000\000\000\001\031\002j\000\000\001 \002[\000\000\000\000\000\000\002{\000\000\001{\002q\002\\\002\023\002\024\001e\002r\000\000\000\000\002o\000\000\002\145\001>\000\000\000\000\002j\000\000\001\"\002[\001%\000\000\002}\002{\000\000\001{\002q\002\\\003\240\004\229\000\000\000\000\000\000\000\000\002o\000\000\002\147\000\000\000\000\000\000\002j\000\000\006\151\000\000\000\000\000\000\002}\002{\000\000\001{\002q\002l\001.\000\000\000\000\001H\002\023\002\024\001e\000\000\000\000\001*\002\027\000\000\002n\000\200\000\000\000\000\000\000\000\000\002}\002[\000\000\000\000\000\000\002l\000\000\000\000\000\000\002\\\002\023\002\024\001e\000\000\000\000\000\000\002\027\000\000\002n\000\200\001\016\000\000\002j\000\000\002r\002[\001\023\001$\001\031\002l\000\000\001 \000\000\002\\\002\023\002\024\001e\000\000\000\000\000\000\002\027\000\000\002n\000\200\000\000\000\000\002j\000\000\002r\002[\000\000\002o\000\000\002\149\000\000\001\"\000\000\002\\\000\000\000\000\000\000\000\000\000\000\000\000\002{\004\224\001{\002q\000\000\000\000\002j\001>\002r\000\000\000\000\002o\000\000\002\151\001%\000\000\005\180\002l\000\000\000\000\000\000\000\000\000\000\002}\002{\000\000\001{\002q\002\027\000\000\002n\000\200\000\000\000\000\001*\002o\000\000\002\153\000\000\000\000\000\000\002l\000\000\000\000\000\000\000\000\001.\002}\002{\003\247\001{\002q\002\027\000\000\002n\000\200\000\000\002\023\002\024\001e\002r\000\000\000\000\001\016\000\000\002l\000\000\000\000\000\000\001\023\001$\002}\002[\000\000\000\000\000\000\002\027\000\000\002n\000\200\002\\\002\023\002\024\001e\002r\000\000\000\000\002o\000\000\002\155\000\000\000\000\000\000\002j\000\000\000\000\002[\000\000\000\000\000\000\002{\000\000\001{\002q\002\\\002\023\002\024\001e\002r\000\000\000\000\002o\000\000\002\157\001>\000\000\000\000\002j\000\000\000\000\002[\001%\000\000\002}\002{\000\000\001{\002q\002\\\000\000\004\229\000\000\000\000\000\000\000\000\002o\000\000\002\159\000\000\000\000\000\000\002j\000\000\000\000\000\000\000\000\000\000\002}\002{\000\000\001{\002q\002l\001.\000\000\000\000\001H\002\023\002\024\001e\000\000\000\000\000\000\002\027\000\000\002n\000\200\000\000\000\000\000\000\000\000\002}\002[\000\000\000\000\001\031\002l\000\000\001 \000\000\002\\\002\023\002\024\001e\000\000\000\000\000\000\002\027\000\000\002n\000\200\000\000\000\000\002j\000\000\002r\002[\000\000\000\000\000\000\002l\000\000\001\"\000\000\002\\\002\023\002\024\001e\000\000\000\000\000\000\002\027\004\224\002n\000\200\000\000\000\000\002j\000\000\002r\002[\000\000\002o\000\000\002\161\000\000\000\000\005\194\002\\\000\000\000\000\000\000\000\000\000\000\000\000\002{\000\000\001{\002q\000\000\000\000\002j\000\000\002r\000\000\001*\002o\000\000\002\163\000\000\000\000\000\000\002l\000\000\000\000\000\000\000\000\000\000\002}\002{\000\000\001{\002q\002\027\000\000\002n\000\200\000\000\000\000\000\000\002o\000\000\002\165\000\000\001\016\000\000\002l\000\000\000\000\000\000\001\023\001$\002}\002{\000\000\001{\002q\002\027\000\000\002n\000\200\000\000\000\000\000\000\000\000\002r\000\000\000\000\000\000\000\000\002l\000\000\000\000\000\000\000\000\000\000\002}\000\000\000\000\000\000\000\000\002\027\000\000\002n\000\200\000\000\000\000\000\000\000\000\002r\000\000\000\000\002o\000\000\002\167\001>\000\000\000\000\000\000\002\174\001e\000\000\001%\000\000\000\000\002{\000\000\001{\002q\000\000\000\000\004\229\000\000\002r\000\000\000\000\002o\000\000\002\169\002\228\001|\000\000\001h\001i\000\000\000\000\001d\001e\002}\002{\000\000\001{\002q\000\000\001.\002\191\000\000\001H\000\000\000\000\002o\000\000\002\171\002\194\000\000\000\000\001f\002\195\000\000\001h\001i\001\031\002}\002{\001 \001{\002q\0012\002\023\002\024\001e\002\233\002\249\002\250\000\000\001d\001e\000\000\000\000\000\000\000\000\000\000\000\000\002[\002\191\000\000\002}\0013\001\"\000\000\000\000\002\\\002\194\000\000\001Q\001f\002\195\000\000\001h\001i\000\000\000\000\001\031\001\133\002j\005&\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001n\000\000\000\000\000\200\000\000\000\000\000\000\000\000\002\023\002\024\001e\000\000\000\000\000\000\000\000\001\"\001m\001*\000\000\000\000\002\023\002\024\001e\002[\000\000\000\000\000\000\001n\000\000\000\000\000\200\002\\\000\000\002\253\0018\002[\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\\\002j\000\000\001\016\000\000\000\000\002l\000\000\000\000\001\023\001$\000\000\001m\002j\000\000\005(\001y\002\027\002\196\002n\000\200\000\000\000\000\001n\000\000\000\000\000\200\000\000\000\000\001\135\000\000\001{\001l\000\000\000\000\000\000\000\000\000\000\002\198\000\000\000\000\000\000\000\000\001y\001\016\000\000\000\000\000\000\000\000\002r\001\023\005+\000\000\000\000\001>\000\000\001z\002\196\001{\001l\002l\001%\000\000\000\000\002\023\002\024\001e\000\000\000\000\000\000\001F\002\027\002l\002n\000\200\000\000\002o\002\197\003\b\002[\000\000\000\000\001y\002\027\000\000\002n\000\200\002\\\000\000\002{\000\000\001{\002q\001.\000\000\001z\001H\001{\001l\000\000\002j\000\000\005,\002r\000\000\002\023\002\024\001e\000\000\000\000\000\000\000\000\002}\000\000\000\000\002r\000\000\000\000\000\000\004\246\002[\0059\000\000\005.\002\023\002\024\001e\000\000\002\\\000\000\002o\000\000\003%\000\000\001.\000\000\000\000\000\000\000\000\002[\000\000\002j\002o\002{\003+\001{\002q\002\\\000\000\000\000\000\000\000\000\002\023\002\024\001e\002{\000\000\001{\002q\002l\002j\000\000\000\000\000\000\000\000\000\000\002}\002[\000\000\000\000\002\027\000\000\002n\000\200\000\000\002\\\000\000\000\000\002}\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002j\002\023\002\024\001e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002l\000\000\002r\000\000\002[\000\000\000\000\000\000\000\000\000\000\000\000\002\027\002\\\002n\000\200\000\000\000\000\000\000\000\000\002l\000\000\000\000\000\000\000\000\000\000\002j\000\000\000\000\000\000\002o\002\027\0030\002n\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002{\002r\001{\002q\000\000\002l\000\000\000\000\000\000\002\023\002\024\001e\000\000\000\000\000\000\000\000\002\027\000\000\002n\000\200\002r\000\000\000\000\002}\002[\000\000\000\000\000\000\002o\000\000\0038\000\000\002\\\000\000\000\000\002\023\002\024\001e\000\000\000\000\000\000\002{\002l\001{\002q\002j\000\000\002o\002r\003=\002[\000\000\000\000\002\027\000\000\002n\000\200\000\000\002\\\000\000\002{\000\000\001{\002q\002}\000\000\000\000\000\000\000\000\000\000\000\000\002j\000\000\000\000\000\000\002o\000\000\003?\000\000\000\000\000\000\000\000\000\000\002}\000\000\002r\001d\001e\002{\000\000\001{\002q\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002l\000\000\001f\001|\000\000\001h\001i\002}\002o\000\000\003B\002\027\000\000\002n\000\200\002\023\002\024\001e\000\000\000\000\000\000\002{\000\000\001{\002q\000\000\002l\002\023\002\024\001e\002[\000\000\000\000\000\000\001d\001e\000\000\002\027\002\\\002n\000\200\000\000\002[\002r\002}\001}\000\000\001~\006T\000\000\002\\\002j\000\000\000\000\001f\001|\000\000\001h\001i\000\000\000\000\000\000\000\000\002j\000\000\002\023\002\024\001e\000\000\002r\002o\000\000\003I\000\000\000\000\000\000\001\133\000\000\000\000\000\000\002[\000\000\000\000\002{\000\000\001{\002q\001n\002\\\000\000\000\200\000\000\000\000\002\023\002\024\001e\002o\001}\003N\001~\0027\002j\000\000\000\000\000\000\000\000\002}\000\000\002[\002{\002l\001{\002q\000\000\000\000\000\000\002\\\002\023\002\024\001e\000\000\002\027\002l\002n\000\200\000\000\000\000\000\000\001\133\002j\000\000\000\000\002}\002\027\000\000\002n\000\200\000\000\000\000\001n\003\168\000\000\000\200\000\000\000\000\001\031\001y\003\177\005&\001\031\003\132\000\000\001 \002r\000\000\001I\000\000\000\000\000\000\001\135\002l\001{\001l\000\000\000\000\002r\000\000\000\000\000\000\000\000\003\190\002\027\001\"\002n\000\200\001K\001\"\000\000\000\000\000\000\002o\004\239\003S\000\000\000\000\000\000\000\000\000\000\002l\000\000\000\000\000\000\002o\002{\003V\001{\002q\000\000\001y\002\027\000\000\002n\000\200\002r\000\000\002{\000\000\001{\002q\000\000\000\000\001\135\002\026\001{\001l\005(\002}\002\174\001e\001*\000\000\000\000\000\000\003\181\000\000\002n\000\200\001\002\002}\000\000\002o\002r\003\136\000\000\000\000\000\000\0018\002\228\001|\000\000\001h\001i\000\000\002{\001\016\001{\002q\000\000\001\016\000\000\001\023\005+\000\000\000\000\001\023\001$\000\000\000\000\002o\003\171\003\138\000\000\000\000\000\000\002\174\001e\002}\000\000\000\000\002\174\001e\002{\000\000\001{\002q\000\000\000\000\000\000\000\000\002\233\002\249\002\250\002o\000\000\002\228\001|\000\000\001h\001i\002\228\001|\000\000\001h\001i\002}\002p\000\000\001{\002q\001>\000\000\000\000\005,\000\000\000\000\000\000\001%\000\000\000\000\000\000\000\000\001\133\000\000\000\000\000\000\005%\002\174\001e\000\000\004\246\000\000\006\005\001n\005.\000\000\000\200\002\233\002\249\002\250\000\000\000\000\002\233\002\249\002\250\001.\000\000\002\228\001|\001.\001h\001i\001H\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\003\147\000\000\000\000\001\133\000\000\000\000\000\000\000\000\001\133\001d\001e\000\000\000\000\000\000\001n\000\000\000\000\000\200\000\000\001n\000\000\000\000\000\200\002\233\002\249\002\250\001y\000\000\000\000\001f\001|\000\000\001h\001i\000\000\000\000\000\000\001\031\000\000\001\135\001 \001{\001l\0012\000\000\000\000\000\000\004\016\000\000\000\000\000\000\000\000\005\221\000\000\000\000\001\133\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0013\001\"\000\000\001n\000\000\000\000\000\200\001O\000\000\001}\001y\001~\007\015\000\000\007\017\001y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\135\000\000\001{\001l\000\000\001\135\000\000\001{\001l\000\000\000\000\000\000\000\000\005\255\000\000\000\000\000\000\001\133\000\000\000\000\001\031\001*\000\000\001 \000\000\000\000\0012\000\000\001n\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\0018\001y\000\000\000\000\001\031\000\000\000\000\001 \0013\001\"\0012\000\000\001\016\000\000\001\135\0014\001{\001l\001\023\001$\001d\001e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0013\001\"\000\000\000\000\000\000\000\000\000\000\001M\000\000\000\000\001f\001|\000\000\001h\001i\000\000\000\000\000\000\000\000\001y\000\000\000\000\001*\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\135\001>\001{\001l\000\000\000\000\000\000\0018\001%\000\000\001d\001e\001*\000\000\000\000\000\000\000\000\001F\000\000\001\016\000\000\001}\000\000\001~\001\161\001\023\001$\000\000\000\000\0018\001f\001|\000\000\001h\001i\001d\001e\000\000\000\000\000\000\001.\001\016\000\000\001H\000\000\000\000\000\000\001\023\001$\000\000\000\000\000\000\001\133\000\000\000\000\001f\001|\000\000\001h\001i\001d\001e\000\000\001n\000\000\000\000\000\200\001d\001e\000\000\001>\000\000\000\000\001}\000\000\001~\001\140\001%\000\000\000\000\001f\001|\000\000\001h\001i\000\000\001F\001f\001|\000\000\001h\001i\001>\000\000\000\000\000\000\000\000\000\000\001}\001%\001~\001\137\000\000\000\000\001\133\000\000\000\000\000\000\001F\001.\000\000\000\000\001H\000\000\000\000\001n\000\000\000\000\000\200\000\000\000\000\000\000\001y\001}\000\000\001~\001\128\000\000\000\000\001\133\001}\001.\001~\001\131\001H\001\135\000\000\001{\001l\000\000\001n\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\133\000\000\001d\001e\000\000\000\000\000\000\001\133\001d\001e\000\000\001n\000\000\000\000\000\200\000\000\000\000\000\000\001n\000\000\001y\000\200\001f\001|\000\000\001h\001i\000\000\001f\001|\000\000\001h\001i\001\135\000\000\001{\001l\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001d\001e\000\000\001\135\000\000\001{\001l\000\000\000\000\000\000\001}\000\000\001~\001\134\000\000\001y\001}\000\000\001~\001\136\001f\001|\001y\001h\001i\000\000\000\000\000\000\001\135\000\000\001{\001l\000\000\000\000\000\000\001\135\000\000\001{\001l\000\000\000\000\001\133\000\000\000\000\000\000\000\000\000\000\001\133\000\000\001d\001e\000\000\001n\000\000\000\000\000\200\000\000\000\000\001n\000\000\000\000\000\200\000\000\001}\000\000\001~\001\145\000\000\000\000\001f\001|\000\000\001h\001i\000\000\000\000\001d\001e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\133\000\000\001f\001|\000\000\001h\001i\000\000\000\000\000\000\000\000\001n\000\000\000\000\000\200\000\000\000\000\001y\001}\000\000\001~\001\148\000\000\001y\000\000\000\000\000\000\000\000\000\000\000\000\001\135\000\000\001{\001l\001d\001e\001\135\000\000\001{\001l\000\000\000\000\000\000\002\224\000\000\001}\000\000\001~\002Q\001\133\000\000\002\227\000\000\000\000\001f\002\195\000\000\001h\001i\000\000\001n\000\000\000\000\000\200\000\000\000\000\000\000\000\000\000\000\000\000\001y\000\000\000\000\000\000\000\000\000\000\001\133\000\000\001d\001e\000\000\000\000\000\000\001\135\000\000\001{\001l\001n\001d\001e\000\200\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001f\001|\000\000\001h\001i\000\000\000\000\000\000\000\000\000\000\001f\001|\000\000\001h\001i\000\000\000\000\000\000\000\000\000\000\000\000\001y\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001m\000\000\000\000\000\000\001\135\000\000\001{\001l\005=\000\000\000\000\001n\000\000\001}\000\200\001~\002\238\000\000\001y\000\000\000\000\000\000\000\000\001}\000\000\001~\002\241\001d\001e\000\000\000\000\001\135\000\000\001{\001l\000\000\005>\006\225\005?\001d\001e\000\000\000\000\000\000\001\133\002\196\000\000\001f\001|\000\000\001h\001i\000\000\000\000\001\133\001n\000\000\000\000\000\200\001f\001|\000\000\001h\001i\000\000\001n\000\000\005@\000\200\000\000\001y\000\000\000\000\002\023\002\024\001e\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001z\000\000\001{\001l\000\000\000\000\000\000\001}\001\031\001~\002\244\001 \000\000\003\168\001I\000\000\000\000\005A\000\000\001}\003\177\001~\002\252\000\000\000\000\000\000\005B\000\000\005C\000\000\000\000\001y\000\000\000\000\001K\001\"\000\000\000\000\001\133\000\000\000\000\001y\000\000\003\178\001\135\000\000\001{\001l\000\000\001n\001\133\005\127\000\200\000\000\001\135\000\000\001{\001l\000\000\000\000\000\000\001n\000\000\000\000\000\200\000\000\000\000\001\031\000\000\000\000\001 \000\000\000\000\0012\005E\006\227\000\000\000\000\001*\005G\005Q\001d\001e\000\000\000\000\002\026\000\000\000\000\000\000\005{\000\000\000\000\000\000\0017\001\"\0018\003\181\000\000\002n\000\200\001\002\001f\001|\000\000\001h\001i\000\000\001\016\001y\000\000\005|\000\000\000\000\001\023\001$\000\000\000\000\000\000\000\000\000\000\001y\001\135\000\000\001{\001l\000\000\000\000\000\000\000\000\001d\001e\000\000\003\171\001\135\000\000\001{\001l\001*\000\000\000\000\000\000\000\000\000\000\000\000\001}\000\000\001~\004K\000\000\001f\002\195\000\000\001h\001i\0018\002o\000\000\000\000\001>\001d\001e\000\000\000\000\000\000\000\000\001%\001\016\000\000\002p\000\000\001{\002q\001\023\001$\001F\001\133\004\022\000\000\000\000\001f\002\195\000\000\001h\001i\000\000\000\000\001n\001d\001e\000\200\000\000\000\000\001d\001e\000\000\000\000\000\000\001.\000\000\000\000\001H\000\000\000\000\000\000\000\000\000\000\000\000\001f\002\195\000\000\001h\001i\001f\002\195\000\000\001h\001i\001>\000\000\001d\001e\000\000\000\000\001m\001%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001F\001n\000\000\000\000\000\200\000\000\001f\002\195\000\000\001h\001i\000\000\001y\000\000\000\000\000\000\001d\001e\000\000\000\000\001m\001d\001e\001.\000\000\001\135\001H\001{\001l\000\000\000\000\001n\000\000\005\183\000\200\003u\001f\002\195\005\207\001h\001i\001f\002\195\000\000\001h\001i\000\000\000\000\001m\000\000\000\000\000\000\000\000\001m\003w\000\000\000\000\000\000\000\000\001n\001y\000\000\000\200\000\000\001n\002\196\000\000\000\200\000\000\000\000\000\000\000\000\000\000\001z\000\000\001{\001l\000\000\000\000\000\000\001m\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001y\001n\000\000\003u\000\200\000\000\000\000\000\000\003u\000\000\000\000\000\000\000\000\001z\000\000\001{\001l\000\000\000\000\000\000\001m\000\000\003v\000\000\000\000\001m\000\000\003z\001y\000\000\000\000\001n\000\000\001y\000\200\006\"\001n\000\000\000\000\000\200\000\000\001z\000\000\001{\001l\000\000\001z\000\000\001{\001l\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001d\001e\000\000\001y\000\000\001d\001e\000\000\002\196\000\000\000\000\005=\000\000\002\196\000\000\000\000\001z\000\000\001{\001l\001f\002\195\000\000\001h\001i\001f\002\195\000\000\001h\001i\006$\000\000\000\000\001y\000\000\001d\001e\000\000\001y\005>\006\207\005?\001d\001e\000\000\000\000\001z\000\000\001{\001l\000\000\001z\000\000\001{\001l\001f\002\195\000\000\001h\001i\000\000\000\000\001f\002\195\000\000\001h\001i\000\000\001d\001e\005@\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001f\002\195\000\000\001h\001i\000\000\001m\000\000\002\023\002\024\001e\001m\000\000\000\000\000\000\005A\000\000\001n\000\000\000\000\000\200\000\000\001n\000\000\005B\000\200\005C\000\000\000\000\000\000\001\031\006a\000\000\001 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\001m\000\000\000\000\000\000\000\000\000\000\000\000\001m\005\127\000\000\005\234\001n\000\000\000\000\000\200\005\234\001\"\000\000\001n\000\000\000\000\000\200\000\000\000\000\000\000\000\000\004\224\000\000\000\000\000\000\000\000\005E\000\000\001m\000\000\001y\005G\005Q\000\000\000\000\001y\005\204\006/\000\000\001n\006\"\005{\000\200\001z\000\000\001{\001l\006\"\001z\000\000\001{\001l\007.\000\000\001*\007/\005\247\002\026\0062\000\000\000\000\005\246\005|\000\000\000\000\001y\000\000\0063\002\027\000\000\002n\000\200\001y\003y\002\023\002\024\001e\000\000\001z\000\000\001{\001l\000\000\001\016\000\000\001z\006/\001{\001l\001\023\001$\000\000\006#\000\000\000\000\000\000\0064\003W\001y\006+\000\000\007.\006/\000\000\007/\001d\001e\0062\000\000\000\000\000\000\001z\000\000\001{\001l\000\000\0063\007.\000\000\000\000\007/\005\240\000\000\0062\000\000\001f\001w\002o\001h\001i\0065\000\000\0063\000\000\001>\000\000\000\000\000\000\0066\000\000\002p\001%\001{\002q\000\000\0064\000\000\000\000\000\000\000\000\004\229\000\000\000\000\000\000\000\000\000\000\000\000\000\000\0071\000\000\006/\0064\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\026\000\000\000\000\005=\001.\000\000\007.\001H\0068\007/\0065\002\027\0062\002n\000\200\000\000\000\000\0069\0066\000\000\000\000\0063\006;\000\000\000\000\000\000\0065\000\000\001d\001e\001m\005>\006=\005?\0066\000\000\000\000\000\000\0070\000\000\000\000\001n\000\000\000\000\000\200\000\000\003Z\000\000\001f\001x\0064\001h\001i\006>\0074\001d\001e\0068\000\000\000\000\000\000\000\000\005@\000\000\000\000\000\000\0069\000\000\000\000\000\000\002o\006;\000\000\0068\001\031\001f\002\180\001 \001h\001i\000\000\006=\0069\002p\0065\001{\002q\006;\000\000\000\000\000\000\000\000\0066\000\000\000\000\005A\000\000\006=\000\000\000\000\001y\001\"\006>\000\000\005B\001\031\005C\001\031\001 \000\000\001 \002\217\0079\001z\000\000\001{\001l\000\000\006>\000\000\000\000\001\031\001m\000\000\001 \000\000\000\000\000\000\000\000\005}\000\000\0068\001\"\001n\001\"\000\000\000\200\000\000\000\000\004\239\0069\000\000\003\240\000\000\001*\006;\000\000\000\000\001\"\001m\000\000\000\000\005E\000\000\000\000\006=\003\243\005G\005Q\000\000\001n\000\000\000\000\000\200\000\000\000\000\005=\005{\000\000\000\000\000\000\000\000\000\000\001\016\000\000\001*\006>\001*\000\000\001\023\001$\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005|\000\000\000\000\001*\001y\000\000\005>\000\000\005?\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\016\001z\001\016\001{\001l\000\000\001\023\001$\001\023\001$\000\000\000\000\000\000\000\000\001\031\001y\001\016\001 \000\000\000\000\001>\005@\001\023\001$\000\000\000\000\000\000\001%\001z\001\031\001{\001l\001 \000\000\000\000\000\000\002\188\000\000\000\000\000\000\000\000\001\"\000\000\006/\000\000\000\000\005\229\000\000\000\000\000\000\000\000\001>\000\000\001>\005A\000\000\001\"\000\000\001%\001.\001%\0060\001H\005B\0062\005C\000\000\001>\000\000\004\244\000\000\000\000\000\000\0063\001%\000\000\000\000\000\000\000\000\000\000\006/\000\000\000\000\005\001\001*\000\000\005\004\000\000\005D\000\000\001.\000\000\001.\003\247\000\000\001H\000\000\000\000\0060\001*\006/\0062\0064\000\000\000\000\001\031\001.\000\000\001 \001H\0063\005E\000\000\001\016\000\000\000\000\005G\005Q\0060\001\023\001$\0062\000\000\000\000\000\000\000\000\005{\000\000\001\016\000\000\0063\000\000\001\"\000\000\001\023\001$\0065\006/\000\000\0064\000\000\000\000\001\031\000\000\0066\001 \000\000\005|\000\000\000\000\000\000\000\000\000\000\000\000\000\000\007%\000\000\000\000\0062\0064\000\000\000\000\001\031\000\000\001>\001 \000\000\0063\0067\001\"\000\000\001%\000\000\0065\000\000\001*\000\000\000\000\000\000\001>\004\244\0066\001\031\0068\000\000\001 \001%\000\000\000\000\001\"\000\000\000\000\0069\0065\000\000\005\001\0064\006;\006\019\001\031\000\000\0066\001 \001.\001\016\006B\001H\006=\006\251\001\"\001\023\001$\001*\000\000\000\000\000\000\000\000\001<\001.\001\031\0068\001H\001 \000\000\000\000\006K\001\"\000\000\006>\0069\0065\000\000\001*\000\000\006;\002\023\002\024\001e\0066\000\000\0068\001\016\000\000\000\000\006=\000\000\001\"\001\023\001$\0069\000\000\000\000\001*\001\031\006;\001>\001 \000\000\003\185\007&\000\000\001\016\001%\000\000\006=\006>\000\000\001\023\001$\001*\000\000\001X\002\023\002\024\001e\000\000\000\000\0068\000\000\000\000\001\"\001\016\000\000\000\000\000\000\006>\0069\001\023\001$\001*\001\031\006;\001>\001 \001.\002\025\000\000\001H\001\016\001%\000\000\006=\000\000\000\000\001\023\001$\000\000\000\000\006\252\000\000\000\000\000\000\001>\000\000\000\000\000\000\000\000\001\"\001\016\001%\000\000\000\000\006>\001*\001\023\001$\000\000\000\000\001\177\000\000\002\026\001.\001>\000\000\001H\000\000\000\000\000\000\000\000\001%\000\000\002\027\000\000\002n\000\200\000\000\000\000\000\000\000\000\001>\000\000\001.\001\016\000\000\001H\000\000\001%\000\000\001\023\001$\001*\000\000\000\000\000\000\000\000\001\215\000\000\002\026\000\000\001>\000\000\001.\000\000\000\000\001D\000\000\001%\000\000\002\027\000\000\002n\000\200\002\023\002\024\001e\001\217\000\000\000\000\001.\001\016\000\000\001H\000\000\000\000\000\000\001\023\001$\000\000\000\000\000\000\002o\000\000\000\000\001>\001\031\002V\000\000\001 \001.\000\000\001%\001H\000\000\002p\000\000\001{\002q\000\000\000\000\002.\002\023\002\024\001e\000\000\000\000\002\023\002\024\001e\000\000\000\000\000\000\001\"\002\023\002\024\001e\000\000\000\000\002o\001\031\000\000\001>\001 \001.\002X\000\000\001H\000\000\001%\002b\000\000\002p\000\000\001{\002q\000\000\002m\002A\000\000\002\023\002\024\001e\000\000\000\000\000\000\000\000\001\"\000\000\000\000\000\000\001\031\000\000\000\000\001 \000\000\001*\000\000\000\000\002\026\000\000\001.\000\000\002|\001H\000\000\000\000\000\000\000\000\000\000\002\027\000\000\002n\000\200\000\000\000\000\000\000\000\000\001\"\000\000\000\000\000\000\000\000\000\000\000\000\001\016\000\000\000\000\000\000\000\000\001*\001\023\001$\000\000\000\000\000\000\000\000\002\026\000\000\000\000\000\000\001\031\002\026\000\000\001 \000\000\000\000\000\000\002\027\002\026\002n\000\200\000\000\002\027\000\000\002n\000\200\000\000\000\000\001\016\002\027\001*\002n\000\200\000\000\001\023\001$\000\000\001\"\002o\000\000\000\000\000\000\000\000\000\000\002\026\001>\000\000\000\000\000\000\000\000\000\000\002p\001%\001{\002q\002\027\000\000\002n\000\200\001\016\000\000\002\185\000\000\000\000\000\000\001\023\001$\000\000\000\000\000\000\000\000\000\000\001\031\000\000\000\000\001 \002o\000\000\000\000\001>\001*\002o\000\000\000\000\001.\000\000\001%\001H\002o\002p\000\000\001{\002q\000\000\002p\002\190\001{\002q\000\000\001\"\000\000\002p\000\000\001{\002q\001\031\000\000\000\000\001 \001\016\001>\002\023\002\024\001e\002o\001\023\001$\001%\001.\000\000\000\000\001H\000\000\000\000\000\000\000\000\002\207\002p\000\000\001{\002q\000\000\001\"\000\000\003\030\000\000\000\000\000\000\001\031\000\000\000\000\001 \001*\001\031\000\000\000\000\001 \000\000\000\000\001.\000\000\000\000\001H\001\031\000\000\000\000\001 \000\000\000\000\000\000\001>\000\000\000\000\000\000\000\000\001\"\000\000\001%\000\000\000\000\001\"\001\016\000\000\000\000\000\000\001*\002\214\001\023\001$\000\000\001\"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001.\001\031\000\000\001H\001 \001\016\000\000\002\026\000\000\001*\000\000\001\023\001$\001\031\001*\000\000\001 \000\000\002\027\000\000\002n\000\200\000\000\001>\001*\000\000\000\000\000\000\001\"\000\000\001%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\016\002\221\001\"\000\000\000\000\001\016\001\023\001$\000\000\000\000\000\000\001\023\001$\001\031\000\000\001\016\001 \000\000\001>\000\000\000\000\001\023\001$\000\000\001.\001%\000\000\001H\000\000\000\000\000\000\000\000\001\031\001*\002\230\001 \000\000\000\000\000\000\002o\001\"\000\000\000\000\000\000\001\031\001*\000\000\001 \000\000\000\000\000\000\001>\002p\000\000\001{\002q\001>\001.\001%\001\"\001H\000\000\001\016\001%\000\000\000\000\001>\004Z\001\023\001$\000\000\001\"\004\201\001%\001\016\000\000\000\000\000\000\000\000\000\000\001\023\001$\004\213\001*\000\000\000\000\000\000\000\000\000\000\000\000\001.\000\000\000\000\001H\000\000\001.\000\000\000\000\001H\000\000\000\000\001\031\001*\000\000\001 \001.\000\000\000\000\001H\000\000\000\000\000\000\001\016\001>\001*\000\000\000\000\000\000\001\023\001$\001%\001\031\000\000\000\000\005&\001>\000\000\000\000\001\"\004\226\000\000\001\016\001%\000\000\000\000\000\000\000\000\001\023\001$\001\031\000\000\004\243\001 \001\016\000\000\000\000\000\000\000\000\001\"\001\023\001$\000\000\001.\000\000\000\000\001H\000\000\000\000\001\031\000\000\000\000\001 \000\000\001>\001.\000\000\001\"\001H\000\000\001\031\001%\001*\001 \000\000\000\000\000\000\000\000\001\031\000\000\005\003\001 \000\000\001>\000\000\000\000\001\"\000\000\000\000\000\000\001%\000\000\005(\000\000\000\000\001>\000\000\001\"\000\000\005\159\000\000\001\016\001%\001.\000\000\001\"\001H\001\023\001$\000\000\001*\005\177\000\000\000\000\000\000\000\000\001\031\000\000\000\000\001 \000\000\001\016\001.\000\000\000\000\001H\000\000\001\023\005+\001*\000\000\000\000\000\000\000\000\001.\001\031\000\000\001H\001 \001\016\001*\000\000\000\000\001\"\001\031\001\023\001$\001 \001*\000\000\000\000\000\000\001>\000\000\000\000\000\000\000\000\000\000\001\016\001%\000\000\000\000\001\"\000\000\001\023\001$\000\000\000\000\005\201\001\016\000\000\001\"\000\000\000\000\000\000\001\023\001$\001\016\000\000\005,\000\000\000\000\000\000\001\023\001$\000\000\001*\000\000\000\000\000\000\001>\001.\000\000\000\000\001H\000\000\004\246\001%\006\031\000\000\005.\000\000\000\000\000\000\000\000\001*\006W\000\000\000\000\001>\000\000\001.\000\000\000\000\001*\001\016\001%\000\000\000\000\000\000\001>\001\023\001$\000\000\000\000\006\172\000\000\001%\001>\001.\000\000\000\000\001H\000\000\001\016\001%\006\176\000\000\000\000\000\000\001\023\001$\000\000\001\016\000\000\000\000\000\000\000\000\001.\001\023\001$\001H\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001.\000\000\000\000\001H\000\000\000\000\000\000\001>\001.\000\000\000\000\001?\000\000\000\000\001%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001>\000\000\000\000\000\000\000\000\000\000\000\000\001%\000\000\001>\000\000\000\000\000\000\000\000\000\000\000\000\001%\000\000\000\000\000\000\001.\000\000\000\000\001\210\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001.\000\000\000\000\001\212\000\000\000\000\000\000\000\000\000\000\001.\000\000\000\000\003\242")) and semantic_action = [| @@ -1332,9 +1337,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3652 "parsing/parser.mly" +# 3693 "parsing/parser.mly" ( "+" ) -# 1338 "parsing/parser.ml" +# 1343 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -1357,9 +1362,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3653 "parsing/parser.mly" +# 3694 "parsing/parser.mly" ( "+." ) -# 1363 "parsing/parser.ml" +# 1368 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -1382,9 +1387,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.core_type) = -# 3209 "parsing/parser.mly" +# 3250 "parsing/parser.mly" ( _1 ) -# 1388 "parsing/parser.ml" +# 1393 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -1429,24 +1434,24 @@ module Tables = struct let _endpos = _endpos_tyvar_ in let _v : (Parsetree.core_type) = let _1 = let _1 = -# 3212 "parsing/parser.mly" +# 3253 "parsing/parser.mly" ( Ptyp_alias(ty, tyvar) ) -# 1435 "parsing/parser.ml" +# 1440 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_tyvar_, _startpos_ty_) in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 1444 "parsing/parser.ml" +# 1449 "parsing/parser.ml" in -# 3214 "parsing/parser.mly" +# 3255 "parsing/parser.mly" ( _1 ) -# 1450 "parsing/parser.ml" +# 1455 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -1492,30 +1497,30 @@ module Tables = struct let _v : (let_binding) = let attrs2 = let _1 = _1_inlined2 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 1498 "parsing/parser.ml" +# 1503 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined2_ in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 1507 "parsing/parser.ml" +# 1512 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2478 "parsing/parser.mly" +# 2483 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in mklb ~loc:_sloc false body attrs ) -# 1519 "parsing/parser.ml" +# 1524 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -1538,9 +1543,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3539 "parsing/parser.mly" +# 3580 "parsing/parser.mly" ( _1 ) -# 1544 "parsing/parser.ml" +# 1549 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -1563,9 +1568,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3540 "parsing/parser.mly" +# 3581 "parsing/parser.mly" ( Lident _1 ) -# 1569 "parsing/parser.ml" +# 1574 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -1602,9 +1607,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.core_type) = -# 3270 "parsing/parser.mly" +# 3311 "parsing/parser.mly" ( _2 ) -# 1608 "parsing/parser.ml" +# 1613 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -1667,11 +1672,11 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3330 "parsing/parser.mly" +# 3371 "parsing/parser.mly" ( let (lid, cstrs, attrs) = package_type_of_module_type _1 in let descr = Ptyp_package (lid, cstrs) in mktyp ~loc:_sloc ~attrs descr ) -# 1675 "parsing/parser.ml" +# 1680 "parsing/parser.ml" in let _3 = @@ -1679,24 +1684,24 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 1685 "parsing/parser.ml" +# 1690 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 1691 "parsing/parser.ml" +# 1696 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3272 "parsing/parser.mly" +# 3313 "parsing/parser.mly" ( wrap_typ_attrs ~loc:_sloc (reloc_typ ~loc:_sloc _4) _3 ) -# 1700 "parsing/parser.ml" +# 1705 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -1727,24 +1732,24 @@ module Tables = struct let _endpos = _endpos__2_ in let _v : (Parsetree.core_type) = let _1 = let _1 = -# 3275 "parsing/parser.mly" +# 3316 "parsing/parser.mly" ( Ptyp_var _2 ) -# 1733 "parsing/parser.ml" +# 1738 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 1742 "parsing/parser.ml" +# 1747 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 1748 "parsing/parser.ml" +# 1753 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -1768,23 +1773,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.core_type) = let _1 = let _1 = -# 3277 "parsing/parser.mly" +# 3318 "parsing/parser.mly" ( Ptyp_any ) -# 1774 "parsing/parser.ml" +# 1779 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 1782 "parsing/parser.ml" +# 1787 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 1788 "parsing/parser.ml" +# 1793 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -1813,35 +1818,35 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 1819 "parsing/parser.ml" +# 1824 "parsing/parser.ml" in let tys = -# 3322 "parsing/parser.mly" +# 3363 "parsing/parser.mly" ( [] ) -# 1825 "parsing/parser.ml" +# 1830 "parsing/parser.ml" in -# 3280 "parsing/parser.mly" +# 3321 "parsing/parser.mly" ( Ptyp_constr(tid, tys) ) -# 1830 "parsing/parser.ml" +# 1835 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 1839 "parsing/parser.ml" +# 1844 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 1845 "parsing/parser.ml" +# 1850 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -1877,20 +1882,20 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 1883 "parsing/parser.ml" +# 1888 "parsing/parser.ml" in let tys = -# 3324 "parsing/parser.mly" +# 3365 "parsing/parser.mly" ( [ty] ) -# 1889 "parsing/parser.ml" +# 1894 "parsing/parser.ml" in -# 3280 "parsing/parser.mly" +# 3321 "parsing/parser.mly" ( Ptyp_constr(tid, tys) ) -# 1894 "parsing/parser.ml" +# 1899 "parsing/parser.ml" in let _startpos__1_ = _startpos_ty_ in @@ -1898,15 +1903,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 1904 "parsing/parser.ml" +# 1909 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 1910 "parsing/parser.ml" +# 1915 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -1957,9 +1962,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 1963 "parsing/parser.ml" +# 1968 "parsing/parser.ml" in let tys = @@ -1967,24 +1972,24 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 1971 "parsing/parser.ml" +# 1976 "parsing/parser.ml" in -# 975 "parsing/parser.mly" +# 976 "parsing/parser.mly" ( xs ) -# 1976 "parsing/parser.ml" +# 1981 "parsing/parser.ml" in -# 3326 "parsing/parser.mly" +# 3367 "parsing/parser.mly" ( tys ) -# 1982 "parsing/parser.ml" +# 1987 "parsing/parser.ml" in -# 3280 "parsing/parser.mly" +# 3321 "parsing/parser.mly" ( Ptyp_constr(tid, tys) ) -# 1988 "parsing/parser.ml" +# 1993 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined1_ in @@ -1992,15 +1997,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 1998 "parsing/parser.ml" +# 2003 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 2004 "parsing/parser.ml" +# 2009 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -2038,24 +2043,24 @@ module Tables = struct let _endpos = _endpos__3_ in let _v : (Parsetree.core_type) = let _1 = let _1 = -# 3282 "parsing/parser.mly" +# 3323 "parsing/parser.mly" ( let (f, c) = _2 in Ptyp_object (f, c) ) -# 2044 "parsing/parser.ml" +# 2049 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 2053 "parsing/parser.ml" +# 2058 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 2059 "parsing/parser.ml" +# 2064 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -2086,24 +2091,24 @@ module Tables = struct let _endpos = _endpos__2_ in let _v : (Parsetree.core_type) = let _1 = let _1 = -# 3284 "parsing/parser.mly" +# 3325 "parsing/parser.mly" ( Ptyp_object ([], Closed) ) -# 2092 "parsing/parser.ml" +# 2097 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 2101 "parsing/parser.ml" +# 2106 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 2107 "parsing/parser.ml" +# 2112 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -2139,20 +2144,20 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 2145 "parsing/parser.ml" +# 2150 "parsing/parser.ml" in let tys = -# 3322 "parsing/parser.mly" +# 3363 "parsing/parser.mly" ( [] ) -# 2151 "parsing/parser.ml" +# 2156 "parsing/parser.ml" in -# 3288 "parsing/parser.mly" +# 3329 "parsing/parser.mly" ( Ptyp_class(cid, tys) ) -# 2156 "parsing/parser.ml" +# 2161 "parsing/parser.ml" in let _startpos__1_ = _startpos__2_ in @@ -2160,15 +2165,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 2166 "parsing/parser.ml" +# 2171 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 2172 "parsing/parser.ml" +# 2177 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -2211,20 +2216,20 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 2217 "parsing/parser.ml" +# 2222 "parsing/parser.ml" in let tys = -# 3324 "parsing/parser.mly" +# 3365 "parsing/parser.mly" ( [ty] ) -# 2223 "parsing/parser.ml" +# 2228 "parsing/parser.ml" in -# 3288 "parsing/parser.mly" +# 3329 "parsing/parser.mly" ( Ptyp_class(cid, tys) ) -# 2228 "parsing/parser.ml" +# 2233 "parsing/parser.ml" in let _startpos__1_ = _startpos_ty_ in @@ -2232,15 +2237,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 2238 "parsing/parser.ml" +# 2243 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 2244 "parsing/parser.ml" +# 2249 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -2298,9 +2303,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 2304 "parsing/parser.ml" +# 2309 "parsing/parser.ml" in let tys = @@ -2308,24 +2313,24 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 2312 "parsing/parser.ml" +# 2317 "parsing/parser.ml" in -# 975 "parsing/parser.mly" +# 976 "parsing/parser.mly" ( xs ) -# 2317 "parsing/parser.ml" +# 2322 "parsing/parser.ml" in -# 3326 "parsing/parser.mly" +# 3367 "parsing/parser.mly" ( tys ) -# 2323 "parsing/parser.ml" +# 2328 "parsing/parser.ml" in -# 3288 "parsing/parser.mly" +# 3329 "parsing/parser.mly" ( Ptyp_class(cid, tys) ) -# 2329 "parsing/parser.ml" +# 2334 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined1_ in @@ -2333,15 +2338,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 2339 "parsing/parser.ml" +# 2344 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 2345 "parsing/parser.ml" +# 2350 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -2379,24 +2384,24 @@ module Tables = struct let _endpos = _endpos__3_ in let _v : (Parsetree.core_type) = let _1 = let _1 = -# 3291 "parsing/parser.mly" +# 3332 "parsing/parser.mly" ( Ptyp_variant([_2], Closed, None) ) -# 2385 "parsing/parser.ml" +# 2390 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 2394 "parsing/parser.ml" +# 2399 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 2400 "parsing/parser.ml" +# 2405 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -2446,24 +2451,24 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 2450 "parsing/parser.ml" +# 2455 "parsing/parser.ml" in -# 947 "parsing/parser.mly" +# 948 "parsing/parser.mly" ( xs ) -# 2455 "parsing/parser.ml" +# 2460 "parsing/parser.ml" in -# 3336 "parsing/parser.mly" +# 3377 "parsing/parser.mly" ( _1 ) -# 2461 "parsing/parser.ml" +# 2466 "parsing/parser.ml" in -# 3293 "parsing/parser.mly" +# 3334 "parsing/parser.mly" ( Ptyp_variant(_3, Closed, None) ) -# 2467 "parsing/parser.ml" +# 2472 "parsing/parser.ml" in let _endpos__1_ = _endpos__4_ in @@ -2471,15 +2476,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 2477 "parsing/parser.ml" +# 2482 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 2483 "parsing/parser.ml" +# 2488 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -2536,24 +2541,24 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 2540 "parsing/parser.ml" +# 2545 "parsing/parser.ml" in -# 947 "parsing/parser.mly" +# 948 "parsing/parser.mly" ( xs ) -# 2545 "parsing/parser.ml" +# 2550 "parsing/parser.ml" in -# 3336 "parsing/parser.mly" +# 3377 "parsing/parser.mly" ( _1 ) -# 2551 "parsing/parser.ml" +# 2556 "parsing/parser.ml" in -# 3295 "parsing/parser.mly" +# 3336 "parsing/parser.mly" ( Ptyp_variant(_2 :: _4, Closed, None) ) -# 2557 "parsing/parser.ml" +# 2562 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -2561,15 +2566,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 2567 "parsing/parser.ml" +# 2572 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 2573 "parsing/parser.ml" +# 2578 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -2619,24 +2624,24 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 2623 "parsing/parser.ml" +# 2628 "parsing/parser.ml" in -# 947 "parsing/parser.mly" +# 948 "parsing/parser.mly" ( xs ) -# 2628 "parsing/parser.ml" +# 2633 "parsing/parser.ml" in -# 3336 "parsing/parser.mly" +# 3377 "parsing/parser.mly" ( _1 ) -# 2634 "parsing/parser.ml" +# 2639 "parsing/parser.ml" in -# 3297 "parsing/parser.mly" +# 3338 "parsing/parser.mly" ( Ptyp_variant(_3, Open, None) ) -# 2640 "parsing/parser.ml" +# 2645 "parsing/parser.ml" in let _endpos__1_ = _endpos__4_ in @@ -2644,15 +2649,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 2650 "parsing/parser.ml" +# 2655 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 2656 "parsing/parser.ml" +# 2661 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -2683,24 +2688,24 @@ module Tables = struct let _endpos = _endpos__2_ in let _v : (Parsetree.core_type) = let _1 = let _1 = -# 3299 "parsing/parser.mly" +# 3340 "parsing/parser.mly" ( Ptyp_variant([], Open, None) ) -# 2689 "parsing/parser.ml" +# 2694 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 2698 "parsing/parser.ml" +# 2703 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 2704 "parsing/parser.ml" +# 2709 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -2750,24 +2755,24 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 2754 "parsing/parser.ml" +# 2759 "parsing/parser.ml" in -# 947 "parsing/parser.mly" +# 948 "parsing/parser.mly" ( xs ) -# 2759 "parsing/parser.ml" +# 2764 "parsing/parser.ml" in -# 3336 "parsing/parser.mly" +# 3377 "parsing/parser.mly" ( _1 ) -# 2765 "parsing/parser.ml" +# 2770 "parsing/parser.ml" in -# 3301 "parsing/parser.mly" +# 3342 "parsing/parser.mly" ( Ptyp_variant(_3, Closed, Some []) ) -# 2771 "parsing/parser.ml" +# 2776 "parsing/parser.ml" in let _endpos__1_ = _endpos__4_ in @@ -2775,15 +2780,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 2781 "parsing/parser.ml" +# 2786 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 2787 "parsing/parser.ml" +# 2792 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -2848,18 +2853,18 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 2852 "parsing/parser.ml" +# 2857 "parsing/parser.ml" in -# 915 "parsing/parser.mly" +# 916 "parsing/parser.mly" ( xs ) -# 2857 "parsing/parser.ml" +# 2862 "parsing/parser.ml" in -# 3364 "parsing/parser.mly" +# 3405 "parsing/parser.mly" ( _1 ) -# 2863 "parsing/parser.ml" +# 2868 "parsing/parser.ml" in let _3 = @@ -2867,24 +2872,24 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 2871 "parsing/parser.ml" +# 2876 "parsing/parser.ml" in -# 947 "parsing/parser.mly" +# 948 "parsing/parser.mly" ( xs ) -# 2876 "parsing/parser.ml" +# 2881 "parsing/parser.ml" in -# 3336 "parsing/parser.mly" +# 3377 "parsing/parser.mly" ( _1 ) -# 2882 "parsing/parser.ml" +# 2887 "parsing/parser.ml" in -# 3303 "parsing/parser.mly" +# 3344 "parsing/parser.mly" ( Ptyp_variant(_3, Closed, Some _5) ) -# 2888 "parsing/parser.ml" +# 2893 "parsing/parser.ml" in let _endpos__1_ = _endpos__6_ in @@ -2892,15 +2897,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 2898 "parsing/parser.ml" +# 2903 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 2904 "parsing/parser.ml" +# 2909 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -2924,23 +2929,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.core_type) = let _1 = let _1 = -# 3305 "parsing/parser.mly" +# 3346 "parsing/parser.mly" ( Ptyp_extension _1 ) -# 2930 "parsing/parser.ml" +# 2935 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 2938 "parsing/parser.ml" +# 2943 "parsing/parser.ml" in -# 3307 "parsing/parser.mly" +# 3348 "parsing/parser.mly" ( _1 ) -# 2944 "parsing/parser.ml" +# 2949 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -2964,23 +2969,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (string Asttypes.loc) = let _1 = let _1 = -# 3719 "parsing/parser.mly" +# 3760 "parsing/parser.mly" ( _1 ) -# 2970 "parsing/parser.ml" +# 2975 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 843 "parsing/parser.mly" +# 844 "parsing/parser.mly" ( mkloc _1 (make_loc _sloc) ) -# 2978 "parsing/parser.ml" +# 2983 "parsing/parser.ml" in -# 3721 "parsing/parser.mly" +# 3762 "parsing/parser.mly" ( _1 ) -# 2984 "parsing/parser.ml" +# 2989 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3018,24 +3023,24 @@ module Tables = struct let _endpos = _endpos__3_ in let _v : (string Asttypes.loc) = let _1 = let _1 = -# 3720 "parsing/parser.mly" +# 3761 "parsing/parser.mly" ( _1 ^ "." ^ _3.txt ) -# 3024 "parsing/parser.ml" +# 3029 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 843 "parsing/parser.mly" +# 844 "parsing/parser.mly" ( mkloc _1 (make_loc _sloc) ) -# 3033 "parsing/parser.ml" +# 3038 "parsing/parser.ml" in -# 3721 "parsing/parser.mly" +# 3762 "parsing/parser.mly" ( _1 ) -# 3039 "parsing/parser.ml" +# 3044 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3082,9 +3087,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3725 "parsing/parser.mly" +# 3766 "parsing/parser.mly" ( Attr.mk ~loc:(make_loc _sloc) _2 _3 ) -# 3088 "parsing/parser.ml" +# 3093 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3107,9 +3112,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.class_expr) = -# 1762 "parsing/parser.mly" +# 1767 "parsing/parser.mly" ( _1 ) -# 3113 "parsing/parser.ml" +# 3118 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3148,18 +3153,18 @@ module Tables = struct let _v : (Parsetree.class_expr) = let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 3154 "parsing/parser.ml" +# 3159 "parsing/parser.ml" in let _endpos = _endpos__3_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1764 "parsing/parser.mly" +# 1769 "parsing/parser.mly" ( wrap_class_attrs ~loc:_sloc _3 _2 ) -# 3163 "parsing/parser.ml" +# 3168 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3199,9 +3204,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1766 "parsing/parser.mly" +# 1771 "parsing/parser.mly" ( class_of_let_bindings ~loc:_sloc _1 _3 ) -# 3205 "parsing/parser.ml" +# 3210 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3264,34 +3269,34 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 3270 "parsing/parser.ml" +# 3275 "parsing/parser.ml" in let _4 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 3278 "parsing/parser.ml" +# 3283 "parsing/parser.ml" in let _endpos__4_ = _endpos__1_inlined1_ in let _3 = -# 3644 "parsing/parser.mly" +# 3685 "parsing/parser.mly" ( Fresh ) -# 3285 "parsing/parser.ml" +# 3290 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1768 "parsing/parser.mly" +# 1773 "parsing/parser.mly" ( let loc = (_startpos__2_, _endpos__4_) in let od = Opn.mk ~override:_3 ~loc:(make_loc loc) _5 in mkclass ~loc:_sloc ~attrs:_4 (Pcl_open(od, _7)) ) -# 3295 "parsing/parser.ml" +# 3300 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3361,37 +3366,37 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 3367 "parsing/parser.ml" +# 3372 "parsing/parser.ml" in let _4 = let _1 = _1_inlined2 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 3375 "parsing/parser.ml" +# 3380 "parsing/parser.ml" in let _endpos__4_ = _endpos__1_inlined2_ in let _3 = let _1 = _1_inlined1 in -# 3645 "parsing/parser.mly" +# 3686 "parsing/parser.mly" ( Override ) -# 3384 "parsing/parser.ml" +# 3389 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1768 "parsing/parser.mly" +# 1773 "parsing/parser.mly" ( let loc = (_startpos__2_, _endpos__4_) in let od = Opn.mk ~override:_3 ~loc:(make_loc loc) _5 in mkclass ~loc:_sloc ~attrs:_4 (Pcl_open(od, _7)) ) -# 3395 "parsing/parser.ml" +# 3400 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3421,9 +3426,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.class_expr) = -# 1772 "parsing/parser.mly" +# 1777 "parsing/parser.mly" ( Cl.attr _1 _2 ) -# 3427 "parsing/parser.ml" +# 3432 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3458,18 +3463,18 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 3462 "parsing/parser.ml" +# 3467 "parsing/parser.ml" in -# 915 "parsing/parser.mly" +# 916 "parsing/parser.mly" ( xs ) -# 3467 "parsing/parser.ml" +# 3472 "parsing/parser.ml" in -# 1775 "parsing/parser.mly" +# 1780 "parsing/parser.mly" ( Pcl_apply(_1, _2) ) -# 3473 "parsing/parser.ml" +# 3478 "parsing/parser.ml" in let _endpos__1_ = _endpos_xs_ in @@ -3477,15 +3482,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 866 "parsing/parser.mly" +# 867 "parsing/parser.mly" ( mkclass ~loc:_sloc _1 ) -# 3483 "parsing/parser.ml" +# 3488 "parsing/parser.ml" in -# 1778 "parsing/parser.mly" +# 1783 "parsing/parser.mly" ( _1 ) -# 3489 "parsing/parser.ml" +# 3494 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3509,23 +3514,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.class_expr) = let _1 = let _1 = -# 1777 "parsing/parser.mly" +# 1782 "parsing/parser.mly" ( Pcl_extension _1 ) -# 3515 "parsing/parser.ml" +# 3520 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 866 "parsing/parser.mly" +# 867 "parsing/parser.mly" ( mkclass ~loc:_sloc _1 ) -# 3523 "parsing/parser.ml" +# 3528 "parsing/parser.ml" in -# 1778 "parsing/parser.mly" +# 1783 "parsing/parser.mly" ( _1 ) -# 3529 "parsing/parser.ml" +# 3534 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3578,33 +3583,33 @@ module Tables = struct let _v : (Parsetree.class_field) = let _6 = let _1 = _1_inlined2 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 3584 "parsing/parser.ml" +# 3589 "parsing/parser.ml" in let _endpos__6_ = _endpos__1_inlined2_ in let _3 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 3593 "parsing/parser.ml" +# 3598 "parsing/parser.ml" in let _2 = -# 3644 "parsing/parser.mly" +# 3685 "parsing/parser.mly" ( Fresh ) -# 3599 "parsing/parser.ml" +# 3604 "parsing/parser.ml" in let _endpos = _endpos__6_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1827 "parsing/parser.mly" +# 1832 "parsing/parser.mly" ( let docs = symbol_docs _sloc in mkcf ~loc:_sloc (Pcf_inherit (_2, _4, self)) ~attrs:(_3@_6) ~docs ) -# 3608 "parsing/parser.ml" +# 3613 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3664,36 +3669,36 @@ module Tables = struct let _v : (Parsetree.class_field) = let _6 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 3670 "parsing/parser.ml" +# 3675 "parsing/parser.ml" in let _endpos__6_ = _endpos__1_inlined3_ in let _3 = let _1 = _1_inlined2 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 3679 "parsing/parser.ml" +# 3684 "parsing/parser.ml" in let _2 = let _1 = _1_inlined1 in -# 3645 "parsing/parser.mly" +# 3686 "parsing/parser.mly" ( Override ) -# 3687 "parsing/parser.ml" +# 3692 "parsing/parser.ml" in let _endpos = _endpos__6_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1827 "parsing/parser.mly" +# 1832 "parsing/parser.mly" ( let docs = symbol_docs _sloc in mkcf ~loc:_sloc (Pcf_inherit (_2, _4, self)) ~attrs:(_3@_6) ~docs ) -# 3697 "parsing/parser.ml" +# 3702 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3734,9 +3739,9 @@ module Tables = struct let _v : (Parsetree.class_field) = let _3 = let _1 = _1_inlined1 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 3740 "parsing/parser.ml" +# 3745 "parsing/parser.ml" in let _endpos__3_ = _endpos__1_inlined1_ in @@ -3744,11 +3749,11 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1830 "parsing/parser.mly" +# 1835 "parsing/parser.mly" ( let v, attrs = _2 in let docs = symbol_docs _sloc in mkcf ~loc:_sloc (Pcf_val v) ~attrs:(attrs@_3) ~docs ) -# 3752 "parsing/parser.ml" +# 3757 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3789,9 +3794,9 @@ module Tables = struct let _v : (Parsetree.class_field) = let _3 = let _1 = _1_inlined1 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 3795 "parsing/parser.ml" +# 3800 "parsing/parser.ml" in let _endpos__3_ = _endpos__1_inlined1_ in @@ -3799,11 +3804,11 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1834 "parsing/parser.mly" +# 1839 "parsing/parser.mly" ( let meth, attrs = _2 in let docs = symbol_docs _sloc in mkcf ~loc:_sloc (Pcf_method meth) ~attrs:(attrs@_3) ~docs ) -# 3807 "parsing/parser.ml" +# 3812 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3849,28 +3854,28 @@ module Tables = struct let _v : (Parsetree.class_field) = let _4 = let _1 = _1_inlined2 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 3855 "parsing/parser.ml" +# 3860 "parsing/parser.ml" in let _endpos__4_ = _endpos__1_inlined2_ in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 3864 "parsing/parser.ml" +# 3869 "parsing/parser.ml" in let _endpos = _endpos__4_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1838 "parsing/parser.mly" +# 1843 "parsing/parser.mly" ( let docs = symbol_docs _sloc in mkcf ~loc:_sloc (Pcf_constraint _3) ~attrs:(_2@_4) ~docs ) -# 3874 "parsing/parser.ml" +# 3879 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3916,28 +3921,28 @@ module Tables = struct let _v : (Parsetree.class_field) = let _4 = let _1 = _1_inlined2 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 3922 "parsing/parser.ml" +# 3927 "parsing/parser.ml" in let _endpos__4_ = _endpos__1_inlined2_ in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 3931 "parsing/parser.ml" +# 3936 "parsing/parser.ml" in let _endpos = _endpos__4_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1841 "parsing/parser.mly" +# 1846 "parsing/parser.mly" ( let docs = symbol_docs _sloc in mkcf ~loc:_sloc (Pcf_initializer _3) ~attrs:(_2@_4) ~docs ) -# 3941 "parsing/parser.ml" +# 3946 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -3969,9 +3974,9 @@ module Tables = struct let _v : (Parsetree.class_field) = let _2 = let _1 = _1_inlined1 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 3975 "parsing/parser.ml" +# 3980 "parsing/parser.ml" in let _endpos__2_ = _endpos__1_inlined1_ in @@ -3979,10 +3984,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1844 "parsing/parser.mly" +# 1849 "parsing/parser.mly" ( let docs = symbol_docs _sloc in mkcf ~loc:_sloc (Pcf_extension _1) ~attrs:_2 ~docs ) -# 3986 "parsing/parser.ml" +# 3991 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4006,23 +4011,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.class_field) = let _1 = let _1 = -# 1847 "parsing/parser.mly" +# 1852 "parsing/parser.mly" ( Pcf_attribute _1 ) -# 4012 "parsing/parser.ml" +# 4017 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 864 "parsing/parser.mly" +# 865 "parsing/parser.mly" ( mkcf ~loc:_sloc _1 ) -# 4020 "parsing/parser.ml" +# 4025 "parsing/parser.ml" in -# 1848 "parsing/parser.mly" +# 1853 "parsing/parser.mly" ( _1 ) -# 4026 "parsing/parser.ml" +# 4031 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4052,9 +4057,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.class_expr) = -# 1742 "parsing/parser.mly" +# 1747 "parsing/parser.mly" ( _2 ) -# 4058 "parsing/parser.ml" +# 4063 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4099,24 +4104,24 @@ module Tables = struct let _endpos = _endpos__4_ in let _v : (Parsetree.class_expr) = let _1 = let _1 = -# 1745 "parsing/parser.mly" +# 1750 "parsing/parser.mly" ( Pcl_constraint(_4, _2) ) -# 4105 "parsing/parser.ml" +# 4110 "parsing/parser.ml" in let _endpos__1_ = _endpos__4_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 866 "parsing/parser.mly" +# 867 "parsing/parser.mly" ( mkclass ~loc:_sloc _1 ) -# 4114 "parsing/parser.ml" +# 4119 "parsing/parser.ml" in -# 1748 "parsing/parser.mly" +# 1753 "parsing/parser.mly" ( _1 ) -# 4120 "parsing/parser.ml" +# 4125 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4147,24 +4152,24 @@ module Tables = struct let _endpos = _endpos__2_ in let _v : (Parsetree.class_expr) = let _1 = let _1 = -# 1747 "parsing/parser.mly" +# 1752 "parsing/parser.mly" ( let (l,o,p) = _1 in Pcl_fun(l, o, p, _2) ) -# 4153 "parsing/parser.ml" +# 4158 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 866 "parsing/parser.mly" +# 867 "parsing/parser.mly" ( mkclass ~loc:_sloc _1 ) -# 4162 "parsing/parser.ml" +# 4167 "parsing/parser.ml" in -# 1748 "parsing/parser.mly" +# 1753 "parsing/parser.mly" ( _1 ) -# 4168 "parsing/parser.ml" +# 4173 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4202,24 +4207,24 @@ module Tables = struct let _endpos = _endpos_e_ in let _v : (Parsetree.class_expr) = let _1 = let _1 = -# 1803 "parsing/parser.mly" +# 1808 "parsing/parser.mly" ( let (l,o,p) = _1 in Pcl_fun(l, o, p, e) ) -# 4208 "parsing/parser.ml" +# 4213 "parsing/parser.ml" in let _endpos__1_ = _endpos_e_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 866 "parsing/parser.mly" +# 867 "parsing/parser.mly" ( mkclass ~loc:_sloc _1 ) -# 4217 "parsing/parser.ml" +# 4222 "parsing/parser.ml" in -# 1804 "parsing/parser.mly" +# 1809 "parsing/parser.mly" ( _1 ) -# 4223 "parsing/parser.ml" +# 4228 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4250,24 +4255,24 @@ module Tables = struct let _endpos = _endpos_e_ in let _v : (Parsetree.class_expr) = let _1 = let _1 = -# 1803 "parsing/parser.mly" +# 1808 "parsing/parser.mly" ( let (l,o,p) = _1 in Pcl_fun(l, o, p, e) ) -# 4256 "parsing/parser.ml" +# 4261 "parsing/parser.ml" in let _endpos__1_ = _endpos_e_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 866 "parsing/parser.mly" +# 867 "parsing/parser.mly" ( mkclass ~loc:_sloc _1 ) -# 4265 "parsing/parser.ml" +# 4270 "parsing/parser.ml" in -# 1804 "parsing/parser.mly" +# 1809 "parsing/parser.mly" ( _1 ) -# 4271 "parsing/parser.ml" +# 4276 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4290,9 +4295,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3530 "parsing/parser.mly" +# 3571 "parsing/parser.mly" ( _1 ) -# 4296 "parsing/parser.ml" +# 4301 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4332,9 +4337,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1812 "parsing/parser.mly" +# 1817 "parsing/parser.mly" ( reloc_pat ~loc:_sloc _2 ) -# 4338 "parsing/parser.ml" +# 4343 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4386,24 +4391,24 @@ module Tables = struct let _endpos = _endpos__5_ in let _v : (Parsetree.pattern) = let _1 = let _1 = -# 1814 "parsing/parser.mly" +# 1819 "parsing/parser.mly" ( Ppat_constraint(_2, _4) ) -# 4392 "parsing/parser.ml" +# 4397 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 4401 "parsing/parser.ml" +# 4406 "parsing/parser.ml" in -# 1815 "parsing/parser.mly" +# 1820 "parsing/parser.mly" ( _1 ) -# 4407 "parsing/parser.ml" +# 4412 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4422,9 +4427,9 @@ module Tables = struct let _symbolstartpos = _endpos in let _sloc = (_symbolstartpos, _endpos) in -# 1817 "parsing/parser.mly" +# 1822 "parsing/parser.mly" ( ghpat ~loc:_sloc Ppat_any ) -# 4428 "parsing/parser.ml" +# 4433 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4461,9 +4466,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.core_type) = -# 1942 "parsing/parser.mly" +# 1947 "parsing/parser.mly" ( _2 ) -# 4467 "parsing/parser.ml" +# 4472 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4480,24 +4485,24 @@ module Tables = struct let _endpos = _startpos in let _v : (Parsetree.core_type) = let _1 = let _1 = -# 1943 "parsing/parser.mly" +# 1948 "parsing/parser.mly" ( Ptyp_any ) -# 4486 "parsing/parser.ml" +# 4491 "parsing/parser.ml" in let _endpos__1_ = _endpos__0_ in let _endpos = _endpos__1_ in let _symbolstartpos = _endpos in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 4495 "parsing/parser.ml" +# 4500 "parsing/parser.ml" in -# 1944 "parsing/parser.mly" +# 1949 "parsing/parser.mly" ( _1 ) -# 4501 "parsing/parser.ml" +# 4506 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4543,28 +4548,28 @@ module Tables = struct let _v : (Parsetree.class_type_field) = let _4 = let _1 = _1_inlined2 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 4549 "parsing/parser.ml" +# 4554 "parsing/parser.ml" in let _endpos__4_ = _endpos__1_inlined2_ in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 4558 "parsing/parser.ml" +# 4563 "parsing/parser.ml" in let _endpos = _endpos__4_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1952 "parsing/parser.mly" +# 1957 "parsing/parser.mly" ( let docs = symbol_docs _sloc in mkctf ~loc:_sloc (Pctf_inherit _3) ~attrs:(_2@_4) ~docs ) -# 4568 "parsing/parser.ml" +# 4573 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4622,9 +4627,9 @@ module Tables = struct let ty : (Parsetree.core_type) = Obj.magic ty in let _3 : unit = Obj.magic _3 in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 4628 "parsing/parser.ml" +# 4633 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let flags : (Asttypes.mutable_flag * Asttypes.virtual_flag) = Obj.magic flags in let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in @@ -4635,9 +4640,9 @@ module Tables = struct let _v : (Parsetree.class_type_field) = let _4 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 4641 "parsing/parser.ml" +# 4646 "parsing/parser.ml" in let _endpos__4_ = _endpos__1_inlined3_ in @@ -4645,44 +4650,44 @@ module Tables = struct let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in let label = let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 4651 "parsing/parser.ml" +# 4656 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 4659 "parsing/parser.ml" +# 4664 "parsing/parser.ml" in -# 1977 "parsing/parser.mly" +# 1982 "parsing/parser.mly" ( let mut, virt = flags in label, mut, virt, ty ) -# 4668 "parsing/parser.ml" +# 4673 "parsing/parser.ml" in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 4676 "parsing/parser.ml" +# 4681 "parsing/parser.ml" in let _endpos = _endpos__4_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1955 "parsing/parser.mly" +# 1960 "parsing/parser.mly" ( let docs = symbol_docs _sloc in mkctf ~loc:_sloc (Pctf_val _3) ~attrs:(_2@_4) ~docs ) -# 4686 "parsing/parser.ml" +# 4691 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4740,9 +4745,9 @@ module Tables = struct let _1_inlined3 : (Parsetree.core_type) = Obj.magic _1_inlined3 in let _5 : unit = Obj.magic _5 in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 4746 "parsing/parser.ml" +# 4751 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let _3 : (Asttypes.private_flag * Asttypes.virtual_flag) = Obj.magic _3 in let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in @@ -4753,53 +4758,53 @@ module Tables = struct let _v : (Parsetree.class_type_field) = let _7 = let _1 = _1_inlined4 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 4759 "parsing/parser.ml" +# 4764 "parsing/parser.ml" in let _endpos__7_ = _endpos__1_inlined4_ in let _6 = let _1 = _1_inlined3 in -# 3175 "parsing/parser.mly" +# 3216 "parsing/parser.mly" ( _1 ) -# 4768 "parsing/parser.ml" +# 4773 "parsing/parser.ml" in let _4 = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 4776 "parsing/parser.ml" +# 4781 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 4784 "parsing/parser.ml" +# 4789 "parsing/parser.ml" in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 4792 "parsing/parser.ml" +# 4797 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1959 "parsing/parser.mly" +# 1964 "parsing/parser.mly" ( let (p, v) = _3 in let docs = symbol_docs _sloc in mkctf ~loc:_sloc (Pctf_method (_4, p, v, _6)) ~attrs:(_2@_7) ~docs ) -# 4803 "parsing/parser.ml" +# 4808 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4845,28 +4850,28 @@ module Tables = struct let _v : (Parsetree.class_type_field) = let _4 = let _1 = _1_inlined2 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 4851 "parsing/parser.ml" +# 4856 "parsing/parser.ml" in let _endpos__4_ = _endpos__1_inlined2_ in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 4860 "parsing/parser.ml" +# 4865 "parsing/parser.ml" in let _endpos = _endpos__4_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1963 "parsing/parser.mly" +# 1968 "parsing/parser.mly" ( let docs = symbol_docs _sloc in mkctf ~loc:_sloc (Pctf_constraint _3) ~attrs:(_2@_4) ~docs ) -# 4870 "parsing/parser.ml" +# 4875 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4898,9 +4903,9 @@ module Tables = struct let _v : (Parsetree.class_type_field) = let _2 = let _1 = _1_inlined1 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 4904 "parsing/parser.ml" +# 4909 "parsing/parser.ml" in let _endpos__2_ = _endpos__1_inlined1_ in @@ -4908,10 +4913,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1966 "parsing/parser.mly" +# 1971 "parsing/parser.mly" ( let docs = symbol_docs _sloc in mkctf ~loc:_sloc (Pctf_extension _1) ~attrs:_2 ~docs ) -# 4915 "parsing/parser.ml" +# 4920 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4935,23 +4940,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.class_type_field) = let _1 = let _1 = -# 1969 "parsing/parser.mly" +# 1974 "parsing/parser.mly" ( Pctf_attribute _1 ) -# 4941 "parsing/parser.ml" +# 4946 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 862 "parsing/parser.mly" +# 863 "parsing/parser.mly" ( mkctf ~loc:_sloc _1 ) -# 4949 "parsing/parser.ml" +# 4954 "parsing/parser.ml" in -# 1970 "parsing/parser.mly" +# 1975 "parsing/parser.mly" ( _1 ) -# 4955 "parsing/parser.ml" +# 4960 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -4980,42 +4985,42 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 4986 "parsing/parser.ml" +# 4991 "parsing/parser.ml" in let tys = let tys = -# 1928 "parsing/parser.mly" +# 1933 "parsing/parser.mly" ( [] ) -# 4993 "parsing/parser.ml" +# 4998 "parsing/parser.ml" in -# 1934 "parsing/parser.mly" +# 1939 "parsing/parser.mly" ( tys ) -# 4998 "parsing/parser.ml" +# 5003 "parsing/parser.ml" in -# 1911 "parsing/parser.mly" +# 1916 "parsing/parser.mly" ( Pcty_constr (cid, tys) ) -# 5004 "parsing/parser.ml" +# 5009 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 860 "parsing/parser.mly" +# 861 "parsing/parser.mly" ( mkcty ~loc:_sloc _1 ) -# 5013 "parsing/parser.ml" +# 5018 "parsing/parser.ml" in -# 1914 "parsing/parser.mly" +# 1919 "parsing/parser.mly" ( _1 ) -# 5019 "parsing/parser.ml" +# 5024 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -5066,9 +5071,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 5072 "parsing/parser.ml" +# 5077 "parsing/parser.ml" in let tys = @@ -5077,30 +5082,30 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 5081 "parsing/parser.ml" +# 5086 "parsing/parser.ml" in -# 947 "parsing/parser.mly" +# 948 "parsing/parser.mly" ( xs ) -# 5086 "parsing/parser.ml" +# 5091 "parsing/parser.ml" in -# 1930 "parsing/parser.mly" +# 1935 "parsing/parser.mly" ( params ) -# 5092 "parsing/parser.ml" +# 5097 "parsing/parser.ml" in -# 1934 "parsing/parser.mly" +# 1939 "parsing/parser.mly" ( tys ) -# 5098 "parsing/parser.ml" +# 5103 "parsing/parser.ml" in -# 1911 "parsing/parser.mly" +# 1916 "parsing/parser.mly" ( Pcty_constr (cid, tys) ) -# 5104 "parsing/parser.ml" +# 5109 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined1_ in @@ -5108,15 +5113,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 860 "parsing/parser.mly" +# 861 "parsing/parser.mly" ( mkcty ~loc:_sloc _1 ) -# 5114 "parsing/parser.ml" +# 5119 "parsing/parser.ml" in -# 1914 "parsing/parser.mly" +# 1919 "parsing/parser.mly" ( _1 ) -# 5120 "parsing/parser.ml" +# 5125 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -5140,23 +5145,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.class_type) = let _1 = let _1 = -# 1913 "parsing/parser.mly" +# 1918 "parsing/parser.mly" ( Pcty_extension _1 ) -# 5146 "parsing/parser.ml" +# 5151 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 860 "parsing/parser.mly" +# 861 "parsing/parser.mly" ( mkcty ~loc:_sloc _1 ) -# 5154 "parsing/parser.ml" +# 5159 "parsing/parser.ml" in -# 1914 "parsing/parser.mly" +# 1919 "parsing/parser.mly" ( _1 ) -# 5160 "parsing/parser.ml" +# 5165 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -5213,44 +5218,44 @@ module Tables = struct let _1 = # 260 "<standard.mly>" ( List.flatten xss ) -# 5217 "parsing/parser.ml" +# 5222 "parsing/parser.ml" in -# 1948 "parsing/parser.mly" +# 1953 "parsing/parser.mly" ( _1 ) -# 5222 "parsing/parser.ml" +# 5227 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 808 "parsing/parser.mly" +# 809 "parsing/parser.mly" ( extra_csig _startpos _endpos _1 ) -# 5231 "parsing/parser.ml" +# 5236 "parsing/parser.ml" in -# 1938 "parsing/parser.mly" +# 1943 "parsing/parser.mly" ( Csig.mk _1 _2 ) -# 5237 "parsing/parser.ml" +# 5242 "parsing/parser.ml" in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 5245 "parsing/parser.ml" +# 5250 "parsing/parser.ml" in let _endpos = _endpos__4_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1916 "parsing/parser.mly" +# 1921 "parsing/parser.mly" ( mkcty ~loc:_sloc ~attrs:_2 (Pcty_signature _3) ) -# 5254 "parsing/parser.ml" +# 5259 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -5307,43 +5312,43 @@ module Tables = struct let _1 = # 260 "<standard.mly>" ( List.flatten xss ) -# 5311 "parsing/parser.ml" +# 5316 "parsing/parser.ml" in -# 1948 "parsing/parser.mly" +# 1953 "parsing/parser.mly" ( _1 ) -# 5316 "parsing/parser.ml" +# 5321 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 808 "parsing/parser.mly" +# 809 "parsing/parser.mly" ( extra_csig _startpos _endpos _1 ) -# 5325 "parsing/parser.ml" +# 5330 "parsing/parser.ml" in -# 1938 "parsing/parser.mly" +# 1943 "parsing/parser.mly" ( Csig.mk _1 _2 ) -# 5331 "parsing/parser.ml" +# 5336 "parsing/parser.ml" in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 5339 "parsing/parser.ml" +# 5344 "parsing/parser.ml" in let _loc__4_ = (_startpos__4_, _endpos__4_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1918 "parsing/parser.mly" +# 1923 "parsing/parser.mly" ( unclosed "object" _loc__1_ "end" _loc__4_ ) -# 5347 "parsing/parser.ml" +# 5352 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -5373,9 +5378,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.class_type) = -# 1920 "parsing/parser.mly" +# 1925 "parsing/parser.mly" ( Cty.attr _1 _2 ) -# 5379 "parsing/parser.ml" +# 5384 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -5438,34 +5443,34 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 5444 "parsing/parser.ml" +# 5449 "parsing/parser.ml" in let _4 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 5452 "parsing/parser.ml" +# 5457 "parsing/parser.ml" in let _endpos__4_ = _endpos__1_inlined1_ in let _3 = -# 3644 "parsing/parser.mly" +# 3685 "parsing/parser.mly" ( Fresh ) -# 5459 "parsing/parser.ml" +# 5464 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1922 "parsing/parser.mly" +# 1927 "parsing/parser.mly" ( let loc = (_startpos__2_, _endpos__4_) in let od = Opn.mk ~override:_3 ~loc:(make_loc loc) _5 in mkcty ~loc:_sloc ~attrs:_4 (Pcty_open(od, _7)) ) -# 5469 "parsing/parser.ml" +# 5474 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -5535,37 +5540,37 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 5541 "parsing/parser.ml" +# 5546 "parsing/parser.ml" in let _4 = let _1 = _1_inlined2 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 5549 "parsing/parser.ml" +# 5554 "parsing/parser.ml" in let _endpos__4_ = _endpos__1_inlined2_ in let _3 = let _1 = _1_inlined1 in -# 3645 "parsing/parser.mly" +# 3686 "parsing/parser.mly" ( Override ) -# 5558 "parsing/parser.ml" +# 5563 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1922 "parsing/parser.mly" +# 1927 "parsing/parser.mly" ( let loc = (_startpos__2_, _endpos__4_) in let od = Opn.mk ~override:_3 ~loc:(make_loc loc) _5 in mkcty ~loc:_sloc ~attrs:_4 (Pcty_open(od, _7)) ) -# 5569 "parsing/parser.ml" +# 5574 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -5602,9 +5607,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.class_expr) = -# 1782 "parsing/parser.mly" +# 1787 "parsing/parser.mly" ( _2 ) -# 5608 "parsing/parser.ml" +# 5613 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -5643,9 +5648,9 @@ module Tables = struct let _v : (Parsetree.class_expr) = let _loc__3_ = (_startpos__3_, _endpos__3_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1784 "parsing/parser.mly" +# 1789 "parsing/parser.mly" ( unclosed "(" _loc__1_ ")" _loc__3_ ) -# 5649 "parsing/parser.ml" +# 5654 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -5674,42 +5679,42 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 5680 "parsing/parser.ml" +# 5685 "parsing/parser.ml" in let tys = let tys = -# 1928 "parsing/parser.mly" +# 1933 "parsing/parser.mly" ( [] ) -# 5687 "parsing/parser.ml" +# 5692 "parsing/parser.ml" in -# 1934 "parsing/parser.mly" +# 1939 "parsing/parser.mly" ( tys ) -# 5692 "parsing/parser.ml" +# 5697 "parsing/parser.ml" in -# 1787 "parsing/parser.mly" +# 1792 "parsing/parser.mly" ( Pcl_constr(cid, tys) ) -# 5698 "parsing/parser.ml" +# 5703 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 866 "parsing/parser.mly" +# 867 "parsing/parser.mly" ( mkclass ~loc:_sloc _1 ) -# 5707 "parsing/parser.ml" +# 5712 "parsing/parser.ml" in -# 1794 "parsing/parser.mly" +# 1799 "parsing/parser.mly" ( _1 ) -# 5713 "parsing/parser.ml" +# 5718 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -5760,9 +5765,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 5766 "parsing/parser.ml" +# 5771 "parsing/parser.ml" in let tys = @@ -5771,30 +5776,30 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 5775 "parsing/parser.ml" +# 5780 "parsing/parser.ml" in -# 947 "parsing/parser.mly" +# 948 "parsing/parser.mly" ( xs ) -# 5780 "parsing/parser.ml" +# 5785 "parsing/parser.ml" in -# 1930 "parsing/parser.mly" +# 1935 "parsing/parser.mly" ( params ) -# 5786 "parsing/parser.ml" +# 5791 "parsing/parser.ml" in -# 1934 "parsing/parser.mly" +# 1939 "parsing/parser.mly" ( tys ) -# 5792 "parsing/parser.ml" +# 5797 "parsing/parser.ml" in -# 1787 "parsing/parser.mly" +# 1792 "parsing/parser.mly" ( Pcl_constr(cid, tys) ) -# 5798 "parsing/parser.ml" +# 5803 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined1_ in @@ -5802,15 +5807,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 866 "parsing/parser.mly" +# 867 "parsing/parser.mly" ( mkclass ~loc:_sloc _1 ) -# 5808 "parsing/parser.ml" +# 5813 "parsing/parser.ml" in -# 1794 "parsing/parser.mly" +# 1799 "parsing/parser.mly" ( _1 ) -# 5814 "parsing/parser.ml" +# 5819 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -5869,43 +5874,43 @@ module Tables = struct let _1 = # 260 "<standard.mly>" ( List.flatten xss ) -# 5873 "parsing/parser.ml" +# 5878 "parsing/parser.ml" in -# 1821 "parsing/parser.mly" +# 1826 "parsing/parser.mly" ( _1 ) -# 5878 "parsing/parser.ml" +# 5883 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 807 "parsing/parser.mly" +# 808 "parsing/parser.mly" ( extra_cstr _startpos _endpos _1 ) -# 5887 "parsing/parser.ml" +# 5892 "parsing/parser.ml" in -# 1808 "parsing/parser.mly" +# 1813 "parsing/parser.mly" ( Cstr.mk _1 _2 ) -# 5893 "parsing/parser.ml" +# 5898 "parsing/parser.ml" in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 5901 "parsing/parser.ml" +# 5906 "parsing/parser.ml" in let _loc__4_ = (_startpos__4_, _endpos__4_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1789 "parsing/parser.mly" +# 1794 "parsing/parser.mly" ( unclosed "object" _loc__1_ "end" _loc__4_ ) -# 5909 "parsing/parser.ml" +# 5914 "parsing/parser.ml" in let _endpos__1_ = _endpos__4_ in @@ -5913,15 +5918,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 866 "parsing/parser.mly" +# 867 "parsing/parser.mly" ( mkclass ~loc:_sloc _1 ) -# 5919 "parsing/parser.ml" +# 5924 "parsing/parser.ml" in -# 1794 "parsing/parser.mly" +# 1799 "parsing/parser.mly" ( _1 ) -# 5925 "parsing/parser.ml" +# 5930 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -5973,24 +5978,24 @@ module Tables = struct let _endpos = _endpos__5_ in let _v : (Parsetree.class_expr) = let _1 = let _1 = -# 1791 "parsing/parser.mly" +# 1796 "parsing/parser.mly" ( Pcl_constraint(_2, _4) ) -# 5979 "parsing/parser.ml" +# 5984 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 866 "parsing/parser.mly" +# 867 "parsing/parser.mly" ( mkclass ~loc:_sloc _1 ) -# 5988 "parsing/parser.ml" +# 5993 "parsing/parser.ml" in -# 1794 "parsing/parser.mly" +# 1799 "parsing/parser.mly" ( _1 ) -# 5994 "parsing/parser.ml" +# 5999 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6045,9 +6050,9 @@ module Tables = struct let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1793 "parsing/parser.mly" +# 1798 "parsing/parser.mly" ( unclosed "(" _loc__1_ ")" _loc__5_ ) -# 6051 "parsing/parser.ml" +# 6056 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -6055,15 +6060,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 866 "parsing/parser.mly" +# 867 "parsing/parser.mly" ( mkclass ~loc:_sloc _1 ) -# 6061 "parsing/parser.ml" +# 6066 "parsing/parser.ml" in -# 1794 "parsing/parser.mly" +# 1799 "parsing/parser.mly" ( _1 ) -# 6067 "parsing/parser.ml" +# 6072 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6120,44 +6125,44 @@ module Tables = struct let _1 = # 260 "<standard.mly>" ( List.flatten xss ) -# 6124 "parsing/parser.ml" +# 6129 "parsing/parser.ml" in -# 1821 "parsing/parser.mly" +# 1826 "parsing/parser.mly" ( _1 ) -# 6129 "parsing/parser.ml" +# 6134 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 807 "parsing/parser.mly" +# 808 "parsing/parser.mly" ( extra_cstr _startpos _endpos _1 ) -# 6138 "parsing/parser.ml" +# 6143 "parsing/parser.ml" in -# 1808 "parsing/parser.mly" +# 1813 "parsing/parser.mly" ( Cstr.mk _1 _2 ) -# 6144 "parsing/parser.ml" +# 6149 "parsing/parser.ml" in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 6152 "parsing/parser.ml" +# 6157 "parsing/parser.ml" in let _endpos = _endpos__4_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1796 "parsing/parser.mly" +# 1801 "parsing/parser.mly" ( mkclass ~loc:_sloc ~attrs:_2 (Pcl_structure _3) ) -# 6161 "parsing/parser.ml" +# 6166 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6180,9 +6185,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.class_type) = -# 1899 "parsing/parser.mly" +# 1904 "parsing/parser.mly" ( _1 ) -# 6186 "parsing/parser.ml" +# 6191 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6228,14 +6233,14 @@ module Tables = struct let _v : (Parsetree.class_type) = let _1 = let _1 = let label = -# 3238 "parsing/parser.mly" +# 3279 "parsing/parser.mly" ( Optional label ) -# 6234 "parsing/parser.ml" +# 6239 "parsing/parser.ml" in -# 1905 "parsing/parser.mly" +# 1910 "parsing/parser.mly" ( Pcty_arrow(label, domain, codomain) ) -# 6239 "parsing/parser.ml" +# 6244 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_codomain_, _startpos_label_) in @@ -6243,15 +6248,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 860 "parsing/parser.mly" +# 861 "parsing/parser.mly" ( mkcty ~loc:_sloc _1 ) -# 6249 "parsing/parser.ml" +# 6254 "parsing/parser.ml" in -# 1906 "parsing/parser.mly" +# 1911 "parsing/parser.mly" ( _1 ) -# 6255 "parsing/parser.ml" +# 6260 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6298,9 +6303,9 @@ module Tables = struct let domain : (Parsetree.core_type) = Obj.magic domain in let _2 : unit = Obj.magic _2 in let label : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 6304 "parsing/parser.ml" +# 6309 "parsing/parser.ml" ) = Obj.magic label in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos_label_ in @@ -6308,14 +6313,14 @@ module Tables = struct let _v : (Parsetree.class_type) = let _1 = let _1 = let label = -# 3240 "parsing/parser.mly" +# 3281 "parsing/parser.mly" ( Labelled label ) -# 6314 "parsing/parser.ml" +# 6319 "parsing/parser.ml" in -# 1905 "parsing/parser.mly" +# 1910 "parsing/parser.mly" ( Pcty_arrow(label, domain, codomain) ) -# 6319 "parsing/parser.ml" +# 6324 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_codomain_, _startpos_label_) in @@ -6323,15 +6328,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 860 "parsing/parser.mly" +# 861 "parsing/parser.mly" ( mkcty ~loc:_sloc _1 ) -# 6329 "parsing/parser.ml" +# 6334 "parsing/parser.ml" in -# 1906 "parsing/parser.mly" +# 1911 "parsing/parser.mly" ( _1 ) -# 6335 "parsing/parser.ml" +# 6340 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6370,14 +6375,14 @@ module Tables = struct let _v : (Parsetree.class_type) = let _1 = let _1 = let label = -# 3242 "parsing/parser.mly" +# 3283 "parsing/parser.mly" ( Nolabel ) -# 6376 "parsing/parser.ml" +# 6381 "parsing/parser.ml" in -# 1905 "parsing/parser.mly" +# 1910 "parsing/parser.mly" ( Pcty_arrow(label, domain, codomain) ) -# 6381 "parsing/parser.ml" +# 6386 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_codomain_, _startpos_domain_) in @@ -6385,15 +6390,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 860 "parsing/parser.mly" +# 861 "parsing/parser.mly" ( mkcty ~loc:_sloc _1 ) -# 6391 "parsing/parser.ml" +# 6396 "parsing/parser.ml" in -# 1906 "parsing/parser.mly" +# 1911 "parsing/parser.mly" ( _1 ) -# 6397 "parsing/parser.ml" +# 6402 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6476,9 +6481,9 @@ module Tables = struct let csig : (Parsetree.class_type) = Obj.magic csig in let _8 : unit = Obj.magic _8 in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 6482 "parsing/parser.ml" +# 6487 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let params : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = Obj.magic params in let virt : (Asttypes.virtual_flag) = Obj.magic virt in @@ -6494,9 +6499,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 6500 "parsing/parser.ml" +# 6505 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -6506,24 +6511,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 6512 "parsing/parser.ml" +# 6517 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 6520 "parsing/parser.ml" +# 6525 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2044 "parsing/parser.mly" +# 2049 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in @@ -6531,19 +6536,19 @@ module Tables = struct ext, Ci.mk id csig ~virt ~params ~attrs ~loc ~docs ) -# 6535 "parsing/parser.ml" +# 6540 "parsing/parser.ml" in -# 1044 "parsing/parser.mly" +# 1045 "parsing/parser.mly" ( let (x, b) = a in x, b :: bs ) -# 6541 "parsing/parser.ml" +# 6546 "parsing/parser.ml" in -# 2032 "parsing/parser.mly" +# 2037 "parsing/parser.mly" ( _1 ) -# 6547 "parsing/parser.ml" +# 6552 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6566,9 +6571,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3527 "parsing/parser.mly" +# 3568 "parsing/parser.mly" ( _1 ) -# 6572 "parsing/parser.ml" +# 6577 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6587,17 +6592,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 633 "parsing/parser.mly" +# 634 "parsing/parser.mly" (string * char option) -# 6593 "parsing/parser.ml" +# 6598 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.constant) = -# 3410 "parsing/parser.mly" +# 3451 "parsing/parser.mly" ( let (n, m) = _1 in Pconst_integer (n, m) ) -# 6601 "parsing/parser.ml" +# 6606 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6618,15 +6623,15 @@ module Tables = struct let _1 : ( # 592 "parsing/parser.mly" (char) -# 6622 "parsing/parser.ml" +# 6627 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.constant) = -# 3411 "parsing/parser.mly" +# 3452 "parsing/parser.mly" ( Pconst_char _1 ) -# 6630 "parsing/parser.ml" +# 6635 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6645,17 +6650,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 685 "parsing/parser.mly" +# 686 "parsing/parser.mly" (string * Location.t * string option) -# 6651 "parsing/parser.ml" +# 6656 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.constant) = -# 3412 "parsing/parser.mly" +# 3453 "parsing/parser.mly" ( let (s, strloc, d) = _1 in Pconst_string (s, strloc, d) ) -# 6659 "parsing/parser.ml" +# 6664 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6674,17 +6679,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 612 "parsing/parser.mly" +# 613 "parsing/parser.mly" (string * char option) -# 6680 "parsing/parser.ml" +# 6685 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.constant) = -# 3413 "parsing/parser.mly" +# 3454 "parsing/parser.mly" ( let (f, m) = _1 in Pconst_float (f, m) ) -# 6688 "parsing/parser.ml" +# 6693 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6714,9 +6719,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.label) = -# 3484 "parsing/parser.mly" +# 3525 "parsing/parser.mly" ( "[]" ) -# 6720 "parsing/parser.ml" +# 6725 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6746,9 +6751,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.label) = -# 3485 "parsing/parser.mly" +# 3526 "parsing/parser.mly" ( "()" ) -# 6752 "parsing/parser.ml" +# 6757 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6771,9 +6776,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = -# 3486 "parsing/parser.mly" +# 3527 "parsing/parser.mly" ( "false" ) -# 6777 "parsing/parser.ml" +# 6782 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6796,9 +6801,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = -# 3487 "parsing/parser.mly" +# 3528 "parsing/parser.mly" ( "true" ) -# 6802 "parsing/parser.ml" +# 6807 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6817,17 +6822,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 697 "parsing/parser.mly" +# 698 "parsing/parser.mly" (string) -# 6823 "parsing/parser.ml" +# 6828 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = -# 3490 "parsing/parser.mly" +# 3531 "parsing/parser.mly" ( _1 ) -# 6831 "parsing/parser.ml" +# 6836 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6864,14 +6869,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Asttypes.label) = let _1 = -# 3481 "parsing/parser.mly" +# 3522 "parsing/parser.mly" ( "::" ) -# 6870 "parsing/parser.ml" +# 6875 "parsing/parser.ml" in -# 3491 "parsing/parser.mly" +# 3532 "parsing/parser.mly" ( _1 ) -# 6875 "parsing/parser.ml" +# 6880 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6894,9 +6899,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = -# 3492 "parsing/parser.mly" +# 3533 "parsing/parser.mly" ( _1 ) -# 6900 "parsing/parser.ml" +# 6905 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6919,9 +6924,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3495 "parsing/parser.mly" +# 3536 "parsing/parser.mly" ( _1 ) -# 6925 "parsing/parser.ml" +# 6930 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -6974,15 +6979,15 @@ module Tables = struct let _v : (Longident.t) = let _3 = let (_2, _1) = (_2_inlined1, _1_inlined1) in -# 3481 "parsing/parser.mly" +# 3522 "parsing/parser.mly" ( "::" ) -# 6980 "parsing/parser.ml" +# 6985 "parsing/parser.ml" in -# 3496 "parsing/parser.mly" +# 3537 "parsing/parser.mly" ( Ldot(_1,_3) ) -# 6986 "parsing/parser.ml" +# 6991 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7019,14 +7024,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Longident.t) = let _1 = -# 3481 "parsing/parser.mly" +# 3522 "parsing/parser.mly" ( "::" ) -# 7025 "parsing/parser.ml" +# 7030 "parsing/parser.ml" in -# 3497 "parsing/parser.mly" +# 3538 "parsing/parser.mly" ( Lident _1 ) -# 7030 "parsing/parser.ml" +# 7035 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7049,9 +7054,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3498 "parsing/parser.mly" +# 3539 "parsing/parser.mly" ( Lident _1 ) -# 7055 "parsing/parser.ml" +# 7060 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7088,9 +7093,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.core_type * Parsetree.core_type) = -# 1988 "parsing/parser.mly" +# 1993 "parsing/parser.mly" ( _1, _3 ) -# 7094 "parsing/parser.ml" +# 7099 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7115,26 +7120,26 @@ module Tables = struct let _v : (Parsetree.constructor_arguments) = let tys = let xs = let xs = -# 931 "parsing/parser.mly" +# 932 "parsing/parser.mly" ( [ x ] ) -# 7121 "parsing/parser.ml" +# 7126 "parsing/parser.ml" in # 253 "<standard.mly>" ( List.rev xs ) -# 7126 "parsing/parser.ml" +# 7131 "parsing/parser.ml" in -# 951 "parsing/parser.mly" +# 952 "parsing/parser.mly" ( xs ) -# 7132 "parsing/parser.ml" +# 7137 "parsing/parser.ml" in -# 3045 "parsing/parser.mly" +# 3086 "parsing/parser.mly" ( Pcstr_tuple tys ) -# 7138 "parsing/parser.ml" +# 7143 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7173,26 +7178,26 @@ module Tables = struct let _v : (Parsetree.constructor_arguments) = let tys = let xs = let xs = -# 935 "parsing/parser.mly" +# 936 "parsing/parser.mly" ( x :: xs ) -# 7179 "parsing/parser.ml" +# 7184 "parsing/parser.ml" in # 253 "<standard.mly>" ( List.rev xs ) -# 7184 "parsing/parser.ml" +# 7189 "parsing/parser.ml" in -# 951 "parsing/parser.mly" +# 952 "parsing/parser.mly" ( xs ) -# 7190 "parsing/parser.ml" +# 7195 "parsing/parser.ml" in -# 3045 "parsing/parser.mly" +# 3086 "parsing/parser.mly" ( Pcstr_tuple tys ) -# 7196 "parsing/parser.ml" +# 7201 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7229,9 +7234,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.constructor_arguments) = -# 3047 "parsing/parser.mly" +# 3088 "parsing/parser.mly" ( Pcstr_record _2 ) -# 7235 "parsing/parser.ml" +# 7240 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7254,9 +7259,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.constructor_declaration list) = -# 2966 "parsing/parser.mly" +# 2973 "parsing/parser.mly" ( [] ) -# 7260 "parsing/parser.ml" +# 7265 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7279,14 +7284,14 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_xs_ in let _v : (Parsetree.constructor_declaration list) = let cs = -# 1036 "parsing/parser.mly" +# 1037 "parsing/parser.mly" ( List.rev xs ) -# 7285 "parsing/parser.ml" +# 7290 "parsing/parser.ml" in -# 2968 "parsing/parser.mly" +# 2975 "parsing/parser.mly" ( cs ) -# 7290 "parsing/parser.ml" +# 7295 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7309,14 +7314,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.core_type) = let _1 = -# 3200 "parsing/parser.mly" +# 3241 "parsing/parser.mly" ( _1 ) -# 7315 "parsing/parser.ml" +# 7320 "parsing/parser.ml" in -# 3190 "parsing/parser.mly" +# 3231 "parsing/parser.mly" ( _1 ) -# 7320 "parsing/parser.ml" +# 7325 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7346,9 +7351,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.core_type) = -# 3192 "parsing/parser.mly" +# 3233 "parsing/parser.mly" ( Typ.attr _1 _2 ) -# 7352 "parsing/parser.ml" +# 7357 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7371,9 +7376,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.direction_flag) = -# 3589 "parsing/parser.mly" +# 3630 "parsing/parser.mly" ( Upto ) -# 7377 "parsing/parser.ml" +# 7382 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7396,9 +7401,413 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.direction_flag) = -# 3590 "parsing/parser.mly" +# 3631 "parsing/parser.mly" ( Downto ) -# 7402 "parsing/parser.ml" +# 7407 "parsing/parser.ml" + in + { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = Obj.repr _v; + MenhirLib.EngineTypes.startp = _startpos; + MenhirLib.EngineTypes.endp = _endpos; + MenhirLib.EngineTypes.next = _menhir_stack; + }); + (fun _menhir_env -> + let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in + let { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _4; + MenhirLib.EngineTypes.startp = _startpos__4_; + MenhirLib.EngineTypes.endp = _endpos__4_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _3; + MenhirLib.EngineTypes.startp = _startpos__3_; + MenhirLib.EngineTypes.endp = _endpos__3_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _2; + MenhirLib.EngineTypes.startp = _startpos__2_; + MenhirLib.EngineTypes.endp = _endpos__2_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = _1; + MenhirLib.EngineTypes.startp = _startpos__1_; + MenhirLib.EngineTypes.endp = _endpos__1_; + MenhirLib.EngineTypes.next = _menhir_stack; + }; + }; + }; + } = _menhir_stack in + let _4 : (Parsetree.core_type) = Obj.magic _4 in + let _3 : unit = Obj.magic _3 in + let _2 : (Parsetree.core_type list) = Obj.magic _2 in + let _1 : unit = Obj.magic _1 in + let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in + let _startpos = _startpos__1_ in + let _endpos = _endpos__4_ in + let _v : (Parsetree.core_type list * Parsetree.core_type) = +# 3048 "parsing/parser.mly" + ( (_2, _4) ) +# 7453 "parsing/parser.ml" + in + { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = Obj.repr _v; + MenhirLib.EngineTypes.startp = _startpos; + MenhirLib.EngineTypes.endp = _endpos; + MenhirLib.EngineTypes.next = _menhir_stack; + }); + (fun _menhir_env -> + let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in + let { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _2; + MenhirLib.EngineTypes.startp = _startpos__2_; + MenhirLib.EngineTypes.endp = _endpos__2_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = _1; + MenhirLib.EngineTypes.startp = _startpos__1_; + MenhirLib.EngineTypes.endp = _endpos__1_; + MenhirLib.EngineTypes.next = _menhir_stack; + }; + } = _menhir_stack in + let _2 : (Parsetree.core_type) = Obj.magic _2 in + let _1 : unit = Obj.magic _1 in + let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in + let _startpos = _startpos__1_ in + let _endpos = _endpos__2_ in + let _v : (Parsetree.core_type list * Parsetree.core_type) = +# 3050 "parsing/parser.mly" + ( ([], _2) ) +# 7485 "parsing/parser.ml" + in + { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = Obj.repr _v; + MenhirLib.EngineTypes.startp = _startpos; + MenhirLib.EngineTypes.endp = _endpos; + MenhirLib.EngineTypes.next = _menhir_stack; + }); + (fun _menhir_env -> + let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in + let { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _1_inlined2; + MenhirLib.EngineTypes.startp = _startpos__1_inlined2_; + MenhirLib.EngineTypes.endp = _endpos__1_inlined2_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = args_res; + MenhirLib.EngineTypes.startp = _startpos_args_res_; + MenhirLib.EngineTypes.endp = _endpos_args_res_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _1_inlined1; + MenhirLib.EngineTypes.startp = _startpos__1_inlined1_; + MenhirLib.EngineTypes.endp = _endpos__1_inlined1_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = _1; + MenhirLib.EngineTypes.startp = _startpos__1_; + MenhirLib.EngineTypes.endp = _endpos__1_; + MenhirLib.EngineTypes.next = _menhir_stack; + }; + }; + }; + } = _menhir_stack in + let _1_inlined2 : (Parsetree.attributes) = Obj.magic _1_inlined2 in + let args_res : (Parsetree.core_type list * Parsetree.core_type) = Obj.magic args_res in + let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in + let _1 : (Asttypes.label) = Obj.magic _1 in + let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in + let _startpos = _startpos__1_ in + let _endpos = _endpos__1_inlined2_ in + let _v : (Parsetree.effect_constructor) = let attrs2 = + let _1 = _1_inlined2 in + +# 3779 "parsing/parser.mly" + ( _1 ) +# 7533 "parsing/parser.ml" + + in + let _endpos_attrs2_ = _endpos__1_inlined2_ in + let attrs1 = + let _1 = _1_inlined1 in + +# 3783 "parsing/parser.mly" + ( _1 ) +# 7542 "parsing/parser.ml" + + in + let id = + let _endpos = _endpos__1_ in + let _symbolstartpos = _startpos__1_ in + let _sloc = (_symbolstartpos, _endpos) in + +# 814 "parsing/parser.mly" + ( mkrhs _1 _sloc ) +# 7552 "parsing/parser.ml" + + in + let _startpos_id_ = _startpos__1_ in + let _endpos = _endpos_attrs2_ in + let _symbolstartpos = _startpos_id_ in + let _sloc = (_symbolstartpos, _endpos) in + +# 3063 "parsing/parser.mly" + ( let args, res = args_res in + Te.effect_decl id res ~args ~loc:(make_loc _sloc) ~attrs:(attrs2@attrs1) + ) +# 7564 "parsing/parser.ml" + in + { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = Obj.repr _v; + MenhirLib.EngineTypes.startp = _startpos; + MenhirLib.EngineTypes.endp = _endpos; + MenhirLib.EngineTypes.next = _menhir_stack; + }); + (fun _menhir_env -> + let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in + let { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _1_inlined3; + MenhirLib.EngineTypes.startp = _startpos__1_inlined3_; + MenhirLib.EngineTypes.endp = _endpos__1_inlined3_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _1_inlined2; + MenhirLib.EngineTypes.startp = _startpos__1_inlined2_; + MenhirLib.EngineTypes.endp = _endpos__1_inlined2_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _3; + MenhirLib.EngineTypes.startp = _startpos__3_; + MenhirLib.EngineTypes.endp = _endpos__3_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _1_inlined1; + MenhirLib.EngineTypes.startp = _startpos__1_inlined1_; + MenhirLib.EngineTypes.endp = _endpos__1_inlined1_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = _1; + MenhirLib.EngineTypes.startp = _startpos__1_; + MenhirLib.EngineTypes.endp = _endpos__1_; + MenhirLib.EngineTypes.next = _menhir_stack; + }; + }; + }; + }; + } = _menhir_stack in + let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in + let _1_inlined2 : (Longident.t) = Obj.magic _1_inlined2 in + let _3 : unit = Obj.magic _3 in + let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in + let _1 : (Asttypes.label) = Obj.magic _1 in + let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in + let _startpos = _startpos__1_ in + let _endpos = _endpos__1_inlined3_ in + let _v : (Parsetree.effect_constructor) = let _5 = + let _1 = _1_inlined3 in + +# 3779 "parsing/parser.mly" + ( _1 ) +# 7619 "parsing/parser.ml" + + in + let _endpos__5_ = _endpos__1_inlined3_ in + let _4 = + let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in + let _endpos = _endpos__1_ in + let _symbolstartpos = _startpos__1_ in + let _sloc = (_symbolstartpos, _endpos) in + +# 814 "parsing/parser.mly" + ( mkrhs _1 _sloc ) +# 7631 "parsing/parser.ml" + + in + let _2 = + let _1 = _1_inlined1 in + +# 3783 "parsing/parser.mly" + ( _1 ) +# 7639 "parsing/parser.ml" + + in + let _1 = + let _endpos = _endpos__1_ in + let _symbolstartpos = _startpos__1_ in + let _sloc = (_symbolstartpos, _endpos) in + +# 814 "parsing/parser.mly" + ( mkrhs _1 _sloc ) +# 7649 "parsing/parser.ml" + + in + let _endpos = _endpos__5_ in + let _symbolstartpos = _startpos__1_ in + let _sloc = (_symbolstartpos, _endpos) in + +# 3070 "parsing/parser.mly" + ( Te.effect_rebind _1 _4 + ~loc:(make_loc _sloc) ~attrs:(_5 @ _2) ) +# 7659 "parsing/parser.ml" + in + { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = Obj.repr _v; + MenhirLib.EngineTypes.startp = _startpos; + MenhirLib.EngineTypes.endp = _endpos; + MenhirLib.EngineTypes.next = _menhir_stack; + }); + (fun _menhir_env -> + let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in + let { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = x; + MenhirLib.EngineTypes.startp = _startpos_x_; + MenhirLib.EngineTypes.endp = _endpos_x_; + MenhirLib.EngineTypes.next = _menhir_stack; + } = _menhir_stack in + let x : (Parsetree.core_type) = Obj.magic x in + let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in + let _startpos = _startpos_x_ in + let _endpos = _endpos_x_ in + let _v : (Parsetree.core_type list) = let _1 = + let xs = + let xs = +# 932 "parsing/parser.mly" + ( [ x ] ) +# 7686 "parsing/parser.ml" + in + +# 253 "<standard.mly>" + ( List.rev xs ) +# 7691 "parsing/parser.ml" + + in + +# 952 "parsing/parser.mly" + ( xs ) +# 7697 "parsing/parser.ml" + + in + +# 3043 "parsing/parser.mly" + ( _1 ) +# 7703 "parsing/parser.ml" + in + { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = Obj.repr _v; + MenhirLib.EngineTypes.startp = _startpos; + MenhirLib.EngineTypes.endp = _endpos; + MenhirLib.EngineTypes.next = _menhir_stack; + }); + (fun _menhir_env -> + let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in + let { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = x; + MenhirLib.EngineTypes.startp = _startpos_x_; + MenhirLib.EngineTypes.endp = _endpos_x_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _2; + MenhirLib.EngineTypes.startp = _startpos__2_; + MenhirLib.EngineTypes.endp = _endpos__2_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = xs; + MenhirLib.EngineTypes.startp = _startpos_xs_; + MenhirLib.EngineTypes.endp = _endpos_xs_; + MenhirLib.EngineTypes.next = _menhir_stack; + }; + }; + } = _menhir_stack in + let x : (Parsetree.core_type) = Obj.magic x in + let _2 : unit = Obj.magic _2 in + let xs : (Parsetree.core_type list) = Obj.magic xs in + let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in + let _startpos = _startpos_xs_ in + let _endpos = _endpos_x_ in + let _v : (Parsetree.core_type list) = let _1 = + let xs = + let xs = +# 936 "parsing/parser.mly" + ( x :: xs ) +# 7744 "parsing/parser.ml" + in + +# 253 "<standard.mly>" + ( List.rev xs ) +# 7749 "parsing/parser.ml" + + in + +# 952 "parsing/parser.mly" + ( xs ) +# 7755 "parsing/parser.ml" + + in + +# 3043 "parsing/parser.mly" + ( _1 ) +# 7761 "parsing/parser.ml" + in + { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = Obj.repr _v; + MenhirLib.EngineTypes.startp = _startpos; + MenhirLib.EngineTypes.endp = _endpos; + MenhirLib.EngineTypes.next = _menhir_stack; + }); + (fun _menhir_env -> + let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in + let { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = _1; + MenhirLib.EngineTypes.startp = _startpos__1_; + MenhirLib.EngineTypes.endp = _endpos__1_; + MenhirLib.EngineTypes.next = _menhir_stack; + } = _menhir_stack in + let _1 : (Parsetree.effect_constructor) = Obj.magic _1 in + let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in + let _startpos = _startpos__1_ in + let _endpos = _endpos__1_ in + let _v : (Parsetree.effect_constructor) = +# 3054 "parsing/parser.mly" + ( _1 ) +# 7786 "parsing/parser.ml" + in + { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = Obj.repr _v; + MenhirLib.EngineTypes.startp = _startpos; + MenhirLib.EngineTypes.endp = _endpos; + MenhirLib.EngineTypes.next = _menhir_stack; + }); + (fun _menhir_env -> + let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in + let { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = _1; + MenhirLib.EngineTypes.startp = _startpos__1_; + MenhirLib.EngineTypes.endp = _endpos__1_; + MenhirLib.EngineTypes.next = _menhir_stack; + } = _menhir_stack in + let _1 : (Parsetree.effect_constructor) = Obj.magic _1 in + let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in + let _startpos = _startpos__1_ in + let _endpos = _endpos__1_ in + let _v : (Parsetree.effect_constructor) = +# 3055 "parsing/parser.mly" + ( _1 ) +# 7811 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7421,9 +7830,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.expression) = -# 2135 "parsing/parser.mly" +# 2140 "parsing/parser.mly" ( _1 ) -# 7427 "parsing/parser.ml" +# 7836 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7501,9 +7910,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 7507 "parsing/parser.ml" +# 7916 "parsing/parser.ml" in let _3 = @@ -7511,21 +7920,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 7517 "parsing/parser.ml" +# 7926 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 7523 "parsing/parser.ml" +# 7932 "parsing/parser.ml" in -# 2183 "parsing/parser.mly" +# 2188 "parsing/parser.mly" ( Pexp_letmodule(_4, _5, _7), _3 ) -# 7529 "parsing/parser.ml" +# 7938 "parsing/parser.ml" in let _endpos__1_ = _endpos__7_ in @@ -7533,10 +7942,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 7540 "parsing/parser.ml" +# 7949 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7620,9 +8029,9 @@ module Tables = struct let _3 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 7626 "parsing/parser.ml" +# 8035 "parsing/parser.ml" in let _endpos__3_ = _endpos__1_inlined1_ in @@ -7631,19 +8040,19 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 7637 "parsing/parser.ml" +# 8046 "parsing/parser.ml" in let _endpos = _endpos__3_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3030 "parsing/parser.mly" +# 3037 "parsing/parser.mly" ( let args, res = _2 in Te.decl _1 ~args ?res ~attrs:_3 ~loc:(make_loc _sloc) ) -# 7647 "parsing/parser.ml" +# 8056 "parsing/parser.ml" in let _3 = @@ -7651,21 +8060,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 7657 "parsing/parser.ml" +# 8066 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 7663 "parsing/parser.ml" +# 8072 "parsing/parser.ml" in -# 2185 "parsing/parser.mly" +# 2190 "parsing/parser.mly" ( Pexp_letexception(_4, _6), _3 ) -# 7669 "parsing/parser.ml" +# 8078 "parsing/parser.ml" in let _endpos__1_ = _endpos__6_ in @@ -7673,10 +8082,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 7680 "parsing/parser.ml" +# 8089 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7746,28 +8155,28 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 7752 "parsing/parser.ml" +# 8161 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 7758 "parsing/parser.ml" +# 8167 "parsing/parser.ml" in let _3 = -# 3644 "parsing/parser.mly" +# 3685 "parsing/parser.mly" ( Fresh ) -# 7764 "parsing/parser.ml" +# 8173 "parsing/parser.ml" in -# 2187 "parsing/parser.mly" +# 2192 "parsing/parser.mly" ( let open_loc = make_loc (_startpos__2_, _endpos__5_) in let od = Opn.mk _5 ~override:_3 ~loc:open_loc in Pexp_open(od, _7), _4 ) -# 7771 "parsing/parser.ml" +# 8180 "parsing/parser.ml" in let _endpos__1_ = _endpos__7_ in @@ -7775,10 +8184,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 7782 "parsing/parser.ml" +# 8191 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7855,31 +8264,31 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 7861 "parsing/parser.ml" +# 8270 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 7867 "parsing/parser.ml" +# 8276 "parsing/parser.ml" in let _3 = let _1 = _1_inlined1 in -# 3645 "parsing/parser.mly" +# 3686 "parsing/parser.mly" ( Override ) -# 7875 "parsing/parser.ml" +# 8284 "parsing/parser.ml" in -# 2187 "parsing/parser.mly" +# 2192 "parsing/parser.mly" ( let open_loc = make_loc (_startpos__2_, _endpos__5_) in let od = Opn.mk _5 ~override:_3 ~loc:open_loc in Pexp_open(od, _7), _4 ) -# 7883 "parsing/parser.ml" +# 8292 "parsing/parser.ml" in let _endpos__1_ = _endpos__7_ in @@ -7887,10 +8296,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 7894 "parsing/parser.ml" +# 8303 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -7939,18 +8348,18 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 7943 "parsing/parser.ml" +# 8352 "parsing/parser.ml" in -# 1008 "parsing/parser.mly" +# 1009 "parsing/parser.mly" ( xs ) -# 7948 "parsing/parser.ml" +# 8357 "parsing/parser.ml" in -# 2519 "parsing/parser.mly" +# 2524 "parsing/parser.mly" ( xs ) -# 7954 "parsing/parser.ml" +# 8363 "parsing/parser.ml" in let _2 = @@ -7958,21 +8367,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 7964 "parsing/parser.ml" +# 8373 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 7970 "parsing/parser.ml" +# 8379 "parsing/parser.ml" in -# 2191 "parsing/parser.mly" +# 2196 "parsing/parser.mly" ( Pexp_function _3, _2 ) -# 7976 "parsing/parser.ml" +# 8385 "parsing/parser.ml" in let _endpos__1_ = _endpos_xs_ in @@ -7980,10 +8389,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 7987 "parsing/parser.ml" +# 8396 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -8039,22 +8448,22 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 8045 "parsing/parser.ml" +# 8454 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 8051 "parsing/parser.ml" +# 8460 "parsing/parser.ml" in -# 2193 "parsing/parser.mly" +# 2198 "parsing/parser.mly" ( let (l,o,p) = _3 in Pexp_fun(l, o, p, _4), _2 ) -# 8058 "parsing/parser.ml" +# 8467 "parsing/parser.ml" in let _endpos__1_ = _endpos__4_ in @@ -8062,10 +8471,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 8069 "parsing/parser.ml" +# 8478 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -8138,33 +8547,33 @@ module Tables = struct let _endpos = _endpos__7_ in let _v : (Parsetree.expression) = let _1 = let _5 = -# 2414 "parsing/parser.mly" +# 2419 "parsing/parser.mly" ( xs ) -# 8144 "parsing/parser.ml" +# 8553 "parsing/parser.ml" in let _2 = let (_1_inlined1, _1) = (_1_inlined2, _1_inlined1) in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 8153 "parsing/parser.ml" +# 8562 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 8159 "parsing/parser.ml" +# 8568 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2196 "parsing/parser.mly" +# 2201 "parsing/parser.mly" ( (mk_newtypes ~loc:_sloc _5 _7).pexp_desc, _2 ) -# 8168 "parsing/parser.ml" +# 8577 "parsing/parser.ml" in let _endpos__1_ = _endpos__7_ in @@ -8172,10 +8581,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 8179 "parsing/parser.ml" +# 8588 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -8238,18 +8647,18 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 8242 "parsing/parser.ml" +# 8651 "parsing/parser.ml" in -# 1008 "parsing/parser.mly" +# 1009 "parsing/parser.mly" ( xs ) -# 8247 "parsing/parser.ml" +# 8656 "parsing/parser.ml" in -# 2519 "parsing/parser.mly" +# 2524 "parsing/parser.mly" ( xs ) -# 8253 "parsing/parser.ml" +# 8662 "parsing/parser.ml" in let _2 = @@ -8257,21 +8666,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 8263 "parsing/parser.ml" +# 8672 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 8269 "parsing/parser.ml" +# 8678 "parsing/parser.ml" in -# 2198 "parsing/parser.mly" +# 2203 "parsing/parser.mly" ( Pexp_match(_3, _5), _2 ) -# 8275 "parsing/parser.ml" +# 8684 "parsing/parser.ml" in let _endpos__1_ = _endpos_xs_ in @@ -8279,10 +8688,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 8286 "parsing/parser.ml" +# 8695 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -8345,18 +8754,18 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 8349 "parsing/parser.ml" +# 8758 "parsing/parser.ml" in -# 1008 "parsing/parser.mly" +# 1009 "parsing/parser.mly" ( xs ) -# 8354 "parsing/parser.ml" +# 8763 "parsing/parser.ml" in -# 2519 "parsing/parser.mly" +# 2524 "parsing/parser.mly" ( xs ) -# 8360 "parsing/parser.ml" +# 8769 "parsing/parser.ml" in let _2 = @@ -8364,21 +8773,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 8370 "parsing/parser.ml" +# 8779 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 8376 "parsing/parser.ml" +# 8785 "parsing/parser.ml" in -# 2200 "parsing/parser.mly" +# 2205 "parsing/parser.mly" ( Pexp_try(_3, _5), _2 ) -# 8382 "parsing/parser.ml" +# 8791 "parsing/parser.ml" in let _endpos__1_ = _endpos_xs_ in @@ -8386,10 +8795,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 8393 "parsing/parser.ml" +# 8802 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -8452,21 +8861,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 8458 "parsing/parser.ml" +# 8867 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 8464 "parsing/parser.ml" +# 8873 "parsing/parser.ml" in -# 2202 "parsing/parser.mly" +# 2207 "parsing/parser.mly" ( syntax_error() ) -# 8470 "parsing/parser.ml" +# 8879 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -8474,10 +8883,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 8481 "parsing/parser.ml" +# 8890 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -8554,21 +8963,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 8560 "parsing/parser.ml" +# 8969 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 8566 "parsing/parser.ml" +# 8975 "parsing/parser.ml" in -# 2204 "parsing/parser.mly" +# 2209 "parsing/parser.mly" ( Pexp_ifthenelse(_3, _5, Some _7), _2 ) -# 8572 "parsing/parser.ml" +# 8981 "parsing/parser.ml" in let _endpos__1_ = _endpos__7_ in @@ -8576,10 +8985,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 8583 "parsing/parser.ml" +# 8992 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -8642,21 +9051,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 8648 "parsing/parser.ml" +# 9057 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 8654 "parsing/parser.ml" +# 9063 "parsing/parser.ml" in -# 2206 "parsing/parser.mly" +# 2211 "parsing/parser.mly" ( Pexp_ifthenelse(_3, _5, None), _2 ) -# 8660 "parsing/parser.ml" +# 9069 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -8664,10 +9073,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 8671 "parsing/parser.ml" +# 9080 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -8737,21 +9146,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 8743 "parsing/parser.ml" +# 9152 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 8749 "parsing/parser.ml" +# 9158 "parsing/parser.ml" in -# 2208 "parsing/parser.mly" +# 2213 "parsing/parser.mly" ( Pexp_while(_3, _5), _2 ) -# 8755 "parsing/parser.ml" +# 9164 "parsing/parser.ml" in let _endpos__1_ = _endpos__6_ in @@ -8759,10 +9168,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 8766 "parsing/parser.ml" +# 9175 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -8860,21 +9269,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 8866 "parsing/parser.ml" +# 9275 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 8872 "parsing/parser.ml" +# 9281 "parsing/parser.ml" in -# 2211 "parsing/parser.mly" +# 2216 "parsing/parser.mly" ( Pexp_for(_3, _5, _7, _6, _9), _2 ) -# 8878 "parsing/parser.ml" +# 9287 "parsing/parser.ml" in let _endpos__1_ = _endpos__10_ in @@ -8882,10 +9291,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 8889 "parsing/parser.ml" +# 9298 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -8934,21 +9343,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 8940 "parsing/parser.ml" +# 9349 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 8946 "parsing/parser.ml" +# 9355 "parsing/parser.ml" in -# 2213 "parsing/parser.mly" +# 2218 "parsing/parser.mly" ( Pexp_assert _3, _2 ) -# 8952 "parsing/parser.ml" +# 9361 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -8956,10 +9365,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 8963 "parsing/parser.ml" +# 9372 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -9008,21 +9417,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 9014 "parsing/parser.ml" +# 9423 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 9020 "parsing/parser.ml" +# 9429 "parsing/parser.ml" in -# 2215 "parsing/parser.mly" +# 2220 "parsing/parser.mly" ( Pexp_lazy _3, _2 ) -# 9026 "parsing/parser.ml" +# 9435 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -9030,10 +9439,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 9037 "parsing/parser.ml" +# 9446 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -9098,27 +9507,27 @@ module Tables = struct let _1 = # 260 "<standard.mly>" ( List.flatten xss ) -# 9102 "parsing/parser.ml" +# 9511 "parsing/parser.ml" in -# 1821 "parsing/parser.mly" +# 1826 "parsing/parser.mly" ( _1 ) -# 9107 "parsing/parser.ml" +# 9516 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 807 "parsing/parser.mly" +# 808 "parsing/parser.mly" ( extra_cstr _startpos _endpos _1 ) -# 9116 "parsing/parser.ml" +# 9525 "parsing/parser.ml" in -# 1808 "parsing/parser.mly" +# 1813 "parsing/parser.mly" ( Cstr.mk _1 _2 ) -# 9122 "parsing/parser.ml" +# 9531 "parsing/parser.ml" in let _2 = @@ -9126,21 +9535,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 9132 "parsing/parser.ml" +# 9541 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 9138 "parsing/parser.ml" +# 9547 "parsing/parser.ml" in -# 2217 "parsing/parser.mly" +# 2222 "parsing/parser.mly" ( Pexp_object _3, _2 ) -# 9144 "parsing/parser.ml" +# 9553 "parsing/parser.ml" in let _endpos__1_ = _endpos__4_ in @@ -9148,10 +9557,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 9155 "parsing/parser.ml" +# 9564 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -9216,27 +9625,27 @@ module Tables = struct let _1 = # 260 "<standard.mly>" ( List.flatten xss ) -# 9220 "parsing/parser.ml" +# 9629 "parsing/parser.ml" in -# 1821 "parsing/parser.mly" +# 1826 "parsing/parser.mly" ( _1 ) -# 9225 "parsing/parser.ml" +# 9634 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 807 "parsing/parser.mly" +# 808 "parsing/parser.mly" ( extra_cstr _startpos _endpos _1 ) -# 9234 "parsing/parser.ml" +# 9643 "parsing/parser.ml" in -# 1808 "parsing/parser.mly" +# 1813 "parsing/parser.mly" ( Cstr.mk _1 _2 ) -# 9240 "parsing/parser.ml" +# 9649 "parsing/parser.ml" in let _2 = @@ -9244,23 +9653,23 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 9250 "parsing/parser.ml" +# 9659 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 9256 "parsing/parser.ml" +# 9665 "parsing/parser.ml" in let _loc__4_ = (_startpos__4_, _endpos__4_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2219 "parsing/parser.mly" +# 2224 "parsing/parser.mly" ( unclosed "object" _loc__1_ "end" _loc__4_ ) -# 9264 "parsing/parser.ml" +# 9673 "parsing/parser.ml" in let _endpos__1_ = _endpos__4_ in @@ -9268,10 +9677,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2137 "parsing/parser.mly" +# 2142 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 9275 "parsing/parser.ml" +# 9684 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -9306,18 +9715,18 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 9310 "parsing/parser.ml" +# 9719 "parsing/parser.ml" in -# 915 "parsing/parser.mly" +# 916 "parsing/parser.mly" ( xs ) -# 9315 "parsing/parser.ml" +# 9724 "parsing/parser.ml" in -# 2223 "parsing/parser.mly" +# 2228 "parsing/parser.mly" ( Pexp_apply(_1, _2) ) -# 9321 "parsing/parser.ml" +# 9730 "parsing/parser.ml" in let _endpos__1_ = _endpos_xs_ in @@ -9325,15 +9734,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 9331 "parsing/parser.ml" +# 9740 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 9337 "parsing/parser.ml" +# 9746 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -9362,24 +9771,24 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 9366 "parsing/parser.ml" +# 9775 "parsing/parser.ml" in -# 975 "parsing/parser.mly" +# 976 "parsing/parser.mly" ( xs ) -# 9371 "parsing/parser.ml" +# 9780 "parsing/parser.ml" in -# 2546 "parsing/parser.mly" +# 2551 "parsing/parser.mly" ( es ) -# 9377 "parsing/parser.ml" +# 9786 "parsing/parser.ml" in -# 2225 "parsing/parser.mly" +# 2230 "parsing/parser.mly" ( Pexp_tuple(_1) ) -# 9383 "parsing/parser.ml" +# 9792 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_xs_, _startpos_xs_) in @@ -9387,15 +9796,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 9393 "parsing/parser.ml" +# 9802 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 9399 "parsing/parser.ml" +# 9808 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -9431,15 +9840,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 9437 "parsing/parser.ml" +# 9846 "parsing/parser.ml" in -# 2227 "parsing/parser.mly" +# 2232 "parsing/parser.mly" ( Pexp_construct(_1, Some _2) ) -# 9443 "parsing/parser.ml" +# 9852 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in @@ -9447,15 +9856,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 9453 "parsing/parser.ml" +# 9862 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 9459 "parsing/parser.ml" +# 9868 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -9486,24 +9895,24 @@ module Tables = struct let _endpos = _endpos__2_ in let _v : (Parsetree.expression) = let _1 = let _1 = -# 2229 "parsing/parser.mly" +# 2234 "parsing/parser.mly" ( Pexp_variant(_1, Some _2) ) -# 9492 "parsing/parser.ml" +# 9901 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 9501 "parsing/parser.ml" +# 9910 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 9507 "parsing/parser.ml" +# 9916 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -9535,9 +9944,9 @@ module Tables = struct } = _menhir_stack in let e2 : (Parsetree.expression) = Obj.magic e2 in let op : ( -# 623 "parsing/parser.mly" +# 624 "parsing/parser.mly" (string) -# 9541 "parsing/parser.ml" +# 9950 "parsing/parser.ml" ) = Obj.magic op in let e1 : (Parsetree.expression) = Obj.magic e1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -9547,24 +9956,24 @@ module Tables = struct let _1 = let op = let _1 = -# 3454 "parsing/parser.mly" +# 3495 "parsing/parser.mly" ( op ) -# 9553 "parsing/parser.ml" +# 9962 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_op_, _startpos_op_) in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 9562 "parsing/parser.ml" +# 9971 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 9568 "parsing/parser.ml" +# 9977 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -9572,15 +9981,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 9578 "parsing/parser.ml" +# 9987 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 9584 "parsing/parser.ml" +# 9993 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -9612,9 +10021,9 @@ module Tables = struct } = _menhir_stack in let e2 : (Parsetree.expression) = Obj.magic e2 in let op : ( -# 624 "parsing/parser.mly" +# 625 "parsing/parser.mly" (string) -# 9618 "parsing/parser.ml" +# 10027 "parsing/parser.ml" ) = Obj.magic op in let e1 : (Parsetree.expression) = Obj.magic e1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -9624,24 +10033,24 @@ module Tables = struct let _1 = let op = let _1 = -# 3455 "parsing/parser.mly" +# 3496 "parsing/parser.mly" ( op ) -# 9630 "parsing/parser.ml" +# 10039 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_op_, _startpos_op_) in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 9639 "parsing/parser.ml" +# 10048 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 9645 "parsing/parser.ml" +# 10054 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -9649,15 +10058,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 9655 "parsing/parser.ml" +# 10064 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 9661 "parsing/parser.ml" +# 10070 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -9689,9 +10098,9 @@ module Tables = struct } = _menhir_stack in let e2 : (Parsetree.expression) = Obj.magic e2 in let op : ( -# 625 "parsing/parser.mly" +# 626 "parsing/parser.mly" (string) -# 9695 "parsing/parser.ml" +# 10104 "parsing/parser.ml" ) = Obj.magic op in let e1 : (Parsetree.expression) = Obj.magic e1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -9701,24 +10110,24 @@ module Tables = struct let _1 = let op = let _1 = -# 3456 "parsing/parser.mly" +# 3497 "parsing/parser.mly" ( op ) -# 9707 "parsing/parser.ml" +# 10116 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_op_, _startpos_op_) in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 9716 "parsing/parser.ml" +# 10125 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 9722 "parsing/parser.ml" +# 10131 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -9726,15 +10135,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 9732 "parsing/parser.ml" +# 10141 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 9738 "parsing/parser.ml" +# 10147 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -9766,9 +10175,9 @@ module Tables = struct } = _menhir_stack in let e2 : (Parsetree.expression) = Obj.magic e2 in let op : ( -# 626 "parsing/parser.mly" +# 627 "parsing/parser.mly" (string) -# 9772 "parsing/parser.ml" +# 10181 "parsing/parser.ml" ) = Obj.magic op in let e1 : (Parsetree.expression) = Obj.magic e1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -9778,24 +10187,24 @@ module Tables = struct let _1 = let op = let _1 = -# 3457 "parsing/parser.mly" +# 3498 "parsing/parser.mly" ( op ) -# 9784 "parsing/parser.ml" +# 10193 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_op_, _startpos_op_) in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 9793 "parsing/parser.ml" +# 10202 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 9799 "parsing/parser.ml" +# 10208 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -9803,15 +10212,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 9809 "parsing/parser.ml" +# 10218 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 9815 "parsing/parser.ml" +# 10224 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -9843,9 +10252,9 @@ module Tables = struct } = _menhir_stack in let e2 : (Parsetree.expression) = Obj.magic e2 in let op : ( -# 627 "parsing/parser.mly" +# 628 "parsing/parser.mly" (string) -# 9849 "parsing/parser.ml" +# 10258 "parsing/parser.ml" ) = Obj.magic op in let e1 : (Parsetree.expression) = Obj.magic e1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -9855,24 +10264,24 @@ module Tables = struct let _1 = let op = let _1 = -# 3458 "parsing/parser.mly" +# 3499 "parsing/parser.mly" ( op ) -# 9861 "parsing/parser.ml" +# 10270 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_op_, _startpos_op_) in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 9870 "parsing/parser.ml" +# 10279 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 9876 "parsing/parser.ml" +# 10285 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -9880,15 +10289,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 9886 "parsing/parser.ml" +# 10295 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 9892 "parsing/parser.ml" +# 10301 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -9928,23 +10337,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3459 "parsing/parser.mly" +# 3500 "parsing/parser.mly" ("+") -# 9934 "parsing/parser.ml" +# 10343 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 9942 "parsing/parser.ml" +# 10351 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 9948 "parsing/parser.ml" +# 10357 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -9952,15 +10361,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 9958 "parsing/parser.ml" +# 10367 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 9964 "parsing/parser.ml" +# 10373 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -10000,23 +10409,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3460 "parsing/parser.mly" +# 3501 "parsing/parser.mly" ("+.") -# 10006 "parsing/parser.ml" +# 10415 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 10014 "parsing/parser.ml" +# 10423 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 10020 "parsing/parser.ml" +# 10429 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -10024,15 +10433,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 10030 "parsing/parser.ml" +# 10439 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 10036 "parsing/parser.ml" +# 10445 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -10072,23 +10481,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3461 "parsing/parser.mly" +# 3502 "parsing/parser.mly" ("+=") -# 10078 "parsing/parser.ml" +# 10487 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 10086 "parsing/parser.ml" +# 10495 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 10092 "parsing/parser.ml" +# 10501 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -10096,15 +10505,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 10102 "parsing/parser.ml" +# 10511 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 10108 "parsing/parser.ml" +# 10517 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -10144,23 +10553,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3462 "parsing/parser.mly" +# 3503 "parsing/parser.mly" ("-") -# 10150 "parsing/parser.ml" +# 10559 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 10158 "parsing/parser.ml" +# 10567 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 10164 "parsing/parser.ml" +# 10573 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -10168,15 +10577,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 10174 "parsing/parser.ml" +# 10583 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 10180 "parsing/parser.ml" +# 10589 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -10216,23 +10625,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3463 "parsing/parser.mly" +# 3504 "parsing/parser.mly" ("-.") -# 10222 "parsing/parser.ml" +# 10631 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 10230 "parsing/parser.ml" +# 10639 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 10236 "parsing/parser.ml" +# 10645 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -10240,15 +10649,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 10246 "parsing/parser.ml" +# 10655 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 10252 "parsing/parser.ml" +# 10661 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -10288,23 +10697,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3464 "parsing/parser.mly" +# 3505 "parsing/parser.mly" ("*") -# 10294 "parsing/parser.ml" +# 10703 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 10302 "parsing/parser.ml" +# 10711 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 10308 "parsing/parser.ml" +# 10717 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -10312,15 +10721,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 10318 "parsing/parser.ml" +# 10727 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 10324 "parsing/parser.ml" +# 10733 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -10360,23 +10769,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3465 "parsing/parser.mly" +# 3506 "parsing/parser.mly" ("%") -# 10366 "parsing/parser.ml" +# 10775 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 10374 "parsing/parser.ml" +# 10783 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 10380 "parsing/parser.ml" +# 10789 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -10384,15 +10793,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 10390 "parsing/parser.ml" +# 10799 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 10396 "parsing/parser.ml" +# 10805 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -10432,23 +10841,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3466 "parsing/parser.mly" +# 3507 "parsing/parser.mly" ("=") -# 10438 "parsing/parser.ml" +# 10847 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 10446 "parsing/parser.ml" +# 10855 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 10452 "parsing/parser.ml" +# 10861 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -10456,15 +10865,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 10462 "parsing/parser.ml" +# 10871 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 10468 "parsing/parser.ml" +# 10877 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -10504,23 +10913,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3467 "parsing/parser.mly" +# 3508 "parsing/parser.mly" ("<") -# 10510 "parsing/parser.ml" +# 10919 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 10518 "parsing/parser.ml" +# 10927 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 10524 "parsing/parser.ml" +# 10933 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -10528,15 +10937,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 10534 "parsing/parser.ml" +# 10943 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 10540 "parsing/parser.ml" +# 10949 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -10576,23 +10985,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3468 "parsing/parser.mly" +# 3509 "parsing/parser.mly" (">") -# 10582 "parsing/parser.ml" +# 10991 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 10590 "parsing/parser.ml" +# 10999 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 10596 "parsing/parser.ml" +# 11005 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -10600,15 +11009,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 10606 "parsing/parser.ml" +# 11015 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 10612 "parsing/parser.ml" +# 11021 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -10648,23 +11057,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3469 "parsing/parser.mly" +# 3510 "parsing/parser.mly" ("or") -# 10654 "parsing/parser.ml" +# 11063 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 10662 "parsing/parser.ml" +# 11071 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 10668 "parsing/parser.ml" +# 11077 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -10672,15 +11081,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 10678 "parsing/parser.ml" +# 11087 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 10684 "parsing/parser.ml" +# 11093 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -10720,23 +11129,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3470 "parsing/parser.mly" +# 3511 "parsing/parser.mly" ("||") -# 10726 "parsing/parser.ml" +# 11135 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 10734 "parsing/parser.ml" +# 11143 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 10740 "parsing/parser.ml" +# 11149 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -10744,15 +11153,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 10750 "parsing/parser.ml" +# 11159 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 10756 "parsing/parser.ml" +# 11165 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -10792,23 +11201,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3471 "parsing/parser.mly" +# 3512 "parsing/parser.mly" ("&") -# 10798 "parsing/parser.ml" +# 11207 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 10806 "parsing/parser.ml" +# 11215 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 10812 "parsing/parser.ml" +# 11221 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -10816,15 +11225,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 10822 "parsing/parser.ml" +# 11231 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 10828 "parsing/parser.ml" +# 11237 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -10864,23 +11273,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3472 "parsing/parser.mly" +# 3513 "parsing/parser.mly" ("&&") -# 10870 "parsing/parser.ml" +# 11279 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 10878 "parsing/parser.ml" +# 11287 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 10884 "parsing/parser.ml" +# 11293 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -10888,15 +11297,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 10894 "parsing/parser.ml" +# 11303 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 10900 "parsing/parser.ml" +# 11309 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -10936,23 +11345,23 @@ module Tables = struct let _1 = let op = let _1 = -# 3473 "parsing/parser.mly" +# 3514 "parsing/parser.mly" (":=") -# 10942 "parsing/parser.ml" +# 11351 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 10950 "parsing/parser.ml" +# 11359 "parsing/parser.ml" in -# 2231 "parsing/parser.mly" +# 2236 "parsing/parser.mly" ( mkinfix e1 op e2 ) -# 10956 "parsing/parser.ml" +# 11365 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_e2_, _startpos_e1_) in @@ -10960,15 +11369,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 10966 "parsing/parser.ml" +# 11375 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 10972 "parsing/parser.ml" +# 11381 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11001,9 +11410,9 @@ module Tables = struct let _1 = let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2233 "parsing/parser.mly" +# 2238 "parsing/parser.mly" ( mkuminus ~oploc:_loc__1_ _1 _2 ) -# 11007 "parsing/parser.ml" +# 11416 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in @@ -11011,15 +11420,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 11017 "parsing/parser.ml" +# 11426 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 11023 "parsing/parser.ml" +# 11432 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11052,9 +11461,9 @@ module Tables = struct let _1 = let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2235 "parsing/parser.mly" +# 2240 "parsing/parser.mly" ( mkuplus ~oploc:_loc__1_ _1 _2 ) -# 11058 "parsing/parser.ml" +# 11467 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in @@ -11062,15 +11471,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 11068 "parsing/parser.ml" +# 11477 "parsing/parser.ml" in -# 2140 "parsing/parser.mly" +# 2145 "parsing/parser.mly" ( _1 ) -# 11074 "parsing/parser.ml" +# 11483 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11110,9 +11519,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2142 "parsing/parser.mly" +# 2147 "parsing/parser.mly" ( expr_of_let_bindings ~loc:_sloc _1 _3 ) -# 11116 "parsing/parser.ml" +# 11525 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11152,9 +11561,9 @@ module Tables = struct let _3 : unit = Obj.magic _3 in let bindings : (Parsetree.pattern * Parsetree.expression * Parsetree.binding_op list) = Obj.magic bindings in let _1 : ( -# 629 "parsing/parser.mly" +# 630 "parsing/parser.mly" (string) -# 11158 "parsing/parser.ml" +# 11567 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -11164,9 +11573,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 11170 "parsing/parser.ml" +# 11579 "parsing/parser.ml" in let _startpos_pbop_op_ = _startpos__1_ in @@ -11174,13 +11583,13 @@ module Tables = struct let _symbolstartpos = _startpos_pbop_op_ in let _sloc = (_symbolstartpos, _endpos) in -# 2144 "parsing/parser.mly" +# 2149 "parsing/parser.mly" ( let (pbop_pat, pbop_exp, rev_ands) = bindings in let ands = List.rev rev_ands in let pbop_loc = make_loc _sloc in let let_ = {pbop_op; pbop_pat; pbop_exp; pbop_loc} in mkexp ~loc:_sloc (Pexp_letop{ let_; ands; body}) ) -# 11184 "parsing/parser.ml" +# 11593 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11221,9 +11630,9 @@ module Tables = struct let _loc__2_ = (_startpos__2_, _endpos__2_) in let _sloc = (_symbolstartpos, _endpos) in -# 2150 "parsing/parser.mly" +# 2155 "parsing/parser.mly" ( mkexp_cons ~loc:_sloc _loc__2_ (ghexp ~loc:_sloc (Pexp_tuple[_1;_3])) ) -# 11227 "parsing/parser.ml" +# 11636 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11256,35 +11665,35 @@ module Tables = struct let _3 : (Parsetree.expression) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 11262 "parsing/parser.ml" +# 11671 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.expression) = let _1 = let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 11271 "parsing/parser.ml" +# 11680 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 11279 "parsing/parser.ml" +# 11688 "parsing/parser.ml" in let _endpos = _endpos__3_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2152 "parsing/parser.mly" +# 2157 "parsing/parser.mly" ( mkexp ~loc:_sloc (Pexp_setinstvar(_1, _3)) ) -# 11288 "parsing/parser.ml" +# 11697 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11340,18 +11749,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 11346 "parsing/parser.ml" +# 11755 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2154 "parsing/parser.mly" +# 2159 "parsing/parser.mly" ( mkexp ~loc:_sloc (Pexp_setfield(_1, _3, _5)) ) -# 11355 "parsing/parser.ml" +# 11764 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11419,9 +11828,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2156 "parsing/parser.mly" +# 2161 "parsing/parser.mly" ( array_set ~loc:_sloc _1 _4 _7 ) -# 11425 "parsing/parser.ml" +# 11834 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11489,9 +11898,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2158 "parsing/parser.mly" +# 2163 "parsing/parser.mly" ( string_set ~loc:_sloc _1 _4 _7 ) -# 11495 "parsing/parser.ml" +# 11904 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11559,9 +11968,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2160 "parsing/parser.mly" +# 2165 "parsing/parser.mly" ( bigarray_set ~loc:_sloc _1 _4 _7 ) -# 11565 "parsing/parser.ml" +# 11974 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11621,26 +12030,26 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _3 : unit = Obj.magic _3 in let _2 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 11627 "parsing/parser.ml" +# 12036 "parsing/parser.ml" ) = Obj.magic _2 in let _1 : (Parsetree.expression) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__7_ in let _v : (Parsetree.expression) = let _4 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 11636 "parsing/parser.ml" +# 12045 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2162 "parsing/parser.mly" +# 2167 "parsing/parser.mly" ( dotop_set ~loc:_sloc lident bracket _2 _1 _4 _7 ) -# 11644 "parsing/parser.ml" +# 12053 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11700,26 +12109,26 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _3 : unit = Obj.magic _3 in let _2 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 11706 "parsing/parser.ml" +# 12115 "parsing/parser.ml" ) = Obj.magic _2 in let _1 : (Parsetree.expression) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__7_ in let _v : (Parsetree.expression) = let _4 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 11715 "parsing/parser.ml" +# 12124 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2164 "parsing/parser.mly" +# 2169 "parsing/parser.mly" ( dotop_set ~loc:_sloc lident paren _2 _1 _4 _7 ) -# 11723 "parsing/parser.ml" +# 12132 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11779,26 +12188,26 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _3 : unit = Obj.magic _3 in let _2 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 11785 "parsing/parser.ml" +# 12194 "parsing/parser.ml" ) = Obj.magic _2 in let _1 : (Parsetree.expression) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__7_ in let _v : (Parsetree.expression) = let _4 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 11794 "parsing/parser.ml" +# 12203 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2166 "parsing/parser.mly" +# 2171 "parsing/parser.mly" ( dotop_set ~loc:_sloc lident brace _2 _1 _4 _7 ) -# 11802 "parsing/parser.ml" +# 12211 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11870,9 +12279,9 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _5 : unit = Obj.magic _5 in let _4 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 11876 "parsing/parser.ml" +# 12285 "parsing/parser.ml" ) = Obj.magic _4 in let _3 : (Longident.t) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in @@ -11881,17 +12290,17 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__9_ in let _v : (Parsetree.expression) = let _6 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 11887 "parsing/parser.ml" +# 12296 "parsing/parser.ml" in let _endpos = _endpos__9_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2169 "parsing/parser.mly" +# 2174 "parsing/parser.mly" ( dotop_set ~loc:_sloc (ldot _3) bracket _4 _1 _6 _9 ) -# 11895 "parsing/parser.ml" +# 12304 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -11963,9 +12372,9 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _5 : unit = Obj.magic _5 in let _4 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 11969 "parsing/parser.ml" +# 12378 "parsing/parser.ml" ) = Obj.magic _4 in let _3 : (Longident.t) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in @@ -11974,17 +12383,17 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__9_ in let _v : (Parsetree.expression) = let _6 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 11980 "parsing/parser.ml" +# 12389 "parsing/parser.ml" in let _endpos = _endpos__9_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2172 "parsing/parser.mly" +# 2177 "parsing/parser.mly" ( dotop_set ~loc:_sloc (ldot _3) paren _4 _1 _6 _9 ) -# 11988 "parsing/parser.ml" +# 12397 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12056,9 +12465,9 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _5 : unit = Obj.magic _5 in let _4 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 12062 "parsing/parser.ml" +# 12471 "parsing/parser.ml" ) = Obj.magic _4 in let _3 : (Longident.t) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in @@ -12067,17 +12476,17 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__9_ in let _v : (Parsetree.expression) = let _6 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 12073 "parsing/parser.ml" +# 12482 "parsing/parser.ml" in let _endpos = _endpos__9_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2175 "parsing/parser.mly" +# 2180 "parsing/parser.mly" ( dotop_set ~loc:_sloc (ldot _3) brace _4 _1 _6 _9 ) -# 12081 "parsing/parser.ml" +# 12490 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12107,9 +12516,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.expression) = -# 2177 "parsing/parser.mly" +# 2182 "parsing/parser.mly" ( Exp.attr _1 _2 ) -# 12113 "parsing/parser.ml" +# 12522 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12133,9 +12542,9 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.expression) = let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2179 "parsing/parser.mly" +# 2184 "parsing/parser.mly" ( not_expecting _loc__1_ "wildcard \"_\"" ) -# 12139 "parsing/parser.ml" +# 12548 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12151,9 +12560,9 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : (string Asttypes.loc option) = -# 3745 "parsing/parser.mly" +# 3786 "parsing/parser.mly" ( None ) -# 12157 "parsing/parser.ml" +# 12566 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12183,9 +12592,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (string Asttypes.loc option) = -# 3746 "parsing/parser.mly" +# 3787 "parsing/parser.mly" ( Some _2 ) -# 12189 "parsing/parser.ml" +# 12598 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12229,9 +12638,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__4_ in let _v : (Parsetree.extension) = -# 3756 "parsing/parser.mly" +# 3797 "parsing/parser.mly" ( (_2, _3) ) -# 12235 "parsing/parser.ml" +# 12644 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12250,9 +12659,9 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 687 "parsing/parser.mly" +# 688 "parsing/parser.mly" (string * Location.t * string * Location.t * string option) -# 12256 "parsing/parser.ml" +# 12665 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -12261,9 +12670,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3758 "parsing/parser.mly" +# 3799 "parsing/parser.mly" ( mk_quotedext ~loc:_sloc _1 ) -# 12267 "parsing/parser.ml" +# 12676 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12316,9 +12725,9 @@ module Tables = struct let _v : (Parsetree.extension_constructor) = let attrs = let _1 = _1_inlined3 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 12322 "parsing/parser.ml" +# 12731 "parsing/parser.ml" in let _endpos_attrs_ = _endpos__1_inlined3_ in @@ -12328,9 +12737,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 12334 "parsing/parser.ml" +# 12743 "parsing/parser.ml" in let cid = @@ -12339,19 +12748,19 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 12345 "parsing/parser.ml" +# 12754 "parsing/parser.ml" in let _endpos = _endpos_attrs_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3114 "parsing/parser.mly" +# 3155 "parsing/parser.mly" ( let info = symbol_info _endpos in Te.rebind cid lid ~attrs ~loc:(make_loc _sloc) ~info ) -# 12355 "parsing/parser.ml" +# 12764 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12397,9 +12806,9 @@ module Tables = struct let _v : (Parsetree.extension_constructor) = let attrs = let _1 = _1_inlined2 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 12403 "parsing/parser.ml" +# 12812 "parsing/parser.ml" in let _endpos_attrs_ = _endpos__1_inlined2_ in @@ -12409,9 +12818,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 12415 "parsing/parser.ml" +# 12824 "parsing/parser.ml" in let cid = @@ -12419,25 +12828,25 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 12425 "parsing/parser.ml" +# 12834 "parsing/parser.ml" in let _startpos_cid_ = _startpos__1_ in let _1 = -# 3565 "parsing/parser.mly" +# 3606 "parsing/parser.mly" ( () ) -# 12432 "parsing/parser.ml" +# 12841 "parsing/parser.ml" in let _endpos = _endpos_attrs_ in let _symbolstartpos = _startpos_cid_ in let _sloc = (_symbolstartpos, _endpos) in -# 3114 "parsing/parser.mly" +# 3155 "parsing/parser.mly" ( let info = symbol_info _endpos in Te.rebind cid lid ~attrs ~loc:(make_loc _sloc) ~info ) -# 12441 "parsing/parser.ml" +# 12850 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12484,10 +12893,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3733 "parsing/parser.mly" +# 3774 "parsing/parser.mly" ( mark_symbol_docs _sloc; Attr.mk ~loc:(make_loc _sloc) _2 _3 ) -# 12491 "parsing/parser.ml" +# 12900 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12503,14 +12912,14 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = let params = -# 1928 "parsing/parser.mly" +# 1933 "parsing/parser.mly" ( [] ) -# 12509 "parsing/parser.ml" +# 12918 "parsing/parser.ml" in -# 1753 "parsing/parser.mly" +# 1758 "parsing/parser.mly" ( params ) -# 12514 "parsing/parser.ml" +# 12923 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12551,24 +12960,24 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 12555 "parsing/parser.ml" +# 12964 "parsing/parser.ml" in -# 947 "parsing/parser.mly" +# 948 "parsing/parser.mly" ( xs ) -# 12560 "parsing/parser.ml" +# 12969 "parsing/parser.ml" in -# 1930 "parsing/parser.mly" +# 1935 "parsing/parser.mly" ( params ) -# 12566 "parsing/parser.ml" +# 12975 "parsing/parser.ml" in -# 1753 "parsing/parser.mly" +# 1758 "parsing/parser.mly" ( params ) -# 12572 "parsing/parser.ml" +# 12981 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12591,9 +13000,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.expression) = -# 2505 "parsing/parser.mly" +# 2510 "parsing/parser.mly" ( _1 ) -# 12597 "parsing/parser.ml" +# 13006 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12633,9 +13042,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2507 "parsing/parser.mly" +# 2512 "parsing/parser.mly" ( mkexp_constraint ~loc:_sloc _3 _1 ) -# 12639 "parsing/parser.ml" +# 13048 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12665,9 +13074,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.expression) = -# 2531 "parsing/parser.mly" +# 2536 "parsing/parser.mly" ( _2 ) -# 12671 "parsing/parser.ml" +# 13080 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12712,24 +13121,24 @@ module Tables = struct let _endpos = _endpos__4_ in let _v : (Parsetree.expression) = let _1 = let _1 = -# 2533 "parsing/parser.mly" +# 2538 "parsing/parser.mly" ( Pexp_constraint (_4, _2) ) -# 12718 "parsing/parser.ml" +# 13127 "parsing/parser.ml" in let _endpos__1_ = _endpos__4_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 12727 "parsing/parser.ml" +# 13136 "parsing/parser.ml" in -# 2534 "parsing/parser.mly" +# 2539 "parsing/parser.mly" ( _1 ) -# 12733 "parsing/parser.ml" +# 13142 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12762,12 +13171,12 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2537 "parsing/parser.mly" +# 2542 "parsing/parser.mly" ( let (l,o,p) = _1 in ghexp ~loc:_sloc (Pexp_fun(l, o, p, _2)) ) -# 12771 "parsing/parser.ml" +# 13180 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12818,17 +13227,17 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__5_ in let _v : (Parsetree.expression) = let _3 = -# 2414 "parsing/parser.mly" +# 2419 "parsing/parser.mly" ( xs ) -# 12824 "parsing/parser.ml" +# 13233 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2542 "parsing/parser.mly" +# 2547 "parsing/parser.mly" ( mk_newtypes ~loc:_sloc _3 _5 ) -# 12832 "parsing/parser.ml" +# 13241 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12851,9 +13260,9 @@ module Tables = struct let _startpos = _startpos_ty_ in let _endpos = _endpos_ty_ in let _v : (Parsetree.core_type) = -# 3226 "parsing/parser.mly" +# 3267 "parsing/parser.mly" ( ty ) -# 12857 "parsing/parser.ml" +# 13266 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12899,19 +13308,19 @@ module Tables = struct let _v : (Parsetree.core_type) = let _1 = let _1 = let domain = -# 811 "parsing/parser.mly" +# 812 "parsing/parser.mly" ( extra_rhs_core_type _1 ~pos:_endpos__1_ ) -# 12905 "parsing/parser.ml" +# 13314 "parsing/parser.ml" in let label = -# 3238 "parsing/parser.mly" +# 3279 "parsing/parser.mly" ( Optional label ) -# 12910 "parsing/parser.ml" +# 13319 "parsing/parser.ml" in -# 3232 "parsing/parser.mly" +# 3273 "parsing/parser.mly" ( Ptyp_arrow(label, domain, codomain) ) -# 12915 "parsing/parser.ml" +# 13324 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_codomain_, _startpos_label_) in @@ -12919,15 +13328,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 12925 "parsing/parser.ml" +# 13334 "parsing/parser.ml" in -# 3234 "parsing/parser.mly" +# 3275 "parsing/parser.mly" ( _1 ) -# 12931 "parsing/parser.ml" +# 13340 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -12974,9 +13383,9 @@ module Tables = struct let _1 : (Parsetree.core_type) = Obj.magic _1 in let _2 : unit = Obj.magic _2 in let label : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 12980 "parsing/parser.ml" +# 13389 "parsing/parser.ml" ) = Obj.magic label in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos_label_ in @@ -12984,19 +13393,19 @@ module Tables = struct let _v : (Parsetree.core_type) = let _1 = let _1 = let domain = -# 811 "parsing/parser.mly" +# 812 "parsing/parser.mly" ( extra_rhs_core_type _1 ~pos:_endpos__1_ ) -# 12990 "parsing/parser.ml" +# 13399 "parsing/parser.ml" in let label = -# 3240 "parsing/parser.mly" +# 3281 "parsing/parser.mly" ( Labelled label ) -# 12995 "parsing/parser.ml" +# 13404 "parsing/parser.ml" in -# 3232 "parsing/parser.mly" +# 3273 "parsing/parser.mly" ( Ptyp_arrow(label, domain, codomain) ) -# 13000 "parsing/parser.ml" +# 13409 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_codomain_, _startpos_label_) in @@ -13004,15 +13413,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 13010 "parsing/parser.ml" +# 13419 "parsing/parser.ml" in -# 3234 "parsing/parser.mly" +# 3275 "parsing/parser.mly" ( _1 ) -# 13016 "parsing/parser.ml" +# 13425 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -13051,19 +13460,19 @@ module Tables = struct let _v : (Parsetree.core_type) = let _1 = let _1 = let domain = -# 811 "parsing/parser.mly" +# 812 "parsing/parser.mly" ( extra_rhs_core_type _1 ~pos:_endpos__1_ ) -# 13057 "parsing/parser.ml" +# 13466 "parsing/parser.ml" in let label = -# 3242 "parsing/parser.mly" +# 3283 "parsing/parser.mly" ( Nolabel ) -# 13062 "parsing/parser.ml" +# 13471 "parsing/parser.ml" in -# 3232 "parsing/parser.mly" +# 3273 "parsing/parser.mly" ( Ptyp_arrow(label, domain, codomain) ) -# 13067 "parsing/parser.ml" +# 13476 "parsing/parser.ml" in let _endpos__1_ = _endpos_codomain_ in @@ -13071,15 +13480,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 13077 "parsing/parser.ml" +# 13486 "parsing/parser.ml" in -# 3234 "parsing/parser.mly" +# 3275 "parsing/parser.mly" ( _1 ) -# 13083 "parsing/parser.ml" +# 13492 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -13109,9 +13518,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.functor_parameter) = -# 1186 "parsing/parser.mly" +# 1187 "parsing/parser.mly" ( Unit ) -# 13115 "parsing/parser.ml" +# 13524 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -13167,15 +13576,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 13173 "parsing/parser.ml" +# 13582 "parsing/parser.ml" in -# 1189 "parsing/parser.mly" +# 1190 "parsing/parser.mly" ( Named (x, mty) ) -# 13179 "parsing/parser.ml" +# 13588 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -13191,9 +13600,9 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : (Parsetree.constructor_arguments * Parsetree.core_type option) = -# 3034 "parsing/parser.mly" +# 3075 "parsing/parser.mly" ( (Pcstr_tuple [],None) ) -# 13197 "parsing/parser.ml" +# 13606 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -13223,9 +13632,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.constructor_arguments * Parsetree.core_type option) = -# 3035 "parsing/parser.mly" +# 3076 "parsing/parser.mly" ( (_2,None) ) -# 13229 "parsing/parser.ml" +# 13638 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -13269,9 +13678,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__4_ in let _v : (Parsetree.constructor_arguments * Parsetree.core_type option) = -# 3037 "parsing/parser.mly" +# 3078 "parsing/parser.mly" ( (_2,Some _4) ) -# 13275 "parsing/parser.ml" +# 13684 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -13301,9 +13710,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.constructor_arguments * Parsetree.core_type option) = -# 3039 "parsing/parser.mly" +# 3080 "parsing/parser.mly" ( (Pcstr_tuple [],Some _2) ) -# 13307 "parsing/parser.ml" +# 13716 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -13351,9 +13760,9 @@ module Tables = struct Docstrings.info) = let attrs = let _1 = _1_inlined2 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 13357 "parsing/parser.ml" +# 13766 "parsing/parser.ml" in let _endpos_attrs_ = _endpos__1_inlined2_ in @@ -13363,23 +13772,23 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 13369 "parsing/parser.ml" +# 13778 "parsing/parser.ml" in let _endpos = _endpos_attrs_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2982 "parsing/parser.mly" +# 2989 "parsing/parser.mly" ( let args, res = args_res in let info = symbol_info _endpos in let loc = make_loc _sloc in cid, args, res, attrs, loc, info ) -# 13383 "parsing/parser.ml" +# 13792 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -13420,9 +13829,9 @@ module Tables = struct Docstrings.info) = let attrs = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 13426 "parsing/parser.ml" +# 13835 "parsing/parser.ml" in let _endpos_attrs_ = _endpos__1_inlined1_ in @@ -13431,29 +13840,29 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 13437 "parsing/parser.ml" +# 13846 "parsing/parser.ml" in let _startpos_cid_ = _startpos__1_ in let _1 = -# 3565 "parsing/parser.mly" +# 3606 "parsing/parser.mly" ( () ) -# 13444 "parsing/parser.ml" +# 13853 "parsing/parser.ml" in let _endpos = _endpos_attrs_ in let _symbolstartpos = _startpos_cid_ in let _sloc = (_symbolstartpos, _endpos) in -# 2982 "parsing/parser.mly" +# 2989 "parsing/parser.mly" ( let args, res = args_res in let info = symbol_info _endpos in let loc = make_loc _sloc in cid, args, res, attrs, loc, info ) -# 13457 "parsing/parser.ml" +# 13866 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -13524,9 +13933,9 @@ module Tables = struct let _2 : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = Obj.magic _2 in let _1_inlined3 : unit = Obj.magic _1_inlined3 in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 13530 "parsing/parser.ml" +# 13939 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let params : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = Obj.magic params in let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in @@ -13539,9 +13948,9 @@ module Tables = struct Parsetree.type_declaration) = let attrs2 = let _1 = _1_inlined4 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 13545 "parsing/parser.ml" +# 13954 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined4_ in @@ -13550,26 +13959,26 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 13554 "parsing/parser.ml" +# 13963 "parsing/parser.ml" in -# 897 "parsing/parser.mly" +# 898 "parsing/parser.mly" ( xs ) -# 13559 "parsing/parser.ml" +# 13968 "parsing/parser.ml" in -# 2887 "parsing/parser.mly" +# 2894 "parsing/parser.mly" ( _1 ) -# 13565 "parsing/parser.ml" +# 13974 "parsing/parser.ml" in let kind_priv_manifest = let _1 = _1_inlined3 in -# 2922 "parsing/parser.mly" +# 2929 "parsing/parser.mly" ( _2 ) -# 13573 "parsing/parser.ml" +# 13982 "parsing/parser.ml" in let id = @@ -13578,29 +13987,29 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 13584 "parsing/parser.ml" +# 13993 "parsing/parser.ml" in let flag = -# 3585 "parsing/parser.mly" +# 3626 "parsing/parser.mly" ( Recursive ) -# 13590 "parsing/parser.ml" +# 13999 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 13597 "parsing/parser.ml" +# 14006 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2859 "parsing/parser.mly" +# 2866 "parsing/parser.mly" ( let (kind, priv, manifest) = kind_priv_manifest in let docs = symbol_docs _sloc in @@ -13609,7 +14018,7 @@ module Tables = struct (flag, ext), Type.mk id ~params ~cstrs ~kind ~priv ?manifest ~attrs ~loc ~docs ) -# 13613 "parsing/parser.ml" +# 14022 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -13686,9 +14095,9 @@ module Tables = struct let _2 : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = Obj.magic _2 in let _1_inlined4 : unit = Obj.magic _1_inlined4 in let _1_inlined3 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 13692 "parsing/parser.ml" +# 14101 "parsing/parser.ml" ) = Obj.magic _1_inlined3 in let params : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = Obj.magic params in let _1_inlined2 : unit = Obj.magic _1_inlined2 in @@ -13702,9 +14111,9 @@ module Tables = struct Parsetree.type_declaration) = let attrs2 = let _1 = _1_inlined5 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 13708 "parsing/parser.ml" +# 14117 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined5_ in @@ -13713,26 +14122,26 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 13717 "parsing/parser.ml" +# 14126 "parsing/parser.ml" in -# 897 "parsing/parser.mly" +# 898 "parsing/parser.mly" ( xs ) -# 13722 "parsing/parser.ml" +# 14131 "parsing/parser.ml" in -# 2887 "parsing/parser.mly" +# 2894 "parsing/parser.mly" ( _1 ) -# 13728 "parsing/parser.ml" +# 14137 "parsing/parser.ml" in let kind_priv_manifest = let _1 = _1_inlined4 in -# 2922 "parsing/parser.mly" +# 2929 "parsing/parser.mly" ( _2 ) -# 13736 "parsing/parser.ml" +# 14145 "parsing/parser.ml" in let id = @@ -13741,9 +14150,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 13747 "parsing/parser.ml" +# 14156 "parsing/parser.ml" in let flag = @@ -13752,24 +14161,24 @@ module Tables = struct let _startpos = _startpos__1_ in let _loc = (_startpos, _endpos) in -# 3586 "parsing/parser.mly" +# 3627 "parsing/parser.mly" ( not_expecting _loc "nonrec flag" ) -# 13758 "parsing/parser.ml" +# 14167 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 13766 "parsing/parser.ml" +# 14175 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2859 "parsing/parser.mly" +# 2866 "parsing/parser.mly" ( let (kind, priv, manifest) = kind_priv_manifest in let docs = symbol_docs _sloc in @@ -13778,7 +14187,7 @@ module Tables = struct (flag, ext), Type.mk id ~params ~cstrs ~kind ~priv ?manifest ~attrs ~loc ~docs ) -# 13782 "parsing/parser.ml" +# 14191 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -13842,9 +14251,9 @@ module Tables = struct let xs : ((Parsetree.core_type * Parsetree.core_type * Ast_helper.loc) list) = Obj.magic xs in let kind_priv_manifest : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = Obj.magic kind_priv_manifest in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 13848 "parsing/parser.ml" +# 14257 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let params : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = Obj.magic params in let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in @@ -13857,9 +14266,9 @@ module Tables = struct Parsetree.type_declaration) = let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 13863 "parsing/parser.ml" +# 14272 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -13868,18 +14277,18 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 13872 "parsing/parser.ml" +# 14281 "parsing/parser.ml" in -# 897 "parsing/parser.mly" +# 898 "parsing/parser.mly" ( xs ) -# 13877 "parsing/parser.ml" +# 14286 "parsing/parser.ml" in -# 2887 "parsing/parser.mly" +# 2894 "parsing/parser.mly" ( _1 ) -# 13883 "parsing/parser.ml" +# 14292 "parsing/parser.ml" in let id = @@ -13888,29 +14297,29 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 13894 "parsing/parser.ml" +# 14303 "parsing/parser.ml" in let flag = -# 3581 "parsing/parser.mly" +# 3622 "parsing/parser.mly" ( Recursive ) -# 13900 "parsing/parser.ml" +# 14309 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 13907 "parsing/parser.ml" +# 14316 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2859 "parsing/parser.mly" +# 2866 "parsing/parser.mly" ( let (kind, priv, manifest) = kind_priv_manifest in let docs = symbol_docs _sloc in @@ -13919,7 +14328,7 @@ module Tables = struct (flag, ext), Type.mk id ~params ~cstrs ~kind ~priv ?manifest ~attrs ~loc ~docs ) -# 13923 "parsing/parser.ml" +# 14332 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -13989,9 +14398,9 @@ module Tables = struct let xs : ((Parsetree.core_type * Parsetree.core_type * Ast_helper.loc) list) = Obj.magic xs in let kind_priv_manifest : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = Obj.magic kind_priv_manifest in let _1_inlined3 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 13995 "parsing/parser.ml" +# 14404 "parsing/parser.ml" ) = Obj.magic _1_inlined3 in let params : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = Obj.magic params in let _1_inlined2 : unit = Obj.magic _1_inlined2 in @@ -14005,9 +14414,9 @@ module Tables = struct Parsetree.type_declaration) = let attrs2 = let _1 = _1_inlined4 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 14011 "parsing/parser.ml" +# 14420 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined4_ in @@ -14016,18 +14425,18 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 14020 "parsing/parser.ml" +# 14429 "parsing/parser.ml" in -# 897 "parsing/parser.mly" +# 898 "parsing/parser.mly" ( xs ) -# 14025 "parsing/parser.ml" +# 14434 "parsing/parser.ml" in -# 2887 "parsing/parser.mly" +# 2894 "parsing/parser.mly" ( _1 ) -# 14031 "parsing/parser.ml" +# 14440 "parsing/parser.ml" in let id = @@ -14036,32 +14445,32 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 14042 "parsing/parser.ml" +# 14451 "parsing/parser.ml" in let flag = let _1 = _1_inlined2 in -# 3582 "parsing/parser.mly" +# 3623 "parsing/parser.mly" ( Nonrecursive ) -# 14050 "parsing/parser.ml" +# 14459 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 14058 "parsing/parser.ml" +# 14467 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2859 "parsing/parser.mly" +# 2866 "parsing/parser.mly" ( let (kind, priv, manifest) = kind_priv_manifest in let docs = symbol_docs _sloc in @@ -14070,7 +14479,7 @@ module Tables = struct (flag, ext), Type.mk id ~params ~cstrs ~kind ~priv ?manifest ~attrs ~loc ~docs ) -# 14074 "parsing/parser.ml" +# 14483 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14089,17 +14498,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 697 "parsing/parser.mly" +# 698 "parsing/parser.mly" (string) -# 14095 "parsing/parser.ml" +# 14504 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = -# 3426 "parsing/parser.mly" +# 3467 "parsing/parser.mly" ( _1 ) -# 14103 "parsing/parser.ml" +# 14512 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14118,17 +14527,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 14124 "parsing/parser.ml" +# 14533 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = -# 3427 "parsing/parser.mly" +# 3468 "parsing/parser.mly" ( _1 ) -# 14132 "parsing/parser.ml" +# 14541 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14158,13 +14567,13 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : ( -# 777 "parsing/parser.mly" +# 778 "parsing/parser.mly" (Parsetree.structure) -# 14164 "parsing/parser.ml" +# 14573 "parsing/parser.ml" ) = -# 1068 "parsing/parser.mly" +# 1069 "parsing/parser.mly" ( _1 ) -# 14168 "parsing/parser.ml" +# 14577 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14180,9 +14589,9 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : (string) = -# 3476 "parsing/parser.mly" +# 3517 "parsing/parser.mly" ( "" ) -# 14186 "parsing/parser.ml" +# 14595 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14212,9 +14621,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (string) = -# 3477 "parsing/parser.mly" +# 3518 "parsing/parser.mly" ( ";.." ) -# 14218 "parsing/parser.ml" +# 14627 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14244,13 +14653,13 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : ( -# 779 "parsing/parser.mly" +# 780 "parsing/parser.mly" (Parsetree.signature) -# 14250 "parsing/parser.ml" +# 14659 "parsing/parser.ml" ) = -# 1074 "parsing/parser.mly" +# 1075 "parsing/parser.mly" ( _1 ) -# 14254 "parsing/parser.ml" +# 14663 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14294,9 +14703,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__4_ in let _v : (Parsetree.extension) = -# 3761 "parsing/parser.mly" +# 3802 "parsing/parser.mly" ( (_2, _3) ) -# 14300 "parsing/parser.ml" +# 14709 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14315,9 +14724,9 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 689 "parsing/parser.mly" +# 690 "parsing/parser.mly" (string * Location.t * string * Location.t * string option) -# 14321 "parsing/parser.ml" +# 14730 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -14326,9 +14735,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3763 "parsing/parser.mly" +# 3804 "parsing/parser.mly" ( mk_quotedext ~loc:_sloc _1 ) -# 14332 "parsing/parser.ml" +# 14741 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14374,9 +14783,9 @@ module Tables = struct let _1_inlined2 : (Parsetree.core_type) = Obj.magic _1_inlined2 in let _3 : unit = Obj.magic _3 in let _1_inlined1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 14380 "parsing/parser.ml" +# 14789 "parsing/parser.ml" ) = Obj.magic _1_inlined1 in let _1 : (Asttypes.mutable_flag) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -14385,34 +14794,34 @@ module Tables = struct let _v : (Parsetree.label_declaration) = let _5 = let _1 = _1_inlined3 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 14391 "parsing/parser.ml" +# 14800 "parsing/parser.ml" in let _endpos__5_ = _endpos__1_inlined3_ in let _4 = let _1 = _1_inlined2 in -# 3179 "parsing/parser.mly" +# 3220 "parsing/parser.mly" ( _1 ) -# 14400 "parsing/parser.ml" +# 14809 "parsing/parser.ml" in let _2 = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 14408 "parsing/parser.ml" +# 14817 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 14416 "parsing/parser.ml" +# 14825 "parsing/parser.ml" in let _startpos__2_ = _startpos__1_inlined1_ in @@ -14423,10 +14832,10 @@ module Tables = struct _startpos__2_ in let _sloc = (_symbolstartpos, _endpos) in -# 3056 "parsing/parser.mly" +# 3097 "parsing/parser.mly" ( let info = symbol_info _endpos in Type.field _2 _4 ~mut:_1 ~attrs:_5 ~loc:(make_loc _sloc) ~info ) -# 14430 "parsing/parser.ml" +# 14839 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14486,9 +14895,9 @@ module Tables = struct let _1_inlined2 : (Parsetree.core_type) = Obj.magic _1_inlined2 in let _3 : unit = Obj.magic _3 in let _1_inlined1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 14492 "parsing/parser.ml" +# 14901 "parsing/parser.ml" ) = Obj.magic _1_inlined1 in let _1 : (Asttypes.mutable_flag) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -14497,43 +14906,43 @@ module Tables = struct let _v : (Parsetree.label_declaration) = let _7 = let _1 = _1_inlined4 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 14503 "parsing/parser.ml" +# 14912 "parsing/parser.ml" in let _endpos__7_ = _endpos__1_inlined4_ in let _5 = let _1 = _1_inlined3 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 14512 "parsing/parser.ml" +# 14921 "parsing/parser.ml" in let _endpos__5_ = _endpos__1_inlined3_ in let _4 = let _1 = _1_inlined2 in -# 3179 "parsing/parser.mly" +# 3220 "parsing/parser.mly" ( _1 ) -# 14521 "parsing/parser.ml" +# 14930 "parsing/parser.ml" in let _2 = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 14529 "parsing/parser.ml" +# 14938 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 14537 "parsing/parser.ml" +# 14946 "parsing/parser.ml" in let _startpos__2_ = _startpos__1_inlined1_ in @@ -14544,14 +14953,14 @@ module Tables = struct _startpos__2_ in let _sloc = (_symbolstartpos, _endpos) in -# 3061 "parsing/parser.mly" +# 3102 "parsing/parser.mly" ( let info = match rhs_info _endpos__5_ with | Some _ as info_before_semi -> info_before_semi | None -> symbol_info _endpos in Type.field _2 _4 ~mut:_1 ~attrs:(_5 @ _7) ~loc:(make_loc _sloc) ~info ) -# 14555 "parsing/parser.ml" +# 14964 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14574,9 +14983,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.label_declaration list) = -# 3050 "parsing/parser.mly" +# 3091 "parsing/parser.mly" ( [_1] ) -# 14580 "parsing/parser.ml" +# 14989 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14599,9 +15008,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.label_declaration list) = -# 3051 "parsing/parser.mly" +# 3092 "parsing/parser.mly" ( [_1] ) -# 14605 "parsing/parser.ml" +# 15014 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14631,9 +15040,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.label_declaration list) = -# 3052 "parsing/parser.mly" +# 3093 "parsing/parser.mly" ( _1 :: _2 ) -# 14637 "parsing/parser.ml" +# 15046 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14652,9 +15061,9 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 14658 "parsing/parser.ml" +# 15067 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -14665,24 +15074,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 14671 "parsing/parser.ml" +# 15080 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2123 "parsing/parser.mly" +# 2128 "parsing/parser.mly" ( (_1.Location.txt, mkpat ~loc:_sloc (Ppat_var _1)) ) -# 14680 "parsing/parser.ml" +# 15089 "parsing/parser.ml" in -# 2115 "parsing/parser.mly" +# 2120 "parsing/parser.mly" ( x ) -# 14686 "parsing/parser.ml" +# 15095 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14715,9 +15124,9 @@ module Tables = struct let cty : (Parsetree.core_type) = Obj.magic cty in let _2 : unit = Obj.magic _2 in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 14721 "parsing/parser.ml" +# 15130 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -14728,18 +15137,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 14734 "parsing/parser.ml" +# 15143 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2123 "parsing/parser.mly" +# 2128 "parsing/parser.mly" ( (_1.Location.txt, mkpat ~loc:_sloc (Ppat_var _1)) ) -# 14743 "parsing/parser.ml" +# 15152 "parsing/parser.ml" in let _startpos_x_ = _startpos__1_ in @@ -14747,11 +15156,11 @@ module Tables = struct let _symbolstartpos = _startpos_x_ in let _sloc = (_symbolstartpos, _endpos) in -# 2117 "parsing/parser.mly" +# 2122 "parsing/parser.mly" ( let lab, pat = x in lab, mkpat ~loc:_sloc (Ppat_constraint (pat, cty)) ) -# 14755 "parsing/parser.ml" +# 15164 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14774,9 +15183,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3508 "parsing/parser.mly" +# 3549 "parsing/parser.mly" ( _1 ) -# 14780 "parsing/parser.ml" +# 15189 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14799,9 +15208,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.arg_label * Parsetree.expression) = -# 2400 "parsing/parser.mly" +# 2405 "parsing/parser.mly" ( (Nolabel, _1) ) -# 14805 "parsing/parser.ml" +# 15214 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14827,17 +15236,17 @@ module Tables = struct } = _menhir_stack in let _2 : (Parsetree.expression) = Obj.magic _2 in let _1 : ( -# 634 "parsing/parser.mly" +# 635 "parsing/parser.mly" (string) -# 14833 "parsing/parser.ml" +# 15242 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.arg_label * Parsetree.expression) = -# 2402 "parsing/parser.mly" +# 2407 "parsing/parser.mly" ( (Labelled _1, _2) ) -# 14841 "parsing/parser.ml" +# 15250 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14862,9 +15271,9 @@ module Tables = struct }; } = _menhir_stack in let label : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 14868 "parsing/parser.ml" +# 15277 "parsing/parser.ml" ) = Obj.magic label in let _1 : unit = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -14872,10 +15281,10 @@ module Tables = struct let _endpos = _endpos_label_ in let _v : (Asttypes.arg_label * Parsetree.expression) = let _loc_label_ = (_startpos_label_, _endpos_label_) in -# 2404 "parsing/parser.mly" +# 2409 "parsing/parser.mly" ( let loc = _loc_label_ in (Labelled label, mkexpvar ~loc label) ) -# 14879 "parsing/parser.ml" +# 15288 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14900,9 +15309,9 @@ module Tables = struct }; } = _menhir_stack in let label : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 14906 "parsing/parser.ml" +# 15315 "parsing/parser.ml" ) = Obj.magic label in let _1 : unit = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -14910,10 +15319,10 @@ module Tables = struct let _endpos = _endpos_label_ in let _v : (Asttypes.arg_label * Parsetree.expression) = let _loc_label_ = (_startpos_label_, _endpos_label_) in -# 2407 "parsing/parser.mly" +# 2412 "parsing/parser.mly" ( let loc = _loc_label_ in (Optional label, mkexpvar ~loc label) ) -# 14917 "parsing/parser.ml" +# 15326 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -14939,17 +15348,17 @@ module Tables = struct } = _menhir_stack in let _2 : (Parsetree.expression) = Obj.magic _2 in let _1 : ( -# 664 "parsing/parser.mly" +# 665 "parsing/parser.mly" (string) -# 14945 "parsing/parser.ml" +# 15354 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.arg_label * Parsetree.expression) = -# 2410 "parsing/parser.mly" +# 2415 "parsing/parser.mly" ( (Optional _1, _2) ) -# 14953 "parsing/parser.ml" +# 15362 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15002,15 +15411,15 @@ module Tables = struct let _v : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = let _4 = let _1 = _1_inlined1 in -# 2111 "parsing/parser.mly" +# 2116 "parsing/parser.mly" ( _1 ) -# 15008 "parsing/parser.ml" +# 15417 "parsing/parser.ml" in -# 2085 "parsing/parser.mly" +# 2090 "parsing/parser.mly" ( (Optional (fst _3), _4, snd _3) ) -# 15014 "parsing/parser.ml" +# 15423 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15035,9 +15444,9 @@ module Tables = struct }; } = _menhir_stack in let _1_inlined1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 15041 "parsing/parser.ml" +# 15450 "parsing/parser.ml" ) = Obj.magic _1_inlined1 in let _1 : unit = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -15050,24 +15459,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 15056 "parsing/parser.ml" +# 15465 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2123 "parsing/parser.mly" +# 2128 "parsing/parser.mly" ( (_1.Location.txt, mkpat ~loc:_sloc (Ppat_var _1)) ) -# 15065 "parsing/parser.ml" +# 15474 "parsing/parser.ml" in -# 2087 "parsing/parser.mly" +# 2092 "parsing/parser.mly" ( (Optional (fst _2), None, snd _2) ) -# 15071 "parsing/parser.ml" +# 15480 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15114,9 +15523,9 @@ module Tables = struct let _3 : (Parsetree.pattern) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in let _1 : ( -# 664 "parsing/parser.mly" +# 665 "parsing/parser.mly" (string) -# 15120 "parsing/parser.ml" +# 15529 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -15124,15 +15533,15 @@ module Tables = struct let _v : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = let _4 = let _1 = _1_inlined1 in -# 2111 "parsing/parser.mly" +# 2116 "parsing/parser.mly" ( _1 ) -# 15130 "parsing/parser.ml" +# 15539 "parsing/parser.ml" in -# 2089 "parsing/parser.mly" +# 2094 "parsing/parser.mly" ( (Optional _1, _4, _3) ) -# 15136 "parsing/parser.ml" +# 15545 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15158,17 +15567,17 @@ module Tables = struct } = _menhir_stack in let _2 : (Parsetree.pattern) = Obj.magic _2 in let _1 : ( -# 664 "parsing/parser.mly" +# 665 "parsing/parser.mly" (string) -# 15164 "parsing/parser.ml" +# 15573 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = -# 2091 "parsing/parser.mly" +# 2096 "parsing/parser.mly" ( (Optional _1, None, _2) ) -# 15172 "parsing/parser.ml" +# 15581 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15212,9 +15621,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__4_ in let _v : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = -# 2093 "parsing/parser.mly" +# 2098 "parsing/parser.mly" ( (Labelled (fst _3), None, snd _3) ) -# 15218 "parsing/parser.ml" +# 15627 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15239,9 +15648,9 @@ module Tables = struct }; } = _menhir_stack in let _1_inlined1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 15245 "parsing/parser.ml" +# 15654 "parsing/parser.ml" ) = Obj.magic _1_inlined1 in let _1 : unit = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -15254,24 +15663,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 15260 "parsing/parser.ml" +# 15669 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2123 "parsing/parser.mly" +# 2128 "parsing/parser.mly" ( (_1.Location.txt, mkpat ~loc:_sloc (Ppat_var _1)) ) -# 15269 "parsing/parser.ml" +# 15678 "parsing/parser.ml" in -# 2095 "parsing/parser.mly" +# 2100 "parsing/parser.mly" ( (Labelled (fst _2), None, snd _2) ) -# 15275 "parsing/parser.ml" +# 15684 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15297,17 +15706,17 @@ module Tables = struct } = _menhir_stack in let _2 : (Parsetree.pattern) = Obj.magic _2 in let _1 : ( -# 634 "parsing/parser.mly" +# 635 "parsing/parser.mly" (string) -# 15303 "parsing/parser.ml" +# 15712 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = -# 2097 "parsing/parser.mly" +# 2102 "parsing/parser.mly" ( (Labelled _1, None, _2) ) -# 15311 "parsing/parser.ml" +# 15720 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15330,9 +15739,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.arg_label * Parsetree.expression option * Parsetree.pattern) = -# 2099 "parsing/parser.mly" +# 2104 "parsing/parser.mly" ( (Nolabel, None, _1) ) -# 15336 "parsing/parser.ml" +# 15745 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15366,15 +15775,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2417 "parsing/parser.mly" +# 2422 "parsing/parser.mly" ( mkpatvar ~loc:_sloc _1 ) -# 15372 "parsing/parser.ml" +# 15781 "parsing/parser.ml" in -# 2421 "parsing/parser.mly" +# 2426 "parsing/parser.mly" ( (_1, _2) ) -# 15378 "parsing/parser.ml" +# 15787 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15422,16 +15831,16 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2417 "parsing/parser.mly" +# 2422 "parsing/parser.mly" ( mkpatvar ~loc:_sloc _1 ) -# 15428 "parsing/parser.ml" +# 15837 "parsing/parser.ml" in let _endpos = _endpos__4_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2423 "parsing/parser.mly" +# 2428 "parsing/parser.mly" ( let v = _1 in (* PR#7344 *) let t = match _2 with @@ -15444,7 +15853,7 @@ module Tables = struct let patloc = (_startpos__1_, _endpos__2_) in (ghpat ~loc:patloc (Ppat_constraint(v, typ)), mkexp_constraint ~loc:_sloc _4 _2) ) -# 15448 "parsing/parser.ml" +# 15857 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15513,18 +15922,18 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 15517 "parsing/parser.ml" +# 15926 "parsing/parser.ml" in -# 915 "parsing/parser.mly" +# 916 "parsing/parser.mly" ( xs ) -# 15522 "parsing/parser.ml" +# 15931 "parsing/parser.ml" in -# 3161 "parsing/parser.mly" +# 3202 "parsing/parser.mly" ( _1 ) -# 15528 "parsing/parser.ml" +# 15937 "parsing/parser.ml" in let _startpos__3_ = _startpos_xs_ in @@ -15533,19 +15942,19 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2417 "parsing/parser.mly" +# 2422 "parsing/parser.mly" ( mkpatvar ~loc:_sloc _1 ) -# 15539 "parsing/parser.ml" +# 15948 "parsing/parser.ml" in -# 2439 "parsing/parser.mly" +# 2444 "parsing/parser.mly" ( let typloc = (_startpos__3_, _endpos__5_) in let patloc = (_startpos__1_, _endpos__5_) in (ghpat ~loc:patloc (Ppat_constraint(_1, ghtyp ~loc:typloc (Ptyp_poly(_3,_5)))), _7) ) -# 15549 "parsing/parser.ml" +# 15958 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15617,30 +16026,30 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__8_ in let _v : (Parsetree.pattern * Parsetree.expression) = let _4 = -# 2414 "parsing/parser.mly" +# 2419 "parsing/parser.mly" ( xs ) -# 15623 "parsing/parser.ml" +# 16032 "parsing/parser.ml" in let _1 = let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2417 "parsing/parser.mly" +# 2422 "parsing/parser.mly" ( mkpatvar ~loc:_sloc _1 ) -# 15632 "parsing/parser.ml" +# 16041 "parsing/parser.ml" in let _endpos = _endpos__8_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2445 "parsing/parser.mly" +# 2450 "parsing/parser.mly" ( let exp, poly = wrap_type_annotation ~loc:_sloc _4 _6 _8 in let loc = (_startpos__1_, _endpos__6_) in (ghpat ~loc (Ppat_constraint(_1, poly)), exp) ) -# 15644 "parsing/parser.ml" +# 16053 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15677,9 +16086,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.pattern * Parsetree.expression) = -# 2450 "parsing/parser.mly" +# 2455 "parsing/parser.mly" ( (_1, _3) ) -# 15683 "parsing/parser.ml" +# 16092 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15730,10 +16139,10 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__5_ in let _v : (Parsetree.pattern * Parsetree.expression) = -# 2452 "parsing/parser.mly" +# 2457 "parsing/parser.mly" ( let loc = (_startpos__1_, _endpos__3_) in (ghpat ~loc (Ppat_constraint(_1, _3)), _5) ) -# 15737 "parsing/parser.ml" +# 16146 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15794,36 +16203,36 @@ module Tables = struct let attrs2 = let _1 = _1_inlined2 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 15800 "parsing/parser.ml" +# 16209 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined2_ in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 15809 "parsing/parser.ml" +# 16218 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2468 "parsing/parser.mly" +# 2473 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in mklbs ~loc:_sloc ext rec_flag (mklb ~loc:_sloc true body attrs) ) -# 15821 "parsing/parser.ml" +# 16230 "parsing/parser.ml" in -# 2458 "parsing/parser.mly" +# 2463 "parsing/parser.mly" ( _1 ) -# 15827 "parsing/parser.ml" +# 16236 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15853,9 +16262,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (let_bindings) = -# 2459 "parsing/parser.mly" +# 2464 "parsing/parser.mly" ( addlb _1 _2 ) -# 15859 "parsing/parser.ml" +# 16268 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -15909,41 +16318,41 @@ module Tables = struct let attrs2 = let _1 = _1_inlined2 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 15915 "parsing/parser.ml" +# 16324 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined2_ in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 15924 "parsing/parser.ml" +# 16333 "parsing/parser.ml" in let ext = -# 3749 "parsing/parser.mly" +# 3790 "parsing/parser.mly" ( None ) -# 15930 "parsing/parser.ml" +# 16339 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2468 "parsing/parser.mly" +# 2473 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in mklbs ~loc:_sloc ext rec_flag (mklb ~loc:_sloc true body attrs) ) -# 15941 "parsing/parser.ml" +# 16350 "parsing/parser.ml" in -# 2458 "parsing/parser.mly" +# 2463 "parsing/parser.mly" ( _1 ) -# 15947 "parsing/parser.ml" +# 16356 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16011,18 +16420,18 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 16017 "parsing/parser.ml" +# 16426 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in let attrs1 = let _1 = _1_inlined2 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 16026 "parsing/parser.ml" +# 16435 "parsing/parser.ml" in let ext = @@ -16031,27 +16440,27 @@ module Tables = struct let _startpos = _startpos__1_ in let _loc = (_startpos, _endpos) in -# 3750 "parsing/parser.mly" +# 3791 "parsing/parser.mly" ( not_expecting _loc "extension" ) -# 16037 "parsing/parser.ml" +# 16446 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2468 "parsing/parser.mly" +# 2473 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in mklbs ~loc:_sloc ext rec_flag (mklb ~loc:_sloc true body attrs) ) -# 16049 "parsing/parser.ml" +# 16458 "parsing/parser.ml" in -# 2458 "parsing/parser.mly" +# 2463 "parsing/parser.mly" ( _1 ) -# 16055 "parsing/parser.ml" +# 16464 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16081,9 +16490,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (let_bindings) = -# 2459 "parsing/parser.mly" +# 2464 "parsing/parser.mly" ( addlb _1 _2 ) -# 16087 "parsing/parser.ml" +# 16496 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16106,9 +16515,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.pattern) = -# 2127 "parsing/parser.mly" +# 2132 "parsing/parser.mly" ( _1 ) -# 16112 "parsing/parser.ml" +# 16521 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16146,24 +16555,24 @@ module Tables = struct let _endpos = _endpos__3_ in let _v : (Parsetree.pattern) = let _1 = let _1 = -# 2129 "parsing/parser.mly" +# 2134 "parsing/parser.mly" ( Ppat_constraint(_1, _3) ) -# 16152 "parsing/parser.ml" +# 16561 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 16161 "parsing/parser.ml" +# 16570 "parsing/parser.ml" in -# 2130 "parsing/parser.mly" +# 2135 "parsing/parser.mly" ( _1 ) -# 16167 "parsing/parser.ml" +# 16576 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16197,15 +16606,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2417 "parsing/parser.mly" +# 2422 "parsing/parser.mly" ( mkpatvar ~loc:_sloc _1 ) -# 16203 "parsing/parser.ml" +# 16612 "parsing/parser.ml" in -# 2485 "parsing/parser.mly" +# 2490 "parsing/parser.mly" ( (pat, exp) ) -# 16209 "parsing/parser.ml" +# 16618 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16256,10 +16665,10 @@ module Tables = struct let _startpos = _startpos_pat_ in let _endpos = _endpos_exp_ in let _v : (Parsetree.pattern * Parsetree.expression) = -# 2487 "parsing/parser.mly" +# 2492 "parsing/parser.mly" ( let loc = (_startpos_pat_, _endpos_typ_) in (ghpat ~loc (Ppat_constraint(pat, typ)), exp) ) -# 16263 "parsing/parser.ml" +# 16672 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16296,9 +16705,9 @@ module Tables = struct let _startpos = _startpos_pat_ in let _endpos = _endpos_exp_ in let _v : (Parsetree.pattern * Parsetree.expression) = -# 2490 "parsing/parser.mly" +# 2495 "parsing/parser.mly" ( (pat, exp) ) -# 16302 "parsing/parser.ml" +# 16711 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16321,10 +16730,10 @@ module Tables = struct let _startpos = _startpos_body_ in let _endpos = _endpos_body_ in let _v : (Parsetree.pattern * Parsetree.expression * Parsetree.binding_op list) = -# 2494 "parsing/parser.mly" +# 2499 "parsing/parser.mly" ( let let_pat, let_exp = body in let_pat, let_exp, [] ) -# 16328 "parsing/parser.ml" +# 16737 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16356,9 +16765,9 @@ module Tables = struct } = _menhir_stack in let body : (Parsetree.pattern * Parsetree.expression) = Obj.magic body in let _1 : ( -# 630 "parsing/parser.mly" +# 631 "parsing/parser.mly" (string) -# 16362 "parsing/parser.ml" +# 16771 "parsing/parser.ml" ) = Obj.magic _1 in let bindings : (Parsetree.pattern * Parsetree.expression * Parsetree.binding_op list) = Obj.magic bindings in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -16369,22 +16778,22 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 16375 "parsing/parser.ml" +# 16784 "parsing/parser.ml" in let _endpos = _endpos_body_ in let _symbolstartpos = _startpos_bindings_ in let _sloc = (_symbolstartpos, _endpos) in -# 2497 "parsing/parser.mly" +# 2502 "parsing/parser.mly" ( let let_pat, let_exp, rev_ands = bindings in let pbop_pat, pbop_exp = body in let pbop_loc = make_loc _sloc in let and_ = {pbop_op; pbop_pat; pbop_exp; pbop_loc} in let_pat, let_exp, and_ :: rev_ands ) -# 16388 "parsing/parser.ml" +# 16797 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16402,7 +16811,7 @@ module Tables = struct let _v : (Parsetree.class_declaration list) = # 211 "<standard.mly>" ( [] ) -# 16406 "parsing/parser.ml" +# 16815 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16466,9 +16875,9 @@ module Tables = struct let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in let body : (Parsetree.class_expr) = Obj.magic body in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 16472 "parsing/parser.ml" +# 16881 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let params : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = Obj.magic params in let virt : (Asttypes.virtual_flag) = Obj.magic virt in @@ -16481,9 +16890,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 16487 "parsing/parser.ml" +# 16896 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -16493,24 +16902,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 16499 "parsing/parser.ml" +# 16908 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 16507 "parsing/parser.ml" +# 16916 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1731 "parsing/parser.mly" +# 1736 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in @@ -16518,13 +16927,13 @@ module Tables = struct let text = symbol_text _symbolstartpos in Ci.mk id body ~virt ~params ~attrs ~loc ~text ~docs ) -# 16522 "parsing/parser.ml" +# 16931 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 16528 "parsing/parser.ml" +# 16937 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16542,7 +16951,7 @@ module Tables = struct let _v : (Parsetree.class_description list) = # 211 "<standard.mly>" ( [] ) -# 16546 "parsing/parser.ml" +# 16955 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16613,9 +17022,9 @@ module Tables = struct let cty : (Parsetree.class_type) = Obj.magic cty in let _6 : unit = Obj.magic _6 in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 16619 "parsing/parser.ml" +# 17028 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let params : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = Obj.magic params in let virt : (Asttypes.virtual_flag) = Obj.magic virt in @@ -16628,9 +17037,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 16634 "parsing/parser.ml" +# 17043 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -16640,24 +17049,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 16646 "parsing/parser.ml" +# 17055 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 16654 "parsing/parser.ml" +# 17063 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2022 "parsing/parser.mly" +# 2027 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in @@ -16665,13 +17074,13 @@ module Tables = struct let text = symbol_text _symbolstartpos in Ci.mk id cty ~virt ~params ~attrs ~loc ~text ~docs ) -# 16669 "parsing/parser.ml" +# 17078 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 16675 "parsing/parser.ml" +# 17084 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16689,7 +17098,7 @@ module Tables = struct let _v : (Parsetree.class_type_declaration list) = # 211 "<standard.mly>" ( [] ) -# 16693 "parsing/parser.ml" +# 17102 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16760,9 +17169,9 @@ module Tables = struct let csig : (Parsetree.class_type) = Obj.magic csig in let _6 : unit = Obj.magic _6 in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 16766 "parsing/parser.ml" +# 17175 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let params : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = Obj.magic params in let virt : (Asttypes.virtual_flag) = Obj.magic virt in @@ -16775,9 +17184,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 16781 "parsing/parser.ml" +# 17190 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -16787,24 +17196,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 16793 "parsing/parser.ml" +# 17202 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 16801 "parsing/parser.ml" +# 17210 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2061 "parsing/parser.mly" +# 2066 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in @@ -16812,13 +17221,13 @@ module Tables = struct let text = symbol_text _symbolstartpos in Ci.mk id csig ~virt ~params ~attrs ~loc ~text ~docs ) -# 16816 "parsing/parser.ml" +# 17225 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 16822 "parsing/parser.ml" +# 17231 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16836,7 +17245,7 @@ module Tables = struct let _v : (Parsetree.module_binding list) = # 211 "<standard.mly>" ( [] ) -# 16840 "parsing/parser.ml" +# 17249 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16897,9 +17306,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 16903 "parsing/parser.ml" +# 17312 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -16909,24 +17318,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 16915 "parsing/parser.ml" +# 17324 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 16923 "parsing/parser.ml" +# 17332 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1413 "parsing/parser.mly" +# 1416 "parsing/parser.mly" ( let loc = make_loc _sloc in let attrs = attrs1 @ attrs2 in @@ -16934,13 +17343,13 @@ module Tables = struct let text = symbol_text _symbolstartpos in Mb.mk name body ~attrs ~loc ~text ~docs ) -# 16938 "parsing/parser.ml" +# 17347 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 16944 "parsing/parser.ml" +# 17353 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -16958,7 +17367,7 @@ module Tables = struct let _v : (Parsetree.module_declaration list) = # 211 "<standard.mly>" ( [] ) -# 16962 "parsing/parser.ml" +# 17371 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17026,9 +17435,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 17032 "parsing/parser.ml" +# 17441 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -17038,24 +17447,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 17044 "parsing/parser.ml" +# 17453 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 17052 "parsing/parser.ml" +# 17461 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1689 "parsing/parser.mly" +# 1694 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let docs = symbol_docs _sloc in @@ -17063,13 +17472,13 @@ module Tables = struct let text = symbol_text _symbolstartpos in Md.mk name mty ~attrs ~loc ~text ~docs ) -# 17067 "parsing/parser.ml" +# 17476 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 17073 "parsing/parser.ml" +# 17482 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17087,7 +17496,7 @@ module Tables = struct let _v : (Parsetree.attributes) = # 211 "<standard.mly>" ( [] ) -# 17091 "parsing/parser.ml" +# 17500 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17119,7 +17528,7 @@ module Tables = struct let _v : (Parsetree.attributes) = # 213 "<standard.mly>" ( x :: xs ) -# 17123 "parsing/parser.ml" +# 17532 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17137,7 +17546,7 @@ module Tables = struct let _v : (Parsetree.type_declaration list) = # 211 "<standard.mly>" ( [] ) -# 17141 "parsing/parser.ml" +# 17550 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17202,9 +17611,9 @@ module Tables = struct let xs_inlined1 : ((Parsetree.core_type * Parsetree.core_type * Ast_helper.loc) list) = Obj.magic xs_inlined1 in let kind_priv_manifest : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = Obj.magic kind_priv_manifest in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 17208 "parsing/parser.ml" +# 17617 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let params : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = Obj.magic params in let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in @@ -17217,9 +17626,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 17223 "parsing/parser.ml" +# 17632 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -17228,18 +17637,18 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 17232 "parsing/parser.ml" +# 17641 "parsing/parser.ml" in -# 897 "parsing/parser.mly" +# 898 "parsing/parser.mly" ( xs ) -# 17237 "parsing/parser.ml" +# 17646 "parsing/parser.ml" in -# 2887 "parsing/parser.mly" +# 2894 "parsing/parser.mly" ( _1 ) -# 17243 "parsing/parser.ml" +# 17652 "parsing/parser.ml" in let id = @@ -17248,24 +17657,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 17254 "parsing/parser.ml" +# 17663 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 17262 "parsing/parser.ml" +# 17671 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2876 "parsing/parser.mly" +# 2883 "parsing/parser.mly" ( let (kind, priv, manifest) = kind_priv_manifest in let docs = symbol_docs _sloc in @@ -17274,13 +17683,13 @@ module Tables = struct let text = symbol_text _symbolstartpos in Type.mk id ~params ~cstrs ~kind ~priv ?manifest ~attrs ~loc ~docs ~text ) -# 17278 "parsing/parser.ml" +# 17687 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 17284 "parsing/parser.ml" +# 17693 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17298,7 +17707,7 @@ module Tables = struct let _v : (Parsetree.type_declaration list) = # 211 "<standard.mly>" ( [] ) -# 17302 "parsing/parser.ml" +# 17711 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17370,9 +17779,9 @@ module Tables = struct let _2 : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = Obj.magic _2 in let _1_inlined3 : unit = Obj.magic _1_inlined3 in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 17376 "parsing/parser.ml" +# 17785 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let params : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = Obj.magic params in let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in @@ -17385,9 +17794,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined4 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 17391 "parsing/parser.ml" +# 17800 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined4_ in @@ -17396,26 +17805,26 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 17400 "parsing/parser.ml" +# 17809 "parsing/parser.ml" in -# 897 "parsing/parser.mly" +# 898 "parsing/parser.mly" ( xs ) -# 17405 "parsing/parser.ml" +# 17814 "parsing/parser.ml" in -# 2887 "parsing/parser.mly" +# 2894 "parsing/parser.mly" ( _1 ) -# 17411 "parsing/parser.ml" +# 17820 "parsing/parser.ml" in let kind_priv_manifest = let _1 = _1_inlined3 in -# 2922 "parsing/parser.mly" +# 2929 "parsing/parser.mly" ( _2 ) -# 17419 "parsing/parser.ml" +# 17828 "parsing/parser.ml" in let id = @@ -17424,24 +17833,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 17430 "parsing/parser.ml" +# 17839 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 17438 "parsing/parser.ml" +# 17847 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2876 "parsing/parser.mly" +# 2883 "parsing/parser.mly" ( let (kind, priv, manifest) = kind_priv_manifest in let docs = symbol_docs _sloc in @@ -17450,13 +17859,13 @@ module Tables = struct let text = symbol_text _symbolstartpos in Type.mk id ~params ~cstrs ~kind ~priv ?manifest ~attrs ~loc ~docs ~text ) -# 17454 "parsing/parser.ml" +# 17863 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 17460 "parsing/parser.ml" +# 17869 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17474,7 +17883,7 @@ module Tables = struct let _v : (Parsetree.attributes) = # 211 "<standard.mly>" ( [] ) -# 17478 "parsing/parser.ml" +# 17887 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17506,7 +17915,7 @@ module Tables = struct let _v : (Parsetree.attributes) = # 213 "<standard.mly>" ( x :: xs ) -# 17510 "parsing/parser.ml" +# 17919 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17524,7 +17933,7 @@ module Tables = struct let _v : (Parsetree.signature_item list list) = # 211 "<standard.mly>" ( [] ) -# 17528 "parsing/parser.ml" +# 17937 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17557,21 +17966,21 @@ module Tables = struct let _1 = let _startpos = _startpos__1_ in -# 823 "parsing/parser.mly" +# 824 "parsing/parser.mly" ( text_sig _startpos ) -# 17563 "parsing/parser.ml" +# 17972 "parsing/parser.ml" in -# 1551 "parsing/parser.mly" +# 1554 "parsing/parser.mly" ( _1 ) -# 17569 "parsing/parser.ml" +# 17978 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 17575 "parsing/parser.ml" +# 17984 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17604,21 +18013,21 @@ module Tables = struct let _1 = let _startpos = _startpos__1_ in -# 821 "parsing/parser.mly" +# 822 "parsing/parser.mly" ( text_sig _startpos @ [_1] ) -# 17610 "parsing/parser.ml" +# 18019 "parsing/parser.ml" in -# 1551 "parsing/parser.mly" +# 1554 "parsing/parser.mly" ( _1 ) -# 17616 "parsing/parser.ml" +# 18025 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 17622 "parsing/parser.ml" +# 18031 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17636,7 +18045,7 @@ module Tables = struct let _v : (Parsetree.structure_item list list) = # 211 "<standard.mly>" ( [] ) -# 17640 "parsing/parser.ml" +# 18049 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17669,40 +18078,40 @@ module Tables = struct let _1 = let ys = let items = -# 883 "parsing/parser.mly" +# 884 "parsing/parser.mly" ( [] ) -# 17675 "parsing/parser.ml" +# 18084 "parsing/parser.ml" in -# 1297 "parsing/parser.mly" +# 1298 "parsing/parser.mly" ( items ) -# 17680 "parsing/parser.ml" +# 18089 "parsing/parser.ml" in let xs = let _startpos = _startpos__1_ in -# 819 "parsing/parser.mly" +# 820 "parsing/parser.mly" ( text_str _startpos ) -# 17688 "parsing/parser.ml" +# 18097 "parsing/parser.ml" in # 267 "<standard.mly>" ( xs @ ys ) -# 17694 "parsing/parser.ml" +# 18103 "parsing/parser.ml" in -# 1313 "parsing/parser.mly" +# 1314 "parsing/parser.mly" ( _1 ) -# 17700 "parsing/parser.ml" +# 18109 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 17706 "parsing/parser.ml" +# 18115 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17754,70 +18163,70 @@ module Tables = struct let _1 = let _1 = let attrs = -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 17760 "parsing/parser.ml" +# 18169 "parsing/parser.ml" in -# 1304 "parsing/parser.mly" +# 1305 "parsing/parser.mly" ( mkstrexp e attrs ) -# 17765 "parsing/parser.ml" +# 18174 "parsing/parser.ml" in let _startpos__1_ = _startpos_e_ in let _startpos = _startpos__1_ in -# 817 "parsing/parser.mly" +# 818 "parsing/parser.mly" ( text_str _startpos @ [_1] ) -# 17773 "parsing/parser.ml" +# 18182 "parsing/parser.ml" in let _startpos__1_ = _startpos_e_ in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 836 "parsing/parser.mly" +# 837 "parsing/parser.mly" ( mark_rhs_docs _startpos _endpos; _1 ) -# 17783 "parsing/parser.ml" +# 18192 "parsing/parser.ml" in -# 885 "parsing/parser.mly" +# 886 "parsing/parser.mly" ( x ) -# 17789 "parsing/parser.ml" +# 18198 "parsing/parser.ml" in -# 1297 "parsing/parser.mly" +# 1298 "parsing/parser.mly" ( items ) -# 17795 "parsing/parser.ml" +# 18204 "parsing/parser.ml" in let xs = let _startpos = _startpos__1_ in -# 819 "parsing/parser.mly" +# 820 "parsing/parser.mly" ( text_str _startpos ) -# 17803 "parsing/parser.ml" +# 18212 "parsing/parser.ml" in # 267 "<standard.mly>" ( xs @ ys ) -# 17809 "parsing/parser.ml" +# 18218 "parsing/parser.ml" in -# 1313 "parsing/parser.mly" +# 1314 "parsing/parser.mly" ( _1 ) -# 17815 "parsing/parser.ml" +# 18224 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 17821 "parsing/parser.ml" +# 18230 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17850,21 +18259,21 @@ module Tables = struct let _1 = let _startpos = _startpos__1_ in -# 817 "parsing/parser.mly" +# 818 "parsing/parser.mly" ( text_str _startpos @ [_1] ) -# 17856 "parsing/parser.ml" +# 18265 "parsing/parser.ml" in -# 1313 "parsing/parser.mly" +# 1314 "parsing/parser.mly" ( _1 ) -# 17862 "parsing/parser.ml" +# 18271 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 17868 "parsing/parser.ml" +# 18277 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17882,7 +18291,7 @@ module Tables = struct let _v : (Parsetree.class_type_field list list) = # 211 "<standard.mly>" ( [] ) -# 17886 "parsing/parser.ml" +# 18295 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17914,15 +18323,15 @@ module Tables = struct let _v : (Parsetree.class_type_field list list) = let x = let _startpos = _startpos__1_ in -# 831 "parsing/parser.mly" +# 832 "parsing/parser.mly" ( text_csig _startpos @ [_1] ) -# 17920 "parsing/parser.ml" +# 18329 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 17926 "parsing/parser.ml" +# 18335 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17940,7 +18349,7 @@ module Tables = struct let _v : (Parsetree.class_field list list) = # 211 "<standard.mly>" ( [] ) -# 17944 "parsing/parser.ml" +# 18353 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17972,15 +18381,15 @@ module Tables = struct let _v : (Parsetree.class_field list list) = let x = let _startpos = _startpos__1_ in -# 829 "parsing/parser.mly" +# 830 "parsing/parser.mly" ( text_cstr _startpos @ [_1] ) -# 17978 "parsing/parser.ml" +# 18387 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 17984 "parsing/parser.ml" +# 18393 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -17998,7 +18407,7 @@ module Tables = struct let _v : (Parsetree.structure_item list list) = # 211 "<standard.mly>" ( [] ) -# 18002 "parsing/parser.ml" +# 18411 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18030,15 +18439,15 @@ module Tables = struct let _v : (Parsetree.structure_item list list) = let x = let _startpos = _startpos__1_ in -# 817 "parsing/parser.mly" +# 818 "parsing/parser.mly" ( text_str _startpos @ [_1] ) -# 18036 "parsing/parser.ml" +# 18445 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 18042 "parsing/parser.ml" +# 18451 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18056,7 +18465,7 @@ module Tables = struct let _v : (Parsetree.toplevel_phrase list list) = # 211 "<standard.mly>" ( [] ) -# 18060 "parsing/parser.ml" +# 18469 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18089,32 +18498,32 @@ module Tables = struct let _1 = let x = let _1 = -# 883 "parsing/parser.mly" +# 884 "parsing/parser.mly" ( [] ) -# 18095 "parsing/parser.ml" +# 18504 "parsing/parser.ml" in -# 1113 "parsing/parser.mly" +# 1114 "parsing/parser.mly" ( _1 ) -# 18100 "parsing/parser.ml" +# 18509 "parsing/parser.ml" in # 183 "<standard.mly>" ( x ) -# 18106 "parsing/parser.ml" +# 18515 "parsing/parser.ml" in -# 1125 "parsing/parser.mly" +# 1126 "parsing/parser.mly" ( _1 ) -# 18112 "parsing/parser.ml" +# 18521 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 18118 "parsing/parser.ml" +# 18527 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18166,58 +18575,58 @@ module Tables = struct let _1 = let _1 = let attrs = -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 18172 "parsing/parser.ml" +# 18581 "parsing/parser.ml" in -# 1304 "parsing/parser.mly" +# 1305 "parsing/parser.mly" ( mkstrexp e attrs ) -# 18177 "parsing/parser.ml" +# 18586 "parsing/parser.ml" in -# 827 "parsing/parser.mly" +# 828 "parsing/parser.mly" ( Ptop_def [_1] ) -# 18183 "parsing/parser.ml" +# 18592 "parsing/parser.ml" in let _startpos__1_ = _startpos_e_ in let _startpos = _startpos__1_ in -# 825 "parsing/parser.mly" +# 826 "parsing/parser.mly" ( text_def _startpos @ [_1] ) -# 18191 "parsing/parser.ml" +# 18600 "parsing/parser.ml" in -# 885 "parsing/parser.mly" +# 886 "parsing/parser.mly" ( x ) -# 18197 "parsing/parser.ml" +# 18606 "parsing/parser.ml" in -# 1113 "parsing/parser.mly" +# 1114 "parsing/parser.mly" ( _1 ) -# 18203 "parsing/parser.ml" +# 18612 "parsing/parser.ml" in # 183 "<standard.mly>" ( x ) -# 18209 "parsing/parser.ml" +# 18618 "parsing/parser.ml" in -# 1125 "parsing/parser.mly" +# 1126 "parsing/parser.mly" ( _1 ) -# 18215 "parsing/parser.ml" +# 18624 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 18221 "parsing/parser.ml" +# 18630 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18249,27 +18658,27 @@ module Tables = struct let _v : (Parsetree.toplevel_phrase list list) = let x = let _1 = let _1 = -# 827 "parsing/parser.mly" +# 828 "parsing/parser.mly" ( Ptop_def [_1] ) -# 18255 "parsing/parser.ml" +# 18664 "parsing/parser.ml" in let _startpos = _startpos__1_ in -# 825 "parsing/parser.mly" +# 826 "parsing/parser.mly" ( text_def _startpos @ [_1] ) -# 18261 "parsing/parser.ml" +# 18670 "parsing/parser.ml" in -# 1125 "parsing/parser.mly" +# 1126 "parsing/parser.mly" ( _1 ) -# 18267 "parsing/parser.ml" +# 18676 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 18273 "parsing/parser.ml" +# 18682 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18304,29 +18713,29 @@ module Tables = struct let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 836 "parsing/parser.mly" +# 837 "parsing/parser.mly" ( mark_rhs_docs _startpos _endpos; _1 ) -# 18311 "parsing/parser.ml" +# 18720 "parsing/parser.ml" in let _startpos = _startpos__1_ in -# 825 "parsing/parser.mly" +# 826 "parsing/parser.mly" ( text_def _startpos @ [_1] ) -# 18318 "parsing/parser.ml" +# 18727 "parsing/parser.ml" in -# 1125 "parsing/parser.mly" +# 1126 "parsing/parser.mly" ( _1 ) -# 18324 "parsing/parser.ml" +# 18733 "parsing/parser.ml" in # 213 "<standard.mly>" ( x :: xs ) -# 18330 "parsing/parser.ml" +# 18739 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18365,7 +18774,7 @@ module Tables = struct let _v : ((Longident.t Asttypes.loc * Parsetree.pattern) list * unit option) = let _2 = # 124 "<standard.mly>" ( None ) -# 18369 "parsing/parser.ml" +# 18778 "parsing/parser.ml" in let x = let label = @@ -18373,9 +18782,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 18379 "parsing/parser.ml" +# 18788 "parsing/parser.ml" in let _startpos_label_ = _startpos__1_ in @@ -18383,7 +18792,7 @@ module Tables = struct let _symbolstartpos = _startpos_label_ in let _sloc = (_symbolstartpos, _endpos) in -# 2765 "parsing/parser.mly" +# 2772 "parsing/parser.mly" ( let pat = match opat with | None -> @@ -18394,13 +18803,13 @@ module Tables = struct in label, mkpat_opt_constraint ~loc:_sloc pat octy ) -# 18398 "parsing/parser.ml" +# 18807 "parsing/parser.ml" in -# 1052 "parsing/parser.mly" +# 1053 "parsing/parser.mly" ( [x], None ) -# 18404 "parsing/parser.ml" +# 18813 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18446,7 +18855,7 @@ module Tables = struct let _v : ((Longident.t Asttypes.loc * Parsetree.pattern) list * unit option) = let _2 = # 126 "<standard.mly>" ( Some x ) -# 18450 "parsing/parser.ml" +# 18859 "parsing/parser.ml" in let x = let label = @@ -18454,9 +18863,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 18460 "parsing/parser.ml" +# 18869 "parsing/parser.ml" in let _startpos_label_ = _startpos__1_ in @@ -18464,7 +18873,7 @@ module Tables = struct let _symbolstartpos = _startpos_label_ in let _sloc = (_symbolstartpos, _endpos) in -# 2765 "parsing/parser.mly" +# 2772 "parsing/parser.mly" ( let pat = match opat with | None -> @@ -18475,13 +18884,13 @@ module Tables = struct in label, mkpat_opt_constraint ~loc:_sloc pat octy ) -# 18479 "parsing/parser.ml" +# 18888 "parsing/parser.ml" in -# 1052 "parsing/parser.mly" +# 1053 "parsing/parser.mly" ( [x], None ) -# 18485 "parsing/parser.ml" +# 18894 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18544,9 +18953,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 18550 "parsing/parser.ml" +# 18959 "parsing/parser.ml" in let _startpos_label_ = _startpos__1_ in @@ -18554,7 +18963,7 @@ module Tables = struct let _symbolstartpos = _startpos_label_ in let _sloc = (_symbolstartpos, _endpos) in -# 2765 "parsing/parser.mly" +# 2772 "parsing/parser.mly" ( let pat = match opat with | None -> @@ -18565,13 +18974,13 @@ module Tables = struct in label, mkpat_opt_constraint ~loc:_sloc pat octy ) -# 18569 "parsing/parser.ml" +# 18978 "parsing/parser.ml" in -# 1054 "parsing/parser.mly" +# 1055 "parsing/parser.mly" ( [x], Some y ) -# 18575 "parsing/parser.ml" +# 18984 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18627,9 +19036,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 18633 "parsing/parser.ml" +# 19042 "parsing/parser.ml" in let _startpos_label_ = _startpos__1_ in @@ -18637,7 +19046,7 @@ module Tables = struct let _symbolstartpos = _startpos_label_ in let _sloc = (_symbolstartpos, _endpos) in -# 2765 "parsing/parser.mly" +# 2772 "parsing/parser.mly" ( let pat = match opat with | None -> @@ -18648,14 +19057,14 @@ module Tables = struct in label, mkpat_opt_constraint ~loc:_sloc pat octy ) -# 18652 "parsing/parser.ml" +# 19061 "parsing/parser.ml" in -# 1058 "parsing/parser.mly" +# 1059 "parsing/parser.mly" ( let xs, y = tail in x :: xs, y ) -# 18659 "parsing/parser.ml" +# 19068 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18692,9 +19101,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.case) = -# 2523 "parsing/parser.mly" +# 2528 "parsing/parser.mly" ( Exp.case _1 _3 ) -# 18698 "parsing/parser.ml" +# 19107 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18745,9 +19154,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__5_ in let _v : (Parsetree.case) = -# 2525 "parsing/parser.mly" +# 2530 "parsing/parser.mly" ( Exp.case _1 ~guard:_3 _5 ) -# 18751 "parsing/parser.ml" +# 19160 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18785,9 +19194,9 @@ module Tables = struct let _endpos = _endpos__3_ in let _v : (Parsetree.case) = let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2527 "parsing/parser.mly" +# 2532 "parsing/parser.mly" ( Exp.case _1 (Exp.unreachable ~loc:(make_loc _loc__3_) ()) ) -# 18791 "parsing/parser.ml" +# 19200 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18848,9 +19257,9 @@ module Tables = struct let _1_inlined1 : (Parsetree.core_type) = Obj.magic _1_inlined1 in let _2 : unit = Obj.magic _2 in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 18854 "parsing/parser.ml" +# 19263 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -18859,49 +19268,49 @@ module Tables = struct let _6 = let _1 = _1_inlined3 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 18865 "parsing/parser.ml" +# 19274 "parsing/parser.ml" in let _endpos__6_ = _endpos__1_inlined3_ in let _4 = let _1 = _1_inlined2 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 18874 "parsing/parser.ml" +# 19283 "parsing/parser.ml" in let _endpos__4_ = _endpos__1_inlined2_ in let _3 = let _1 = _1_inlined1 in -# 3179 "parsing/parser.mly" +# 3220 "parsing/parser.mly" ( _1 ) -# 18883 "parsing/parser.ml" +# 19292 "parsing/parser.ml" in let _1 = let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 18890 "parsing/parser.ml" +# 19299 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 18898 "parsing/parser.ml" +# 19307 "parsing/parser.ml" in let _endpos = _endpos__6_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3389 "parsing/parser.mly" +# 3430 "parsing/parser.mly" ( let info = match rhs_info _endpos__4_ with | Some _ as info_before_semi -> info_before_semi @@ -18909,13 +19318,13 @@ module Tables = struct in let attrs = add_info_attrs info (_4 @ _6) in Of.tag ~loc:(make_loc _sloc) ~attrs _1 _3 ) -# 18913 "parsing/parser.ml" +# 19322 "parsing/parser.ml" in -# 3370 "parsing/parser.mly" +# 3411 "parsing/parser.mly" ( let (f, c) = tail in (head :: f, c) ) -# 18919 "parsing/parser.ml" +# 19328 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -18956,15 +19365,15 @@ module Tables = struct let _symbolstartpos = _startpos_ty_ in let _sloc = (_symbolstartpos, _endpos) in -# 3400 "parsing/parser.mly" +# 3441 "parsing/parser.mly" ( Of.inherit_ ~loc:(make_loc _sloc) ty ) -# 18962 "parsing/parser.ml" +# 19371 "parsing/parser.ml" in -# 3370 "parsing/parser.mly" +# 3411 "parsing/parser.mly" ( let (f, c) = tail in (head :: f, c) ) -# 18968 "parsing/parser.ml" +# 19377 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -19018,9 +19427,9 @@ module Tables = struct let _1_inlined1 : (Parsetree.core_type) = Obj.magic _1_inlined1 in let _2 : unit = Obj.magic _2 in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 19024 "parsing/parser.ml" +# 19433 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -19029,49 +19438,49 @@ module Tables = struct let _6 = let _1 = _1_inlined3 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 19035 "parsing/parser.ml" +# 19444 "parsing/parser.ml" in let _endpos__6_ = _endpos__1_inlined3_ in let _4 = let _1 = _1_inlined2 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 19044 "parsing/parser.ml" +# 19453 "parsing/parser.ml" in let _endpos__4_ = _endpos__1_inlined2_ in let _3 = let _1 = _1_inlined1 in -# 3179 "parsing/parser.mly" +# 3220 "parsing/parser.mly" ( _1 ) -# 19053 "parsing/parser.ml" +# 19462 "parsing/parser.ml" in let _1 = let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 19060 "parsing/parser.ml" +# 19469 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 19068 "parsing/parser.ml" +# 19477 "parsing/parser.ml" in let _endpos = _endpos__6_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3389 "parsing/parser.mly" +# 3430 "parsing/parser.mly" ( let info = match rhs_info _endpos__4_ with | Some _ as info_before_semi -> info_before_semi @@ -19079,13 +19488,13 @@ module Tables = struct in let attrs = add_info_attrs info (_4 @ _6) in Of.tag ~loc:(make_loc _sloc) ~attrs _1 _3 ) -# 19083 "parsing/parser.ml" +# 19492 "parsing/parser.ml" in -# 3373 "parsing/parser.mly" +# 3414 "parsing/parser.mly" ( [head], Closed ) -# 19089 "parsing/parser.ml" +# 19498 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -19119,15 +19528,15 @@ module Tables = struct let _symbolstartpos = _startpos_ty_ in let _sloc = (_symbolstartpos, _endpos) in -# 3400 "parsing/parser.mly" +# 3441 "parsing/parser.mly" ( Of.inherit_ ~loc:(make_loc _sloc) ty ) -# 19125 "parsing/parser.ml" +# 19534 "parsing/parser.ml" in -# 3373 "parsing/parser.mly" +# 3414 "parsing/parser.mly" ( [head], Closed ) -# 19131 "parsing/parser.ml" +# 19540 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -19167,9 +19576,9 @@ module Tables = struct let _1_inlined1 : (Parsetree.core_type) = Obj.magic _1_inlined1 in let _2 : unit = Obj.magic _2 in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 19173 "parsing/parser.ml" +# 19582 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -19178,50 +19587,50 @@ module Tables = struct let _4 = let _1 = _1_inlined2 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 19184 "parsing/parser.ml" +# 19593 "parsing/parser.ml" in let _endpos__4_ = _endpos__1_inlined2_ in let _3 = let _1 = _1_inlined1 in -# 3179 "parsing/parser.mly" +# 3220 "parsing/parser.mly" ( _1 ) -# 19193 "parsing/parser.ml" +# 19602 "parsing/parser.ml" in let _1 = let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 19200 "parsing/parser.ml" +# 19609 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 19208 "parsing/parser.ml" +# 19617 "parsing/parser.ml" in let _endpos = _endpos__4_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3382 "parsing/parser.mly" +# 3423 "parsing/parser.mly" ( let info = symbol_info _endpos in let attrs = add_info_attrs info _4 in Of.tag ~loc:(make_loc _sloc) ~attrs _1 _3 ) -# 19219 "parsing/parser.ml" +# 19628 "parsing/parser.ml" in -# 3376 "parsing/parser.mly" +# 3417 "parsing/parser.mly" ( [head], Closed ) -# 19225 "parsing/parser.ml" +# 19634 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -19248,15 +19657,15 @@ module Tables = struct let _symbolstartpos = _startpos_ty_ in let _sloc = (_symbolstartpos, _endpos) in -# 3400 "parsing/parser.mly" +# 3441 "parsing/parser.mly" ( Of.inherit_ ~loc:(make_loc _sloc) ty ) -# 19254 "parsing/parser.ml" +# 19663 "parsing/parser.ml" in -# 3376 "parsing/parser.mly" +# 3417 "parsing/parser.mly" ( [head], Closed ) -# 19260 "parsing/parser.ml" +# 19669 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -19279,9 +19688,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.object_field list * Asttypes.closed_flag) = -# 3378 "parsing/parser.mly" +# 3419 "parsing/parser.mly" ( [], Open ) -# 19285 "parsing/parser.ml" +# 19694 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -19326,9 +19735,9 @@ module Tables = struct let _1_inlined2 : (Parsetree.core_type) = Obj.magic _1_inlined2 in let _5 : unit = Obj.magic _5 in let _1_inlined1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 19332 "parsing/parser.ml" +# 19741 "parsing/parser.ml" ) = Obj.magic _1_inlined1 in let private_ : (Asttypes.private_flag) = Obj.magic private_ in let _1 : (Parsetree.attributes) = Obj.magic _1 in @@ -19340,41 +19749,41 @@ module Tables = struct Parsetree.attributes) = let ty = let _1 = _1_inlined2 in -# 3175 "parsing/parser.mly" +# 3216 "parsing/parser.mly" ( _1 ) -# 19346 "parsing/parser.ml" +# 19755 "parsing/parser.ml" in let label = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 19354 "parsing/parser.ml" +# 19763 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 19362 "parsing/parser.ml" +# 19771 "parsing/parser.ml" in let attrs = -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 19368 "parsing/parser.ml" +# 19777 "parsing/parser.ml" in let _1 = -# 3641 "parsing/parser.mly" +# 3682 "parsing/parser.mly" ( Fresh ) -# 19373 "parsing/parser.ml" +# 19782 "parsing/parser.ml" in -# 1869 "parsing/parser.mly" +# 1874 "parsing/parser.mly" ( (label, private_, Cfk_virtual ty), attrs ) -# 19378 "parsing/parser.ml" +# 19787 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -19412,9 +19821,9 @@ module Tables = struct } = _menhir_stack in let _5 : (Parsetree.expression) = Obj.magic _5 in let _1_inlined1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 19418 "parsing/parser.ml" +# 19827 "parsing/parser.ml" ) = Obj.magic _1_inlined1 in let _3 : (Asttypes.private_flag) = Obj.magic _3 in let _1 : (Parsetree.attributes) = Obj.magic _1 in @@ -19426,36 +19835,36 @@ module Tables = struct Parsetree.attributes) = let _4 = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 19432 "parsing/parser.ml" +# 19841 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 19440 "parsing/parser.ml" +# 19849 "parsing/parser.ml" in let _2 = -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 19446 "parsing/parser.ml" +# 19855 "parsing/parser.ml" in let _1 = -# 3644 "parsing/parser.mly" +# 3685 "parsing/parser.mly" ( Fresh ) -# 19451 "parsing/parser.ml" +# 19860 "parsing/parser.ml" in -# 1871 "parsing/parser.mly" +# 1876 "parsing/parser.mly" ( let e = _5 in let loc = Location.(e.pexp_loc.loc_start, e.pexp_loc.loc_end) in (_4, _3, Cfk_concrete (_1, ghexp ~loc (Pexp_poly (e, None)))), _2 ) -# 19459 "parsing/parser.ml" +# 19868 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -19499,9 +19908,9 @@ module Tables = struct } = _menhir_stack in let _5 : (Parsetree.expression) = Obj.magic _5 in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 19505 "parsing/parser.ml" +# 19914 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let _3 : (Asttypes.private_flag) = Obj.magic _3 in let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in @@ -19514,39 +19923,39 @@ module Tables = struct Parsetree.attributes) = let _4 = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 19520 "parsing/parser.ml" +# 19929 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 19528 "parsing/parser.ml" +# 19937 "parsing/parser.ml" in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 19536 "parsing/parser.ml" +# 19945 "parsing/parser.ml" in let _1 = -# 3645 "parsing/parser.mly" +# 3686 "parsing/parser.mly" ( Override ) -# 19542 "parsing/parser.ml" +# 19951 "parsing/parser.ml" in -# 1871 "parsing/parser.mly" +# 1876 "parsing/parser.mly" ( let e = _5 in let loc = Location.(e.pexp_loc.loc_start, e.pexp_loc.loc_end) in (_4, _3, Cfk_concrete (_1, ghexp ~loc (Pexp_poly (e, None)))), _2 ) -# 19550 "parsing/parser.ml" +# 19959 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -19605,9 +20014,9 @@ module Tables = struct let _1_inlined2 : (Parsetree.core_type) = Obj.magic _1_inlined2 in let _5 : unit = Obj.magic _5 in let _1_inlined1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 19611 "parsing/parser.ml" +# 20020 "parsing/parser.ml" ) = Obj.magic _1_inlined1 in let _3 : (Asttypes.private_flag) = Obj.magic _3 in let _1 : (Parsetree.attributes) = Obj.magic _1 in @@ -19619,45 +20028,45 @@ module Tables = struct Parsetree.attributes) = let _6 = let _1 = _1_inlined2 in -# 3175 "parsing/parser.mly" +# 3216 "parsing/parser.mly" ( _1 ) -# 19625 "parsing/parser.ml" +# 20034 "parsing/parser.ml" in let _startpos__6_ = _startpos__1_inlined2_ in let _4 = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 19634 "parsing/parser.ml" +# 20043 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 19642 "parsing/parser.ml" +# 20051 "parsing/parser.ml" in let _2 = -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 19648 "parsing/parser.ml" +# 20057 "parsing/parser.ml" in let _1 = -# 3644 "parsing/parser.mly" +# 3685 "parsing/parser.mly" ( Fresh ) -# 19653 "parsing/parser.ml" +# 20062 "parsing/parser.ml" in -# 1877 "parsing/parser.mly" +# 1882 "parsing/parser.mly" ( let poly_exp = let loc = (_startpos__6_, _endpos__8_) in ghexp ~loc (Pexp_poly(_8, Some _6)) in (_4, _3, Cfk_concrete (_1, poly_exp)), _2 ) -# 19661 "parsing/parser.ml" +# 20070 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -19722,9 +20131,9 @@ module Tables = struct let _1_inlined3 : (Parsetree.core_type) = Obj.magic _1_inlined3 in let _5 : unit = Obj.magic _5 in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 19728 "parsing/parser.ml" +# 20137 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let _3 : (Asttypes.private_flag) = Obj.magic _3 in let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in @@ -19737,48 +20146,48 @@ module Tables = struct Parsetree.attributes) = let _6 = let _1 = _1_inlined3 in -# 3175 "parsing/parser.mly" +# 3216 "parsing/parser.mly" ( _1 ) -# 19743 "parsing/parser.ml" +# 20152 "parsing/parser.ml" in let _startpos__6_ = _startpos__1_inlined3_ in let _4 = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 19752 "parsing/parser.ml" +# 20161 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 19760 "parsing/parser.ml" +# 20169 "parsing/parser.ml" in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 19768 "parsing/parser.ml" +# 20177 "parsing/parser.ml" in let _1 = -# 3645 "parsing/parser.mly" +# 3686 "parsing/parser.mly" ( Override ) -# 19774 "parsing/parser.ml" +# 20183 "parsing/parser.ml" in -# 1877 "parsing/parser.mly" +# 1882 "parsing/parser.mly" ( let poly_exp = let loc = (_startpos__6_, _endpos__8_) in ghexp ~loc (Pexp_poly(_8, Some _6)) in (_4, _3, Cfk_concrete (_1, poly_exp)), _2 ) -# 19782 "parsing/parser.ml" +# 20191 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -19858,9 +20267,9 @@ module Tables = struct let _6 : unit = Obj.magic _6 in let _5 : unit = Obj.magic _5 in let _1_inlined1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 19864 "parsing/parser.ml" +# 20273 "parsing/parser.ml" ) = Obj.magic _1_inlined1 in let _3 : (Asttypes.private_flag) = Obj.magic _3 in let _1 : (Parsetree.attributes) = Obj.magic _1 in @@ -19870,38 +20279,38 @@ module Tables = struct let _v : ((Asttypes.label Asttypes.loc * Asttypes.private_flag * Parsetree.class_field_kind) * Parsetree.attributes) = let _7 = -# 2414 "parsing/parser.mly" +# 2419 "parsing/parser.mly" ( xs ) -# 19876 "parsing/parser.ml" +# 20285 "parsing/parser.ml" in let _startpos__7_ = _startpos_xs_ in let _4 = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 19884 "parsing/parser.ml" +# 20293 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 19892 "parsing/parser.ml" +# 20301 "parsing/parser.ml" in let _startpos__4_ = _startpos__1_inlined1_ in let _2 = -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 19899 "parsing/parser.ml" +# 20308 "parsing/parser.ml" in let (_endpos__2_, _startpos__2_) = (_endpos__1_, _startpos__1_) in let _1 = -# 3644 "parsing/parser.mly" +# 3685 "parsing/parser.mly" ( Fresh ) -# 19905 "parsing/parser.ml" +# 20314 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos__0_, _endpos__0_) in let _endpos = _endpos__11_ in @@ -19917,7 +20326,7 @@ module Tables = struct _startpos__4_ in let _sloc = (_symbolstartpos, _endpos) in -# 1883 "parsing/parser.mly" +# 1888 "parsing/parser.mly" ( let poly_exp_loc = (_startpos__7_, _endpos__11_) in let poly_exp = let exp, poly = @@ -19928,7 +20337,7 @@ module Tables = struct ghexp ~loc:poly_exp_loc (Pexp_poly(exp, Some poly)) in (_4, _3, Cfk_concrete (_1, poly_exp)), _2 ) -# 19932 "parsing/parser.ml" +# 20341 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20014,9 +20423,9 @@ module Tables = struct let _6 : unit = Obj.magic _6 in let _5 : unit = Obj.magic _5 in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 20020 "parsing/parser.ml" +# 20429 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let _3 : (Asttypes.private_flag) = Obj.magic _3 in let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in @@ -20027,41 +20436,41 @@ module Tables = struct let _v : ((Asttypes.label Asttypes.loc * Asttypes.private_flag * Parsetree.class_field_kind) * Parsetree.attributes) = let _7 = -# 2414 "parsing/parser.mly" +# 2419 "parsing/parser.mly" ( xs ) -# 20033 "parsing/parser.ml" +# 20442 "parsing/parser.ml" in let _startpos__7_ = _startpos_xs_ in let _4 = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 20041 "parsing/parser.ml" +# 20450 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 20049 "parsing/parser.ml" +# 20458 "parsing/parser.ml" in let _startpos__4_ = _startpos__1_inlined2_ in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 20058 "parsing/parser.ml" +# 20467 "parsing/parser.ml" in let (_endpos__2_, _startpos__2_) = (_endpos__1_inlined1_, _startpos__1_inlined1_) in let _1 = -# 3645 "parsing/parser.mly" +# 3686 "parsing/parser.mly" ( Override ) -# 20065 "parsing/parser.ml" +# 20474 "parsing/parser.ml" in let _endpos = _endpos__11_ in let _symbolstartpos = if _startpos__1_ != _endpos__1_ then @@ -20076,7 +20485,7 @@ module Tables = struct _startpos__4_ in let _sloc = (_symbolstartpos, _endpos) in -# 1883 "parsing/parser.mly" +# 1888 "parsing/parser.mly" ( let poly_exp_loc = (_startpos__7_, _endpos__11_) in let poly_exp = let exp, poly = @@ -20087,7 +20496,7 @@ module Tables = struct ghexp ~loc:poly_exp_loc (Pexp_poly(exp, Some poly)) in (_4, _3, Cfk_concrete (_1, poly_exp)), _2 ) -# 20091 "parsing/parser.ml" +# 20500 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20106,17 +20515,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 20112 "parsing/parser.ml" +# 20521 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3501 "parsing/parser.mly" +# 3542 "parsing/parser.mly" ( Lident _1 ) -# 20120 "parsing/parser.ml" +# 20529 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20147,9 +20556,9 @@ module Tables = struct }; } = _menhir_stack in let _3 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 20153 "parsing/parser.ml" +# 20562 "parsing/parser.ml" ) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in let _1 : (Longident.t) = Obj.magic _1 in @@ -20157,9 +20566,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Longident.t) = -# 3502 "parsing/parser.mly" +# 3543 "parsing/parser.mly" ( Ldot(_1,_3) ) -# 20163 "parsing/parser.ml" +# 20572 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20178,17 +20587,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 697 "parsing/parser.mly" +# 698 "parsing/parser.mly" (string) -# 20184 "parsing/parser.ml" +# 20593 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3501 "parsing/parser.mly" +# 3542 "parsing/parser.mly" ( Lident _1 ) -# 20192 "parsing/parser.ml" +# 20601 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20219,9 +20628,9 @@ module Tables = struct }; } = _menhir_stack in let _3 : ( -# 697 "parsing/parser.mly" +# 698 "parsing/parser.mly" (string) -# 20225 "parsing/parser.ml" +# 20634 "parsing/parser.ml" ) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in let _1 : (Longident.t) = Obj.magic _1 in @@ -20229,9 +20638,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Longident.t) = -# 3502 "parsing/parser.mly" +# 3543 "parsing/parser.mly" ( Ldot(_1,_3) ) -# 20235 "parsing/parser.ml" +# 20644 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20254,14 +20663,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = let _1 = -# 3538 "parsing/parser.mly" +# 3579 "parsing/parser.mly" ( _1 ) -# 20260 "parsing/parser.ml" +# 20669 "parsing/parser.ml" in -# 3501 "parsing/parser.mly" +# 3542 "parsing/parser.mly" ( Lident _1 ) -# 20265 "parsing/parser.ml" +# 20674 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20299,20 +20708,20 @@ module Tables = struct let _endpos = _endpos__3_ in let _v : (Longident.t) = let _1 = let _1 = -# 3481 "parsing/parser.mly" +# 3522 "parsing/parser.mly" ( "::" ) -# 20305 "parsing/parser.ml" +# 20714 "parsing/parser.ml" in -# 3538 "parsing/parser.mly" +# 3579 "parsing/parser.mly" ( _1 ) -# 20310 "parsing/parser.ml" +# 20719 "parsing/parser.ml" in -# 3501 "parsing/parser.mly" +# 3542 "parsing/parser.mly" ( Lident _1 ) -# 20316 "parsing/parser.ml" +# 20725 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20335,14 +20744,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = let _1 = -# 3538 "parsing/parser.mly" +# 3579 "parsing/parser.mly" ( _1 ) -# 20341 "parsing/parser.ml" +# 20750 "parsing/parser.ml" in -# 3501 "parsing/parser.mly" +# 3542 "parsing/parser.mly" ( Lident _1 ) -# 20346 "parsing/parser.ml" +# 20755 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20381,15 +20790,15 @@ module Tables = struct let _v : (Longident.t) = let _3 = let _1 = _1_inlined1 in -# 3538 "parsing/parser.mly" +# 3579 "parsing/parser.mly" ( _1 ) -# 20387 "parsing/parser.ml" +# 20796 "parsing/parser.ml" in -# 3502 "parsing/parser.mly" +# 3543 "parsing/parser.mly" ( Ldot(_1,_3) ) -# 20393 "parsing/parser.ml" +# 20802 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20442,20 +20851,20 @@ module Tables = struct let _v : (Longident.t) = let _3 = let (_2, _1) = (_2_inlined1, _1_inlined1) in let _1 = -# 3481 "parsing/parser.mly" +# 3522 "parsing/parser.mly" ( "::" ) -# 20448 "parsing/parser.ml" +# 20857 "parsing/parser.ml" in -# 3538 "parsing/parser.mly" +# 3579 "parsing/parser.mly" ( _1 ) -# 20453 "parsing/parser.ml" +# 20862 "parsing/parser.ml" in -# 3502 "parsing/parser.mly" +# 3543 "parsing/parser.mly" ( Ldot(_1,_3) ) -# 20459 "parsing/parser.ml" +# 20868 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20494,15 +20903,15 @@ module Tables = struct let _v : (Longident.t) = let _3 = let _1 = _1_inlined1 in -# 3538 "parsing/parser.mly" +# 3579 "parsing/parser.mly" ( _1 ) -# 20500 "parsing/parser.ml" +# 20909 "parsing/parser.ml" in -# 3502 "parsing/parser.mly" +# 3543 "parsing/parser.mly" ( Ldot(_1,_3) ) -# 20506 "parsing/parser.ml" +# 20915 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20525,9 +20934,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3501 "parsing/parser.mly" +# 3542 "parsing/parser.mly" ( Lident _1 ) -# 20531 "parsing/parser.ml" +# 20940 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20564,9 +20973,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Longident.t) = -# 3502 "parsing/parser.mly" +# 3543 "parsing/parser.mly" ( Ldot(_1,_3) ) -# 20570 "parsing/parser.ml" +# 20979 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20585,17 +20994,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 20591 "parsing/parser.ml" +# 21000 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3501 "parsing/parser.mly" +# 3542 "parsing/parser.mly" ( Lident _1 ) -# 20599 "parsing/parser.ml" +# 21008 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20626,9 +21035,9 @@ module Tables = struct }; } = _menhir_stack in let _3 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 20632 "parsing/parser.ml" +# 21041 "parsing/parser.ml" ) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in let _1 : (Longident.t) = Obj.magic _1 in @@ -20636,9 +21045,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Longident.t) = -# 3502 "parsing/parser.mly" +# 3543 "parsing/parser.mly" ( Ldot(_1,_3) ) -# 20642 "parsing/parser.ml" +# 21051 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20657,17 +21066,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 697 "parsing/parser.mly" +# 698 "parsing/parser.mly" (string) -# 20663 "parsing/parser.ml" +# 21072 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3501 "parsing/parser.mly" +# 3542 "parsing/parser.mly" ( Lident _1 ) -# 20671 "parsing/parser.ml" +# 21080 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20698,9 +21107,9 @@ module Tables = struct }; } = _menhir_stack in let _3 : ( -# 697 "parsing/parser.mly" +# 698 "parsing/parser.mly" (string) -# 20704 "parsing/parser.ml" +# 21113 "parsing/parser.ml" ) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in let _1 : (Longident.t) = Obj.magic _1 in @@ -20708,9 +21117,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Longident.t) = -# 3502 "parsing/parser.mly" +# 3543 "parsing/parser.mly" ( Ldot(_1,_3) ) -# 20714 "parsing/parser.ml" +# 21123 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20733,9 +21142,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3501 "parsing/parser.mly" +# 3542 "parsing/parser.mly" ( Lident _1 ) -# 20739 "parsing/parser.ml" +# 21148 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20772,9 +21181,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Longident.t) = -# 3502 "parsing/parser.mly" +# 3543 "parsing/parser.mly" ( Ldot(_1,_3) ) -# 20778 "parsing/parser.ml" +# 21187 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20797,9 +21206,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3517 "parsing/parser.mly" +# 3558 "parsing/parser.mly" ( _1 ) -# 20803 "parsing/parser.ml" +# 21212 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20846,9 +21255,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3519 "parsing/parser.mly" +# 3560 "parsing/parser.mly" ( lapply ~loc:_sloc _1 _3 ) -# 20852 "parsing/parser.ml" +# 21261 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20886,9 +21295,9 @@ module Tables = struct let _endpos = _endpos__3_ in let _v : (Longident.t) = let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 3521 "parsing/parser.mly" +# 3562 "parsing/parser.mly" ( expecting _loc__3_ "module path" ) -# 20892 "parsing/parser.ml" +# 21301 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20911,9 +21320,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3514 "parsing/parser.mly" +# 3555 "parsing/parser.mly" ( _1 ) -# 20917 "parsing/parser.ml" +# 21326 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20943,9 +21352,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos_me_ in let _v : (Parsetree.module_expr) = -# 1373 "parsing/parser.mly" +# 1376 "parsing/parser.mly" ( me ) -# 20949 "parsing/parser.ml" +# 21358 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -20990,24 +21399,24 @@ module Tables = struct let _endpos = _endpos_me_ in let _v : (Parsetree.module_expr) = let _1 = let _1 = -# 1376 "parsing/parser.mly" +# 1379 "parsing/parser.mly" ( Pmod_constraint(me, mty) ) -# 20996 "parsing/parser.ml" +# 21405 "parsing/parser.ml" in let _endpos__1_ = _endpos_me_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 856 "parsing/parser.mly" +# 857 "parsing/parser.mly" ( mkmod ~loc:_sloc _1 ) -# 21005 "parsing/parser.ml" +# 21414 "parsing/parser.ml" in -# 1379 "parsing/parser.mly" +# 1382 "parsing/parser.mly" ( _1 ) -# 21011 "parsing/parser.ml" +# 21420 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21038,24 +21447,24 @@ module Tables = struct let _endpos = _endpos_body_ in let _v : (Parsetree.module_expr) = let _1 = let _1 = -# 1378 "parsing/parser.mly" +# 1381 "parsing/parser.mly" ( Pmod_functor(arg, body) ) -# 21044 "parsing/parser.ml" +# 21453 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_body_, _startpos_arg_) in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 856 "parsing/parser.mly" +# 857 "parsing/parser.mly" ( mkmod ~loc:_sloc _1 ) -# 21053 "parsing/parser.ml" +# 21462 "parsing/parser.ml" in -# 1379 "parsing/parser.mly" +# 1382 "parsing/parser.mly" ( _1 ) -# 21059 "parsing/parser.ml" +# 21468 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21085,9 +21494,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos_mty_ in let _v : (Parsetree.module_type) = -# 1616 "parsing/parser.mly" +# 1621 "parsing/parser.mly" ( mty ) -# 21091 "parsing/parser.ml" +# 21500 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21118,24 +21527,24 @@ module Tables = struct let _endpos = _endpos_body_ in let _v : (Parsetree.module_type) = let _1 = let _1 = -# 1619 "parsing/parser.mly" +# 1624 "parsing/parser.mly" ( Pmty_functor(arg, body) ) -# 21124 "parsing/parser.ml" +# 21533 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_body_, _startpos_arg_) in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 858 "parsing/parser.mly" +# 859 "parsing/parser.mly" ( mkmty ~loc:_sloc _1 ) -# 21133 "parsing/parser.ml" +# 21542 "parsing/parser.ml" in -# 1621 "parsing/parser.mly" +# 1626 "parsing/parser.mly" ( _1 ) -# 21139 "parsing/parser.ml" +# 21548 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21181,18 +21590,18 @@ module Tables = struct let _v : (Parsetree.module_expr) = let attrs = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 21187 "parsing/parser.ml" +# 21596 "parsing/parser.ml" in let _endpos = _endpos__4_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1212 "parsing/parser.mly" +# 1213 "parsing/parser.mly" ( mkmod ~loc:_sloc ~attrs (Pmod_structure s) ) -# 21196 "parsing/parser.ml" +# 21605 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21238,17 +21647,17 @@ module Tables = struct let _v : (Parsetree.module_expr) = let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 21244 "parsing/parser.ml" +# 21653 "parsing/parser.ml" in let _loc__4_ = (_startpos__4_, _endpos__4_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1214 "parsing/parser.mly" +# 1215 "parsing/parser.mly" ( unclosed "struct" _loc__1_ "end" _loc__4_ ) -# 21252 "parsing/parser.ml" +# 21661 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21301,30 +21710,30 @@ module Tables = struct let _v : (Parsetree.module_expr) = let args = let _1 = _1_inlined2 in -# 1178 "parsing/parser.mly" +# 1179 "parsing/parser.mly" ( _1 ) -# 21307 "parsing/parser.ml" +# 21716 "parsing/parser.ml" in let attrs = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 21315 "parsing/parser.ml" +# 21724 "parsing/parser.ml" in let _endpos = _endpos_me_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1216 "parsing/parser.mly" +# 1217 "parsing/parser.mly" ( wrap_mod_attrs ~loc:_sloc attrs ( List.fold_left (fun acc arg -> mkmod ~loc:_sloc (Pmod_functor (arg, acc)) ) me args ) ) -# 21328 "parsing/parser.ml" +# 21737 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21347,9 +21756,9 @@ module Tables = struct let _startpos = _startpos_me_ in let _endpos = _endpos_me_ in let _v : (Parsetree.module_expr) = -# 1222 "parsing/parser.mly" +# 1223 "parsing/parser.mly" ( me ) -# 21353 "parsing/parser.ml" +# 21762 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21379,9 +21788,9 @@ module Tables = struct let _startpos = _startpos_me_ in let _endpos = _endpos_attr_ in let _v : (Parsetree.module_expr) = -# 1224 "parsing/parser.mly" +# 1225 "parsing/parser.mly" ( Mod.attr me attr ) -# 21385 "parsing/parser.ml" +# 21794 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21410,30 +21819,30 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 21416 "parsing/parser.ml" +# 21825 "parsing/parser.ml" in -# 1228 "parsing/parser.mly" +# 1229 "parsing/parser.mly" ( Pmod_ident x ) -# 21422 "parsing/parser.ml" +# 21831 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 856 "parsing/parser.mly" +# 857 "parsing/parser.mly" ( mkmod ~loc:_sloc _1 ) -# 21431 "parsing/parser.ml" +# 21840 "parsing/parser.ml" in -# 1240 "parsing/parser.mly" +# 1241 "parsing/parser.mly" ( _1 ) -# 21437 "parsing/parser.ml" +# 21846 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21464,24 +21873,24 @@ module Tables = struct let _endpos = _endpos_me2_ in let _v : (Parsetree.module_expr) = let _1 = let _1 = -# 1231 "parsing/parser.mly" +# 1232 "parsing/parser.mly" ( Pmod_apply(me1, me2) ) -# 21470 "parsing/parser.ml" +# 21879 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_me2_, _startpos_me1_) in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 856 "parsing/parser.mly" +# 857 "parsing/parser.mly" ( mkmod ~loc:_sloc _1 ) -# 21479 "parsing/parser.ml" +# 21888 "parsing/parser.ml" in -# 1240 "parsing/parser.mly" +# 1241 "parsing/parser.mly" ( _1 ) -# 21485 "parsing/parser.ml" +# 21894 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21523,10 +21932,10 @@ module Tables = struct let _symbolstartpos = _startpos_me1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1234 "parsing/parser.mly" +# 1235 "parsing/parser.mly" ( (* TODO review mkmod location *) Pmod_apply(me1, mkmod ~loc:_sloc (Pmod_structure [])) ) -# 21530 "parsing/parser.ml" +# 21939 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos__3_, _startpos_me1_) in @@ -21534,15 +21943,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 856 "parsing/parser.mly" +# 857 "parsing/parser.mly" ( mkmod ~loc:_sloc _1 ) -# 21540 "parsing/parser.ml" +# 21949 "parsing/parser.ml" in -# 1240 "parsing/parser.mly" +# 1241 "parsing/parser.mly" ( _1 ) -# 21546 "parsing/parser.ml" +# 21955 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21566,24 +21975,24 @@ module Tables = struct let _endpos = _endpos_ex_ in let _v : (Parsetree.module_expr) = let _1 = let _1 = -# 1238 "parsing/parser.mly" +# 1239 "parsing/parser.mly" ( Pmod_extension ex ) -# 21572 "parsing/parser.ml" +# 21981 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_ex_, _startpos_ex_) in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 856 "parsing/parser.mly" +# 857 "parsing/parser.mly" ( mkmod ~loc:_sloc _1 ) -# 21581 "parsing/parser.ml" +# 21990 "parsing/parser.ml" in -# 1240 "parsing/parser.mly" +# 1241 "parsing/parser.mly" ( _1 ) -# 21587 "parsing/parser.ml" +# 21996 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21602,17 +22011,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let x : ( -# 697 "parsing/parser.mly" +# 698 "parsing/parser.mly" (string) -# 21608 "parsing/parser.ml" +# 22017 "parsing/parser.ml" ) = Obj.magic x in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos_x_ in let _endpos = _endpos_x_ in let _v : (string option) = -# 1195 "parsing/parser.mly" +# 1196 "parsing/parser.mly" ( Some x ) -# 21616 "parsing/parser.ml" +# 22025 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21635,9 +22044,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string option) = -# 1198 "parsing/parser.mly" +# 1199 "parsing/parser.mly" ( None ) -# 21641 "parsing/parser.ml" +# 22050 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21695,9 +22104,9 @@ module Tables = struct let _1_inlined3 : (Longident.t) = Obj.magic _1_inlined3 in let _5 : unit = Obj.magic _5 in let _1_inlined2 : ( -# 697 "parsing/parser.mly" +# 698 "parsing/parser.mly" (string) -# 21701 "parsing/parser.ml" +# 22110 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in let ext : (string Asttypes.loc option) = Obj.magic ext in @@ -21708,9 +22117,9 @@ module Tables = struct let _v : (Parsetree.module_substitution * string Asttypes.loc option) = let attrs2 = let _1 = _1_inlined4 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 21714 "parsing/parser.ml" +# 22123 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined4_ in @@ -21720,9 +22129,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 21726 "parsing/parser.ml" +# 22135 "parsing/parser.ml" in let uid = @@ -21731,31 +22140,31 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 21737 "parsing/parser.ml" +# 22146 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 21745 "parsing/parser.ml" +# 22154 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1651 "parsing/parser.mly" +# 1656 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in let docs = symbol_docs _sloc in Ms.mk uid body ~attrs ~loc ~docs, ext ) -# 21759 "parsing/parser.ml" +# 22168 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21806,9 +22215,9 @@ module Tables = struct let _6 : unit = Obj.magic _6 in let _5 : unit = Obj.magic _5 in let _1_inlined2 : ( -# 697 "parsing/parser.mly" +# 698 "parsing/parser.mly" (string) -# 21812 "parsing/parser.ml" +# 22221 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in let _2 : (string Asttypes.loc option) = Obj.magic _2 in @@ -21822,24 +22231,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 21828 "parsing/parser.ml" +# 22237 "parsing/parser.ml" in let _3 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 21836 "parsing/parser.ml" +# 22245 "parsing/parser.ml" in let _loc__6_ = (_startpos__6_, _endpos__6_) in -# 1658 "parsing/parser.mly" +# 1663 "parsing/parser.mly" ( expecting _loc__6_ "module path" ) -# 21843 "parsing/parser.ml" +# 22252 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21885,18 +22294,18 @@ module Tables = struct let _v : (Parsetree.module_type) = let attrs = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 21891 "parsing/parser.ml" +# 22300 "parsing/parser.ml" in let _endpos = _endpos__4_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1504 "parsing/parser.mly" +# 1507 "parsing/parser.mly" ( mkmty ~loc:_sloc ~attrs (Pmty_signature s) ) -# 21900 "parsing/parser.ml" +# 22309 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -21942,17 +22351,17 @@ module Tables = struct let _v : (Parsetree.module_type) = let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 21948 "parsing/parser.ml" +# 22357 "parsing/parser.ml" in let _loc__4_ = (_startpos__4_, _endpos__4_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1506 "parsing/parser.mly" +# 1509 "parsing/parser.mly" ( unclosed "sig" _loc__1_ "end" _loc__4_ ) -# 21956 "parsing/parser.ml" +# 22365 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22005,30 +22414,30 @@ module Tables = struct let _v : (Parsetree.module_type) = let args = let _1 = _1_inlined2 in -# 1178 "parsing/parser.mly" +# 1179 "parsing/parser.mly" ( _1 ) -# 22011 "parsing/parser.ml" +# 22420 "parsing/parser.ml" in let attrs = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 22019 "parsing/parser.ml" +# 22428 "parsing/parser.ml" in let _endpos = _endpos_mty_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1510 "parsing/parser.mly" +# 1513 "parsing/parser.mly" ( wrap_mty_attrs ~loc:_sloc attrs ( List.fold_left (fun acc arg -> mkmty ~loc:_sloc (Pmty_functor (arg, acc)) ) mty args ) ) -# 22032 "parsing/parser.ml" +# 22441 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22081,18 +22490,18 @@ module Tables = struct let _v : (Parsetree.module_type) = let _4 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 22087 "parsing/parser.ml" +# 22496 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1516 "parsing/parser.mly" +# 1519 "parsing/parser.mly" ( mkmty ~loc:_sloc ~attrs:_4 (Pmty_typeof _5) ) -# 22096 "parsing/parser.ml" +# 22505 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22129,9 +22538,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.module_type) = -# 1518 "parsing/parser.mly" +# 1521 "parsing/parser.mly" ( _2 ) -# 22135 "parsing/parser.ml" +# 22544 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22170,9 +22579,9 @@ module Tables = struct let _v : (Parsetree.module_type) = let _loc__3_ = (_startpos__3_, _endpos__3_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1520 "parsing/parser.mly" +# 1523 "parsing/parser.mly" ( unclosed "(" _loc__1_ ")" _loc__3_ ) -# 22176 "parsing/parser.ml" +# 22585 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22202,9 +22611,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.module_type) = -# 1522 "parsing/parser.mly" +# 1525 "parsing/parser.mly" ( Mty.attr _1 _2 ) -# 22208 "parsing/parser.ml" +# 22617 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22233,30 +22642,30 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 22239 "parsing/parser.ml" +# 22648 "parsing/parser.ml" in -# 1525 "parsing/parser.mly" +# 1528 "parsing/parser.mly" ( Pmty_ident _1 ) -# 22245 "parsing/parser.ml" +# 22654 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 858 "parsing/parser.mly" +# 859 "parsing/parser.mly" ( mkmty ~loc:_sloc _1 ) -# 22254 "parsing/parser.ml" +# 22663 "parsing/parser.ml" in -# 1536 "parsing/parser.mly" +# 1539 "parsing/parser.mly" ( _1 ) -# 22260 "parsing/parser.ml" +# 22669 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22294,24 +22703,24 @@ module Tables = struct let _endpos = _endpos__3_ in let _v : (Parsetree.module_type) = let _1 = let _1 = -# 1528 "parsing/parser.mly" +# 1531 "parsing/parser.mly" ( Pmty_functor(Named (mknoloc None, _1), _3) ) -# 22300 "parsing/parser.ml" +# 22709 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 858 "parsing/parser.mly" +# 859 "parsing/parser.mly" ( mkmty ~loc:_sloc _1 ) -# 22309 "parsing/parser.ml" +# 22718 "parsing/parser.ml" in -# 1536 "parsing/parser.mly" +# 1539 "parsing/parser.mly" ( _1 ) -# 22315 "parsing/parser.ml" +# 22724 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22353,18 +22762,18 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 22357 "parsing/parser.ml" +# 22766 "parsing/parser.ml" in -# 947 "parsing/parser.mly" +# 948 "parsing/parser.mly" ( xs ) -# 22362 "parsing/parser.ml" +# 22771 "parsing/parser.ml" in -# 1530 "parsing/parser.mly" +# 1533 "parsing/parser.mly" ( Pmty_with(_1, _3) ) -# 22368 "parsing/parser.ml" +# 22777 "parsing/parser.ml" in let _endpos__1_ = _endpos_xs_ in @@ -22372,15 +22781,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 858 "parsing/parser.mly" +# 859 "parsing/parser.mly" ( mkmty ~loc:_sloc _1 ) -# 22378 "parsing/parser.ml" +# 22787 "parsing/parser.ml" in -# 1536 "parsing/parser.mly" +# 1539 "parsing/parser.mly" ( _1 ) -# 22384 "parsing/parser.ml" +# 22793 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22404,23 +22813,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.module_type) = let _1 = let _1 = -# 1534 "parsing/parser.mly" +# 1537 "parsing/parser.mly" ( Pmty_extension _1 ) -# 22410 "parsing/parser.ml" +# 22819 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 858 "parsing/parser.mly" +# 859 "parsing/parser.mly" ( mkmty ~loc:_sloc _1 ) -# 22418 "parsing/parser.ml" +# 22827 "parsing/parser.ml" in -# 1536 "parsing/parser.mly" +# 1539 "parsing/parser.mly" ( _1 ) -# 22424 "parsing/parser.ml" +# 22833 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22487,9 +22896,9 @@ module Tables = struct let _v : (Parsetree.module_type_declaration * string Asttypes.loc option) = let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 22493 "parsing/parser.ml" +# 22902 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -22499,31 +22908,31 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 22505 "parsing/parser.ml" +# 22914 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 22513 "parsing/parser.ml" +# 22922 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1450 "parsing/parser.mly" +# 1453 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in let docs = symbol_docs _sloc in Mtd.mk id ?typ ~attrs ~loc ~docs, ext ) -# 22527 "parsing/parser.ml" +# 22936 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22546,9 +22955,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3524 "parsing/parser.mly" +# 3565 "parsing/parser.mly" ( _1 ) -# 22552 "parsing/parser.ml" +# 22961 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22564,9 +22973,9 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : (Asttypes.mutable_flag) = -# 3601 "parsing/parser.mly" +# 3642 "parsing/parser.mly" ( Immutable ) -# 22570 "parsing/parser.ml" +# 22979 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22589,9 +22998,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.mutable_flag) = -# 3602 "parsing/parser.mly" +# 3643 "parsing/parser.mly" ( Mutable ) -# 22595 "parsing/parser.ml" +# 23004 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22607,9 +23016,9 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : (Asttypes.mutable_flag * Asttypes.virtual_flag) = -# 3610 "parsing/parser.mly" +# 3651 "parsing/parser.mly" ( Immutable, Concrete ) -# 22613 "parsing/parser.ml" +# 23022 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22632,9 +23041,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.mutable_flag * Asttypes.virtual_flag) = -# 3612 "parsing/parser.mly" +# 3653 "parsing/parser.mly" ( Mutable, Concrete ) -# 22638 "parsing/parser.ml" +# 23047 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22657,9 +23066,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.mutable_flag * Asttypes.virtual_flag) = -# 3614 "parsing/parser.mly" +# 3655 "parsing/parser.mly" ( Immutable, Virtual ) -# 22663 "parsing/parser.ml" +# 23072 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22689,9 +23098,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.mutable_flag * Asttypes.virtual_flag) = -# 3617 "parsing/parser.mly" +# 3658 "parsing/parser.mly" ( Mutable, Virtual ) -# 22695 "parsing/parser.ml" +# 23104 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22721,9 +23130,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.mutable_flag * Asttypes.virtual_flag) = -# 3617 "parsing/parser.mly" +# 3658 "parsing/parser.mly" ( Mutable, Virtual ) -# 22727 "parsing/parser.ml" +# 23136 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22753,9 +23162,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.label) = -# 3574 "parsing/parser.mly" +# 3615 "parsing/parser.mly" ( _2 ) -# 22759 "parsing/parser.ml" +# 23168 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22774,9 +23183,9 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 22780 "parsing/parser.ml" +# 23189 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -22786,15 +23195,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 22792 "parsing/parser.ml" +# 23201 "parsing/parser.ml" in # 221 "<standard.mly>" ( [ x ] ) -# 22798 "parsing/parser.ml" +# 23207 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22820,9 +23229,9 @@ module Tables = struct } = _menhir_stack in let xs : (string Asttypes.loc list) = Obj.magic xs in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 22826 "parsing/parser.ml" +# 23235 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -22832,15 +23241,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 22838 "parsing/parser.ml" +# 23247 "parsing/parser.ml" in # 223 "<standard.mly>" ( x :: xs ) -# 22844 "parsing/parser.ml" +# 23253 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22859,22 +23268,22 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let s : ( -# 685 "parsing/parser.mly" +# 686 "parsing/parser.mly" (string * Location.t * string option) -# 22865 "parsing/parser.ml" +# 23274 "parsing/parser.ml" ) = Obj.magic s in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos_s_ in let _endpos = _endpos_s_ in let _v : (string list) = let x = -# 3570 "parsing/parser.mly" +# 3611 "parsing/parser.mly" ( let body, _, _ = s in body ) -# 22873 "parsing/parser.ml" +# 23282 "parsing/parser.ml" in # 221 "<standard.mly>" ( [ x ] ) -# 22878 "parsing/parser.ml" +# 23287 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22900,22 +23309,22 @@ module Tables = struct } = _menhir_stack in let xs : (string list) = Obj.magic xs in let s : ( -# 685 "parsing/parser.mly" +# 686 "parsing/parser.mly" (string * Location.t * string option) -# 22906 "parsing/parser.ml" +# 23315 "parsing/parser.ml" ) = Obj.magic s in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos_s_ in let _endpos = _endpos_xs_ in let _v : (string list) = let x = -# 3570 "parsing/parser.mly" +# 3611 "parsing/parser.mly" ( let body, _, _ = s in body ) -# 22914 "parsing/parser.ml" +# 23323 "parsing/parser.ml" in # 223 "<standard.mly>" ( x :: xs ) -# 22919 "parsing/parser.ml" +# 23328 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22938,14 +23347,14 @@ module Tables = struct let _startpos = _startpos_ty_ in let _endpos = _endpos_ty_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = -# 3597 "parsing/parser.mly" +# 3638 "parsing/parser.mly" ( Public ) -# 22944 "parsing/parser.ml" +# 23353 "parsing/parser.ml" in -# 2896 "parsing/parser.mly" +# 2903 "parsing/parser.mly" ( (Ptype_abstract, priv, Some ty) ) -# 22949 "parsing/parser.ml" +# 23358 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -22975,14 +23384,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos_ty_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = -# 3598 "parsing/parser.mly" +# 3639 "parsing/parser.mly" ( Private ) -# 22981 "parsing/parser.ml" +# 23390 "parsing/parser.ml" in -# 2896 "parsing/parser.mly" +# 2903 "parsing/parser.mly" ( (Ptype_abstract, priv, Some ty) ) -# 22986 "parsing/parser.ml" +# 23395 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23005,26 +23414,26 @@ module Tables = struct let _startpos = _startpos_cs_ in let _endpos = _endpos_cs_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = -# 3597 "parsing/parser.mly" +# 3638 "parsing/parser.mly" ( Public ) -# 23011 "parsing/parser.ml" +# 23420 "parsing/parser.ml" in let oty = let _1 = # 124 "<standard.mly>" ( None ) -# 23017 "parsing/parser.ml" +# 23426 "parsing/parser.ml" in -# 2912 "parsing/parser.mly" +# 2919 "parsing/parser.mly" ( _1 ) -# 23022 "parsing/parser.ml" +# 23431 "parsing/parser.ml" in -# 2900 "parsing/parser.mly" +# 2907 "parsing/parser.mly" ( (Ptype_variant cs, priv, oty) ) -# 23028 "parsing/parser.ml" +# 23437 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23054,26 +23463,26 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos_cs_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = -# 3598 "parsing/parser.mly" +# 3639 "parsing/parser.mly" ( Private ) -# 23060 "parsing/parser.ml" +# 23469 "parsing/parser.ml" in let oty = let _1 = # 124 "<standard.mly>" ( None ) -# 23066 "parsing/parser.ml" +# 23475 "parsing/parser.ml" in -# 2912 "parsing/parser.mly" +# 2919 "parsing/parser.mly" ( _1 ) -# 23071 "parsing/parser.ml" +# 23480 "parsing/parser.ml" in -# 2900 "parsing/parser.mly" +# 2907 "parsing/parser.mly" ( (Ptype_variant cs, priv, oty) ) -# 23077 "parsing/parser.ml" +# 23486 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23110,33 +23519,33 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos_cs_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = -# 3597 "parsing/parser.mly" +# 3638 "parsing/parser.mly" ( Public ) -# 23116 "parsing/parser.ml" +# 23525 "parsing/parser.ml" in let oty = let _1 = let x = # 191 "<standard.mly>" ( x ) -# 23123 "parsing/parser.ml" +# 23532 "parsing/parser.ml" in # 126 "<standard.mly>" ( Some x ) -# 23128 "parsing/parser.ml" +# 23537 "parsing/parser.ml" in -# 2912 "parsing/parser.mly" +# 2919 "parsing/parser.mly" ( _1 ) -# 23134 "parsing/parser.ml" +# 23543 "parsing/parser.ml" in -# 2900 "parsing/parser.mly" +# 2907 "parsing/parser.mly" ( (Ptype_variant cs, priv, oty) ) -# 23140 "parsing/parser.ml" +# 23549 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23180,33 +23589,33 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos_cs_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = -# 3598 "parsing/parser.mly" +# 3639 "parsing/parser.mly" ( Private ) -# 23186 "parsing/parser.ml" +# 23595 "parsing/parser.ml" in let oty = let _1 = let x = # 191 "<standard.mly>" ( x ) -# 23193 "parsing/parser.ml" +# 23602 "parsing/parser.ml" in # 126 "<standard.mly>" ( Some x ) -# 23198 "parsing/parser.ml" +# 23607 "parsing/parser.ml" in -# 2912 "parsing/parser.mly" +# 2919 "parsing/parser.mly" ( _1 ) -# 23204 "parsing/parser.ml" +# 23613 "parsing/parser.ml" in -# 2900 "parsing/parser.mly" +# 2907 "parsing/parser.mly" ( (Ptype_variant cs, priv, oty) ) -# 23210 "parsing/parser.ml" +# 23619 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23229,26 +23638,26 @@ module Tables = struct let _startpos = _startpos__3_ in let _endpos = _endpos__3_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = -# 3597 "parsing/parser.mly" +# 3638 "parsing/parser.mly" ( Public ) -# 23235 "parsing/parser.ml" +# 23644 "parsing/parser.ml" in let oty = let _1 = # 124 "<standard.mly>" ( None ) -# 23241 "parsing/parser.ml" +# 23650 "parsing/parser.ml" in -# 2912 "parsing/parser.mly" +# 2919 "parsing/parser.mly" ( _1 ) -# 23246 "parsing/parser.ml" +# 23655 "parsing/parser.ml" in -# 2904 "parsing/parser.mly" +# 2911 "parsing/parser.mly" ( (Ptype_open, priv, oty) ) -# 23252 "parsing/parser.ml" +# 23661 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23278,26 +23687,26 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = -# 3598 "parsing/parser.mly" +# 3639 "parsing/parser.mly" ( Private ) -# 23284 "parsing/parser.ml" +# 23693 "parsing/parser.ml" in let oty = let _1 = # 124 "<standard.mly>" ( None ) -# 23290 "parsing/parser.ml" +# 23699 "parsing/parser.ml" in -# 2912 "parsing/parser.mly" +# 2919 "parsing/parser.mly" ( _1 ) -# 23295 "parsing/parser.ml" +# 23704 "parsing/parser.ml" in -# 2904 "parsing/parser.mly" +# 2911 "parsing/parser.mly" ( (Ptype_open, priv, oty) ) -# 23301 "parsing/parser.ml" +# 23710 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23334,33 +23743,33 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos__3_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = -# 3597 "parsing/parser.mly" +# 3638 "parsing/parser.mly" ( Public ) -# 23340 "parsing/parser.ml" +# 23749 "parsing/parser.ml" in let oty = let _1 = let x = # 191 "<standard.mly>" ( x ) -# 23347 "parsing/parser.ml" +# 23756 "parsing/parser.ml" in # 126 "<standard.mly>" ( Some x ) -# 23352 "parsing/parser.ml" +# 23761 "parsing/parser.ml" in -# 2912 "parsing/parser.mly" +# 2919 "parsing/parser.mly" ( _1 ) -# 23358 "parsing/parser.ml" +# 23767 "parsing/parser.ml" in -# 2904 "parsing/parser.mly" +# 2911 "parsing/parser.mly" ( (Ptype_open, priv, oty) ) -# 23364 "parsing/parser.ml" +# 23773 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23404,33 +23813,33 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos__3_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = -# 3598 "parsing/parser.mly" +# 3639 "parsing/parser.mly" ( Private ) -# 23410 "parsing/parser.ml" +# 23819 "parsing/parser.ml" in let oty = let _1 = let x = # 191 "<standard.mly>" ( x ) -# 23417 "parsing/parser.ml" +# 23826 "parsing/parser.ml" in # 126 "<standard.mly>" ( Some x ) -# 23422 "parsing/parser.ml" +# 23831 "parsing/parser.ml" in -# 2912 "parsing/parser.mly" +# 2919 "parsing/parser.mly" ( _1 ) -# 23428 "parsing/parser.ml" +# 23837 "parsing/parser.ml" in -# 2904 "parsing/parser.mly" +# 2911 "parsing/parser.mly" ( (Ptype_open, priv, oty) ) -# 23434 "parsing/parser.ml" +# 23843 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23467,26 +23876,26 @@ module Tables = struct let _startpos = _startpos__3_ in let _endpos = _endpos__5_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = -# 3597 "parsing/parser.mly" +# 3638 "parsing/parser.mly" ( Public ) -# 23473 "parsing/parser.ml" +# 23882 "parsing/parser.ml" in let oty = let _1 = # 124 "<standard.mly>" ( None ) -# 23479 "parsing/parser.ml" +# 23888 "parsing/parser.ml" in -# 2912 "parsing/parser.mly" +# 2919 "parsing/parser.mly" ( _1 ) -# 23484 "parsing/parser.ml" +# 23893 "parsing/parser.ml" in -# 2908 "parsing/parser.mly" +# 2915 "parsing/parser.mly" ( (Ptype_record ls, priv, oty) ) -# 23490 "parsing/parser.ml" +# 23899 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23530,26 +23939,26 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__5_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = -# 3598 "parsing/parser.mly" +# 3639 "parsing/parser.mly" ( Private ) -# 23536 "parsing/parser.ml" +# 23945 "parsing/parser.ml" in let oty = let _1 = # 124 "<standard.mly>" ( None ) -# 23542 "parsing/parser.ml" +# 23951 "parsing/parser.ml" in -# 2912 "parsing/parser.mly" +# 2919 "parsing/parser.mly" ( _1 ) -# 23547 "parsing/parser.ml" +# 23956 "parsing/parser.ml" in -# 2908 "parsing/parser.mly" +# 2915 "parsing/parser.mly" ( (Ptype_record ls, priv, oty) ) -# 23553 "parsing/parser.ml" +# 23962 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23600,33 +24009,33 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos__5_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = -# 3597 "parsing/parser.mly" +# 3638 "parsing/parser.mly" ( Public ) -# 23606 "parsing/parser.ml" +# 24015 "parsing/parser.ml" in let oty = let _1 = let x = # 191 "<standard.mly>" ( x ) -# 23613 "parsing/parser.ml" +# 24022 "parsing/parser.ml" in # 126 "<standard.mly>" ( Some x ) -# 23618 "parsing/parser.ml" +# 24027 "parsing/parser.ml" in -# 2912 "parsing/parser.mly" +# 2919 "parsing/parser.mly" ( _1 ) -# 23624 "parsing/parser.ml" +# 24033 "parsing/parser.ml" in -# 2908 "parsing/parser.mly" +# 2915 "parsing/parser.mly" ( (Ptype_record ls, priv, oty) ) -# 23630 "parsing/parser.ml" +# 24039 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23684,33 +24093,33 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos__5_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = let priv = -# 3598 "parsing/parser.mly" +# 3639 "parsing/parser.mly" ( Private ) -# 23690 "parsing/parser.ml" +# 24099 "parsing/parser.ml" in let oty = let _1 = let x = # 191 "<standard.mly>" ( x ) -# 23697 "parsing/parser.ml" +# 24106 "parsing/parser.ml" in # 126 "<standard.mly>" ( Some x ) -# 23702 "parsing/parser.ml" +# 24111 "parsing/parser.ml" in -# 2912 "parsing/parser.mly" +# 2919 "parsing/parser.mly" ( _1 ) -# 23708 "parsing/parser.ml" +# 24117 "parsing/parser.ml" in -# 2908 "parsing/parser.mly" +# 2915 "parsing/parser.mly" ( (Ptype_record ls, priv, oty) ) -# 23714 "parsing/parser.ml" +# 24123 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23763,37 +24172,37 @@ module Tables = struct let _v : (Parsetree.open_declaration * string Asttypes.loc option) = let attrs2 = let _1 = _1_inlined2 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 23769 "parsing/parser.ml" +# 24178 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined2_ in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 23778 "parsing/parser.ml" +# 24187 "parsing/parser.ml" in let override = -# 3644 "parsing/parser.mly" +# 3685 "parsing/parser.mly" ( Fresh ) -# 23784 "parsing/parser.ml" +# 24193 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1469 "parsing/parser.mly" +# 1472 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in let docs = symbol_docs _sloc in Opn.mk me ~override ~attrs ~loc ~docs, ext ) -# 23797 "parsing/parser.ml" +# 24206 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23853,40 +24262,40 @@ module Tables = struct let _v : (Parsetree.open_declaration * string Asttypes.loc option) = let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 23859 "parsing/parser.ml" +# 24268 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in let attrs1 = let _1 = _1_inlined2 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 23868 "parsing/parser.ml" +# 24277 "parsing/parser.ml" in let override = let _1 = _1_inlined1 in -# 3645 "parsing/parser.mly" +# 3686 "parsing/parser.mly" ( Override ) -# 23876 "parsing/parser.ml" +# 24285 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1469 "parsing/parser.mly" +# 1472 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in let docs = symbol_docs _sloc in Opn.mk me ~override ~attrs ~loc ~docs, ext ) -# 23890 "parsing/parser.ml" +# 24299 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -23939,9 +24348,9 @@ module Tables = struct let _v : (Parsetree.open_description * string Asttypes.loc option) = let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 23945 "parsing/parser.ml" +# 24354 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -23951,36 +24360,36 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 23957 "parsing/parser.ml" +# 24366 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 23965 "parsing/parser.ml" +# 24374 "parsing/parser.ml" in let override = -# 3644 "parsing/parser.mly" +# 3685 "parsing/parser.mly" ( Fresh ) -# 23971 "parsing/parser.ml" +# 24380 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1484 "parsing/parser.mly" +# 1487 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in let docs = symbol_docs _sloc in Opn.mk id ~override ~attrs ~loc ~docs, ext ) -# 23984 "parsing/parser.ml" +# 24393 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24040,9 +24449,9 @@ module Tables = struct let _v : (Parsetree.open_description * string Asttypes.loc option) = let attrs2 = let _1 = _1_inlined4 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 24046 "parsing/parser.ml" +# 24455 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined4_ in @@ -24052,39 +24461,39 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 24058 "parsing/parser.ml" +# 24467 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined2 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 24066 "parsing/parser.ml" +# 24475 "parsing/parser.ml" in let override = let _1 = _1_inlined1 in -# 3645 "parsing/parser.mly" +# 3686 "parsing/parser.mly" ( Override ) -# 24074 "parsing/parser.ml" +# 24483 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1484 "parsing/parser.mly" +# 1487 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in let docs = symbol_docs _sloc in Opn.mk id ~override ~attrs ~loc ~docs, ext ) -# 24088 "parsing/parser.ml" +# 24497 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24103,17 +24512,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 671 "parsing/parser.mly" +# 672 "parsing/parser.mly" (string) -# 24109 "parsing/parser.ml" +# 24518 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = -# 3440 "parsing/parser.mly" +# 3481 "parsing/parser.mly" ( _1 ) -# 24117 "parsing/parser.ml" +# 24526 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24132,17 +24541,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 629 "parsing/parser.mly" +# 630 "parsing/parser.mly" (string) -# 24138 "parsing/parser.ml" +# 24547 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = -# 3441 "parsing/parser.mly" +# 3482 "parsing/parser.mly" ( _1 ) -# 24146 "parsing/parser.ml" +# 24555 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24161,17 +24570,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 630 "parsing/parser.mly" +# 631 "parsing/parser.mly" (string) -# 24167 "parsing/parser.ml" +# 24576 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = -# 3442 "parsing/parser.mly" +# 3483 "parsing/parser.mly" ( _1 ) -# 24175 "parsing/parser.ml" +# 24584 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24211,17 +24620,17 @@ module Tables = struct let _3 : (string) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in let _1 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 24217 "parsing/parser.ml" +# 24626 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__4_ in let _v : (Asttypes.label) = -# 3443 "parsing/parser.mly" +# 3484 "parsing/parser.mly" ( "."^ _1 ^"(" ^ _3 ^ ")" ) -# 24225 "parsing/parser.ml" +# 24634 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24268,17 +24677,17 @@ module Tables = struct let _3 : (string) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in let _1 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 24274 "parsing/parser.ml" +# 24683 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__5_ in let _v : (Asttypes.label) = -# 3444 "parsing/parser.mly" +# 3485 "parsing/parser.mly" ( "."^ _1 ^ "(" ^ _3 ^ ")<-" ) -# 24282 "parsing/parser.ml" +# 24691 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24318,17 +24727,17 @@ module Tables = struct let _3 : (string) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in let _1 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 24324 "parsing/parser.ml" +# 24733 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__4_ in let _v : (Asttypes.label) = -# 3445 "parsing/parser.mly" +# 3486 "parsing/parser.mly" ( "."^ _1 ^"[" ^ _3 ^ "]" ) -# 24332 "parsing/parser.ml" +# 24741 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24375,17 +24784,17 @@ module Tables = struct let _3 : (string) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in let _1 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 24381 "parsing/parser.ml" +# 24790 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__5_ in let _v : (Asttypes.label) = -# 3446 "parsing/parser.mly" +# 3487 "parsing/parser.mly" ( "."^ _1 ^ "[" ^ _3 ^ "]<-" ) -# 24389 "parsing/parser.ml" +# 24798 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24425,17 +24834,17 @@ module Tables = struct let _3 : (string) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in let _1 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 24431 "parsing/parser.ml" +# 24840 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__4_ in let _v : (Asttypes.label) = -# 3447 "parsing/parser.mly" +# 3488 "parsing/parser.mly" ( "."^ _1 ^"{" ^ _3 ^ "}" ) -# 24439 "parsing/parser.ml" +# 24848 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24482,17 +24891,17 @@ module Tables = struct let _3 : (string) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in let _1 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 24488 "parsing/parser.ml" +# 24897 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__5_ in let _v : (Asttypes.label) = -# 3448 "parsing/parser.mly" +# 3489 "parsing/parser.mly" ( "."^ _1 ^ "{" ^ _3 ^ "}<-" ) -# 24496 "parsing/parser.ml" +# 24905 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24511,17 +24920,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 682 "parsing/parser.mly" +# 683 "parsing/parser.mly" (string) -# 24517 "parsing/parser.ml" +# 24926 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = -# 3449 "parsing/parser.mly" +# 3490 "parsing/parser.mly" ( _1 ) -# 24525 "parsing/parser.ml" +# 24934 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24544,9 +24953,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = -# 3450 "parsing/parser.mly" +# 3491 "parsing/parser.mly" ( "!" ) -# 24550 "parsing/parser.ml" +# 24959 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24565,22 +24974,22 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let op : ( -# 623 "parsing/parser.mly" +# 624 "parsing/parser.mly" (string) -# 24571 "parsing/parser.ml" +# 24980 "parsing/parser.ml" ) = Obj.magic op in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos_op_ in let _endpos = _endpos_op_ in let _v : (Asttypes.label) = let _1 = -# 3454 "parsing/parser.mly" +# 3495 "parsing/parser.mly" ( op ) -# 24579 "parsing/parser.ml" +# 24988 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 24584 "parsing/parser.ml" +# 24993 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24599,22 +25008,22 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let op : ( -# 624 "parsing/parser.mly" +# 625 "parsing/parser.mly" (string) -# 24605 "parsing/parser.ml" +# 25014 "parsing/parser.ml" ) = Obj.magic op in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos_op_ in let _endpos = _endpos_op_ in let _v : (Asttypes.label) = let _1 = -# 3455 "parsing/parser.mly" +# 3496 "parsing/parser.mly" ( op ) -# 24613 "parsing/parser.ml" +# 25022 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 24618 "parsing/parser.ml" +# 25027 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24633,22 +25042,22 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let op : ( -# 625 "parsing/parser.mly" +# 626 "parsing/parser.mly" (string) -# 24639 "parsing/parser.ml" +# 25048 "parsing/parser.ml" ) = Obj.magic op in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos_op_ in let _endpos = _endpos_op_ in let _v : (Asttypes.label) = let _1 = -# 3456 "parsing/parser.mly" +# 3497 "parsing/parser.mly" ( op ) -# 24647 "parsing/parser.ml" +# 25056 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 24652 "parsing/parser.ml" +# 25061 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24667,22 +25076,22 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let op : ( -# 626 "parsing/parser.mly" +# 627 "parsing/parser.mly" (string) -# 24673 "parsing/parser.ml" +# 25082 "parsing/parser.ml" ) = Obj.magic op in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos_op_ in let _endpos = _endpos_op_ in let _v : (Asttypes.label) = let _1 = -# 3457 "parsing/parser.mly" +# 3498 "parsing/parser.mly" ( op ) -# 24681 "parsing/parser.ml" +# 25090 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 24686 "parsing/parser.ml" +# 25095 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24701,22 +25110,22 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let op : ( -# 627 "parsing/parser.mly" +# 628 "parsing/parser.mly" (string) -# 24707 "parsing/parser.ml" +# 25116 "parsing/parser.ml" ) = Obj.magic op in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos_op_ in let _endpos = _endpos_op_ in let _v : (Asttypes.label) = let _1 = -# 3458 "parsing/parser.mly" +# 3499 "parsing/parser.mly" ( op ) -# 24715 "parsing/parser.ml" +# 25124 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 24720 "parsing/parser.ml" +# 25129 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24739,14 +25148,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3459 "parsing/parser.mly" +# 3500 "parsing/parser.mly" ("+") -# 24745 "parsing/parser.ml" +# 25154 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 24750 "parsing/parser.ml" +# 25159 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24769,14 +25178,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3460 "parsing/parser.mly" +# 3501 "parsing/parser.mly" ("+.") -# 24775 "parsing/parser.ml" +# 25184 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 24780 "parsing/parser.ml" +# 25189 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24799,14 +25208,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3461 "parsing/parser.mly" +# 3502 "parsing/parser.mly" ("+=") -# 24805 "parsing/parser.ml" +# 25214 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 24810 "parsing/parser.ml" +# 25219 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24829,14 +25238,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3462 "parsing/parser.mly" +# 3503 "parsing/parser.mly" ("-") -# 24835 "parsing/parser.ml" +# 25244 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 24840 "parsing/parser.ml" +# 25249 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24859,14 +25268,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3463 "parsing/parser.mly" +# 3504 "parsing/parser.mly" ("-.") -# 24865 "parsing/parser.ml" +# 25274 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 24870 "parsing/parser.ml" +# 25279 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24889,14 +25298,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3464 "parsing/parser.mly" +# 3505 "parsing/parser.mly" ("*") -# 24895 "parsing/parser.ml" +# 25304 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 24900 "parsing/parser.ml" +# 25309 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24919,14 +25328,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3465 "parsing/parser.mly" +# 3506 "parsing/parser.mly" ("%") -# 24925 "parsing/parser.ml" +# 25334 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 24930 "parsing/parser.ml" +# 25339 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24949,14 +25358,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3466 "parsing/parser.mly" +# 3507 "parsing/parser.mly" ("=") -# 24955 "parsing/parser.ml" +# 25364 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 24960 "parsing/parser.ml" +# 25369 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -24979,14 +25388,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3467 "parsing/parser.mly" +# 3508 "parsing/parser.mly" ("<") -# 24985 "parsing/parser.ml" +# 25394 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 24990 "parsing/parser.ml" +# 25399 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25009,14 +25418,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3468 "parsing/parser.mly" +# 3509 "parsing/parser.mly" (">") -# 25015 "parsing/parser.ml" +# 25424 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 25020 "parsing/parser.ml" +# 25429 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25039,14 +25448,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3469 "parsing/parser.mly" +# 3510 "parsing/parser.mly" ("or") -# 25045 "parsing/parser.ml" +# 25454 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 25050 "parsing/parser.ml" +# 25459 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25069,14 +25478,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3470 "parsing/parser.mly" +# 3511 "parsing/parser.mly" ("||") -# 25075 "parsing/parser.ml" +# 25484 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 25080 "parsing/parser.ml" +# 25489 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25099,14 +25508,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3471 "parsing/parser.mly" +# 3512 "parsing/parser.mly" ("&") -# 25105 "parsing/parser.ml" +# 25514 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 25110 "parsing/parser.ml" +# 25519 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25129,14 +25538,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3472 "parsing/parser.mly" +# 3513 "parsing/parser.mly" ("&&") -# 25135 "parsing/parser.ml" +# 25544 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 25140 "parsing/parser.ml" +# 25549 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25159,14 +25568,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = let _1 = -# 3473 "parsing/parser.mly" +# 3514 "parsing/parser.mly" (":=") -# 25165 "parsing/parser.ml" +# 25574 "parsing/parser.ml" in -# 3451 "parsing/parser.mly" +# 3492 "parsing/parser.mly" ( _1 ) -# 25170 "parsing/parser.ml" +# 25579 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25189,9 +25598,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (bool) = -# 3355 "parsing/parser.mly" +# 3396 "parsing/parser.mly" ( true ) -# 25195 "parsing/parser.ml" +# 25604 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25207,9 +25616,9 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : (bool) = -# 3356 "parsing/parser.mly" +# 3397 "parsing/parser.mly" ( false ) -# 25213 "parsing/parser.ml" +# 25622 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25227,7 +25636,7 @@ module Tables = struct let _v : (unit option) = # 114 "<standard.mly>" ( None ) -# 25231 "parsing/parser.ml" +# 25640 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25252,7 +25661,7 @@ module Tables = struct let _v : (unit option) = # 116 "<standard.mly>" ( Some x ) -# 25256 "parsing/parser.ml" +# 25665 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25270,7 +25679,7 @@ module Tables = struct let _v : (unit option) = # 114 "<standard.mly>" ( None ) -# 25274 "parsing/parser.ml" +# 25683 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25295,7 +25704,7 @@ module Tables = struct let _v : (unit option) = # 116 "<standard.mly>" ( Some x ) -# 25299 "parsing/parser.ml" +# 25708 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25313,7 +25722,7 @@ module Tables = struct let _v : (string Asttypes.loc option) = # 114 "<standard.mly>" ( None ) -# 25317 "parsing/parser.ml" +# 25726 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25338,9 +25747,9 @@ module Tables = struct }; } = _menhir_stack in let _1_inlined1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 25344 "parsing/parser.ml" +# 25753 "parsing/parser.ml" ) = Obj.magic _1_inlined1 in let _1 : unit = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -25353,21 +25762,21 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 25359 "parsing/parser.ml" +# 25768 "parsing/parser.ml" in # 183 "<standard.mly>" ( x ) -# 25365 "parsing/parser.ml" +# 25774 "parsing/parser.ml" in # 116 "<standard.mly>" ( Some x ) -# 25371 "parsing/parser.ml" +# 25780 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25385,7 +25794,7 @@ module Tables = struct let _v : (Parsetree.core_type option) = # 114 "<standard.mly>" ( None ) -# 25389 "parsing/parser.ml" +# 25798 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25417,12 +25826,12 @@ module Tables = struct let _v : (Parsetree.core_type option) = let x = # 183 "<standard.mly>" ( x ) -# 25421 "parsing/parser.ml" +# 25830 "parsing/parser.ml" in # 116 "<standard.mly>" ( Some x ) -# 25426 "parsing/parser.ml" +# 25835 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25440,7 +25849,7 @@ module Tables = struct let _v : (Parsetree.expression option) = # 114 "<standard.mly>" ( None ) -# 25444 "parsing/parser.ml" +# 25853 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25472,12 +25881,12 @@ module Tables = struct let _v : (Parsetree.expression option) = let x = # 183 "<standard.mly>" ( x ) -# 25476 "parsing/parser.ml" +# 25885 "parsing/parser.ml" in # 116 "<standard.mly>" ( Some x ) -# 25481 "parsing/parser.ml" +# 25890 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25495,7 +25904,7 @@ module Tables = struct let _v : (Parsetree.module_type option) = # 114 "<standard.mly>" ( None ) -# 25499 "parsing/parser.ml" +# 25908 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25527,12 +25936,12 @@ module Tables = struct let _v : (Parsetree.module_type option) = let x = # 183 "<standard.mly>" ( x ) -# 25531 "parsing/parser.ml" +# 25940 "parsing/parser.ml" in # 116 "<standard.mly>" ( Some x ) -# 25536 "parsing/parser.ml" +# 25945 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25550,7 +25959,7 @@ module Tables = struct let _v : (Parsetree.pattern option) = # 114 "<standard.mly>" ( None ) -# 25554 "parsing/parser.ml" +# 25963 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25582,12 +25991,12 @@ module Tables = struct let _v : (Parsetree.pattern option) = let x = # 183 "<standard.mly>" ( x ) -# 25586 "parsing/parser.ml" +# 25995 "parsing/parser.ml" in # 116 "<standard.mly>" ( Some x ) -# 25591 "parsing/parser.ml" +# 26000 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25605,7 +26014,7 @@ module Tables = struct let _v : (Parsetree.expression option) = # 114 "<standard.mly>" ( None ) -# 25609 "parsing/parser.ml" +# 26018 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25637,12 +26046,12 @@ module Tables = struct let _v : (Parsetree.expression option) = let x = # 183 "<standard.mly>" ( x ) -# 25641 "parsing/parser.ml" +# 26050 "parsing/parser.ml" in # 116 "<standard.mly>" ( Some x ) -# 25646 "parsing/parser.ml" +# 26055 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25660,7 +26069,7 @@ module Tables = struct let _v : ((Parsetree.core_type option * Parsetree.core_type option) option) = # 114 "<standard.mly>" ( None ) -# 25664 "parsing/parser.ml" +# 26073 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25685,7 +26094,7 @@ module Tables = struct let _v : ((Parsetree.core_type option * Parsetree.core_type option) option) = # 116 "<standard.mly>" ( Some x ) -# 25689 "parsing/parser.ml" +# 26098 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25704,17 +26113,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 664 "parsing/parser.mly" +# 665 "parsing/parser.mly" (string) -# 25710 "parsing/parser.ml" +# 26119 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3656 "parsing/parser.mly" +# 3697 "parsing/parser.mly" ( _1 ) -# 25718 "parsing/parser.ml" +# 26127 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25746,18 +26155,18 @@ module Tables = struct } = _menhir_stack in let _3 : unit = Obj.magic _3 in let _2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 25752 "parsing/parser.ml" +# 26161 "parsing/parser.ml" ) = Obj.magic _2 in let _1 : unit = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (string) = -# 3657 "parsing/parser.mly" +# 3698 "parsing/parser.mly" ( _2 ) -# 25761 "parsing/parser.ml" +# 26170 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25811,9 +26220,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1249 "parsing/parser.mly" +# 1250 "parsing/parser.mly" ( mkmod ~loc:_sloc (Pmod_constraint(me, mty)) ) -# 25817 "parsing/parser.ml" +# 26226 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25866,9 +26275,9 @@ module Tables = struct let _v : (Parsetree.module_expr) = let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1251 "parsing/parser.mly" +# 1252 "parsing/parser.mly" ( unclosed "(" _loc__1_ ")" _loc__5_ ) -# 25872 "parsing/parser.ml" +# 26281 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25905,9 +26314,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.module_expr) = -# 1254 "parsing/parser.mly" +# 1255 "parsing/parser.mly" ( me (* TODO consider reloc *) ) -# 25911 "parsing/parser.ml" +# 26320 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25946,9 +26355,9 @@ module Tables = struct let _v : (Parsetree.module_expr) = let _loc__3_ = (_startpos__3_, _endpos__3_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1256 "parsing/parser.mly" +# 1257 "parsing/parser.mly" ( unclosed "(" _loc__1_ ")" _loc__3_ ) -# 25952 "parsing/parser.ml" +# 26361 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -25999,25 +26408,25 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__5_ in let _v : (Parsetree.module_expr) = let e = -# 1273 "parsing/parser.mly" +# 1274 "parsing/parser.mly" ( e ) -# 26005 "parsing/parser.ml" +# 26414 "parsing/parser.ml" in let attrs = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 26012 "parsing/parser.ml" +# 26421 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1260 "parsing/parser.mly" +# 1261 "parsing/parser.mly" ( mkmod ~loc:_sloc ~attrs (Pmod_unpack e) ) -# 26021 "parsing/parser.ml" +# 26430 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26088,11 +26497,11 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3330 "parsing/parser.mly" +# 3371 "parsing/parser.mly" ( let (lid, cstrs, attrs) = package_type_of_module_type _1 in let descr = Ptyp_package (lid, cstrs) in mktyp ~loc:_sloc ~attrs descr ) -# 26096 "parsing/parser.ml" +# 26505 "parsing/parser.ml" in let _endpos_ty_ = _endpos__1_ in @@ -26100,26 +26509,26 @@ module Tables = struct let _startpos = _startpos_e_ in let _loc = (_startpos, _endpos) in -# 1275 "parsing/parser.mly" +# 1276 "parsing/parser.mly" ( ghexp ~loc:_loc (Pexp_constraint (e, ty)) ) -# 26106 "parsing/parser.ml" +# 26515 "parsing/parser.ml" in let attrs = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 26114 "parsing/parser.ml" +# 26523 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1260 "parsing/parser.mly" +# 1261 "parsing/parser.mly" ( mkmod ~loc:_sloc ~attrs (Pmod_unpack e) ) -# 26123 "parsing/parser.ml" +# 26532 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26205,11 +26614,11 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3330 "parsing/parser.mly" +# 3371 "parsing/parser.mly" ( let (lid, cstrs, attrs) = package_type_of_module_type _1 in let descr = Ptyp_package (lid, cstrs) in mktyp ~loc:_sloc ~attrs descr ) -# 26213 "parsing/parser.ml" +# 26622 "parsing/parser.ml" in let _endpos_ty2_ = _endpos__1_inlined1_ in @@ -26218,37 +26627,37 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3330 "parsing/parser.mly" +# 3371 "parsing/parser.mly" ( let (lid, cstrs, attrs) = package_type_of_module_type _1 in let descr = Ptyp_package (lid, cstrs) in mktyp ~loc:_sloc ~attrs descr ) -# 26226 "parsing/parser.ml" +# 26635 "parsing/parser.ml" in let _endpos = _endpos_ty2_ in let _startpos = _startpos_e_ in let _loc = (_startpos, _endpos) in -# 1277 "parsing/parser.mly" +# 1278 "parsing/parser.mly" ( ghexp ~loc:_loc (Pexp_coerce (e, Some ty1, ty2)) ) -# 26235 "parsing/parser.ml" +# 26644 "parsing/parser.ml" in let attrs = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 26243 "parsing/parser.ml" +# 26652 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1260 "parsing/parser.mly" +# 1261 "parsing/parser.mly" ( mkmod ~loc:_sloc ~attrs (Pmod_unpack e) ) -# 26252 "parsing/parser.ml" +# 26661 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26319,11 +26728,11 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3330 "parsing/parser.mly" +# 3371 "parsing/parser.mly" ( let (lid, cstrs, attrs) = package_type_of_module_type _1 in let descr = Ptyp_package (lid, cstrs) in mktyp ~loc:_sloc ~attrs descr ) -# 26327 "parsing/parser.ml" +# 26736 "parsing/parser.ml" in let _endpos_ty2_ = _endpos__1_ in @@ -26331,26 +26740,26 @@ module Tables = struct let _startpos = _startpos_e_ in let _loc = (_startpos, _endpos) in -# 1279 "parsing/parser.mly" +# 1280 "parsing/parser.mly" ( ghexp ~loc:_loc (Pexp_coerce (e, None, ty2)) ) -# 26337 "parsing/parser.ml" +# 26746 "parsing/parser.ml" in let attrs = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 26345 "parsing/parser.ml" +# 26754 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1260 "parsing/parser.mly" +# 1261 "parsing/parser.mly" ( mkmod ~loc:_sloc ~attrs (Pmod_unpack e) ) -# 26354 "parsing/parser.ml" +# 26763 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26410,17 +26819,17 @@ module Tables = struct let _v : (Parsetree.module_expr) = let _3 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 26416 "parsing/parser.ml" +# 26825 "parsing/parser.ml" in let _loc__6_ = (_startpos__6_, _endpos__6_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1262 "parsing/parser.mly" +# 1263 "parsing/parser.mly" ( unclosed "(" _loc__1_ ")" _loc__6_ ) -# 26424 "parsing/parser.ml" +# 26833 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26480,17 +26889,17 @@ module Tables = struct let _v : (Parsetree.module_expr) = let _3 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 26486 "parsing/parser.ml" +# 26895 "parsing/parser.ml" in let _loc__6_ = (_startpos__6_, _endpos__6_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1264 "parsing/parser.mly" +# 1265 "parsing/parser.mly" ( unclosed "(" _loc__1_ ")" _loc__6_ ) -# 26494 "parsing/parser.ml" +# 26903 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26543,17 +26952,17 @@ module Tables = struct let _v : (Parsetree.module_expr) = let _3 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 26549 "parsing/parser.ml" +# 26958 "parsing/parser.ml" in let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1266 "parsing/parser.mly" +# 1267 "parsing/parser.mly" ( unclosed "(" _loc__1_ ")" _loc__5_ ) -# 26557 "parsing/parser.ml" +# 26966 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26583,13 +26992,13 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : ( -# 801 "parsing/parser.mly" +# 802 "parsing/parser.mly" (Longident.t) -# 26589 "parsing/parser.ml" +# 26998 "parsing/parser.ml" ) = -# 1170 "parsing/parser.mly" +# 1171 "parsing/parser.mly" ( _1 ) -# 26593 "parsing/parser.ml" +# 27002 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26619,13 +27028,13 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : ( -# 791 "parsing/parser.mly" +# 792 "parsing/parser.mly" (Longident.t) -# 26625 "parsing/parser.ml" +# 27034 "parsing/parser.ml" ) = -# 1155 "parsing/parser.mly" +# 1156 "parsing/parser.mly" ( _1 ) -# 26629 "parsing/parser.ml" +# 27038 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26655,13 +27064,13 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : ( -# 785 "parsing/parser.mly" +# 786 "parsing/parser.mly" (Parsetree.core_type) -# 26661 "parsing/parser.ml" +# 27070 "parsing/parser.ml" ) = -# 1130 "parsing/parser.mly" +# 1131 "parsing/parser.mly" ( _1 ) -# 26665 "parsing/parser.ml" +# 27074 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26691,13 +27100,13 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : ( -# 787 "parsing/parser.mly" +# 788 "parsing/parser.mly" (Parsetree.expression) -# 26697 "parsing/parser.ml" +# 27106 "parsing/parser.ml" ) = -# 1135 "parsing/parser.mly" +# 1136 "parsing/parser.mly" ( _1 ) -# 26701 "parsing/parser.ml" +# 27110 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26727,13 +27136,13 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : ( -# 797 "parsing/parser.mly" +# 798 "parsing/parser.mly" (Longident.t) -# 26733 "parsing/parser.ml" +# 27142 "parsing/parser.ml" ) = -# 1160 "parsing/parser.mly" +# 1161 "parsing/parser.mly" ( _1 ) -# 26737 "parsing/parser.ml" +# 27146 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26763,13 +27172,13 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : ( -# 799 "parsing/parser.mly" +# 800 "parsing/parser.mly" (Longident.t) -# 26769 "parsing/parser.ml" +# 27178 "parsing/parser.ml" ) = -# 1165 "parsing/parser.mly" +# 1166 "parsing/parser.mly" ( _1 ) -# 26773 "parsing/parser.ml" +# 27182 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26799,13 +27208,13 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : ( -# 795 "parsing/parser.mly" +# 796 "parsing/parser.mly" (Longident.t) -# 26805 "parsing/parser.ml" +# 27214 "parsing/parser.ml" ) = -# 1145 "parsing/parser.mly" +# 1146 "parsing/parser.mly" ( _1 ) -# 26809 "parsing/parser.ml" +# 27218 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26835,13 +27244,13 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : ( -# 789 "parsing/parser.mly" +# 790 "parsing/parser.mly" (Parsetree.pattern) -# 26841 "parsing/parser.ml" +# 27250 "parsing/parser.ml" ) = -# 1140 "parsing/parser.mly" +# 1141 "parsing/parser.mly" ( _1 ) -# 26845 "parsing/parser.ml" +# 27254 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26871,13 +27280,13 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : ( -# 793 "parsing/parser.mly" +# 794 "parsing/parser.mly" (Longident.t) -# 26877 "parsing/parser.ml" +# 27286 "parsing/parser.ml" ) = -# 1150 "parsing/parser.mly" +# 1151 "parsing/parser.mly" ( _1 ) -# 26881 "parsing/parser.ml" +# 27290 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26919,15 +27328,15 @@ module Tables = struct let _loc__2_ = (_startpos__2_, _endpos__2_) in let _sloc = (_symbolstartpos, _endpos) in -# 2631 "parsing/parser.mly" +# 2638 "parsing/parser.mly" ( mkpat_cons ~loc:_sloc _loc__2_ (ghpat ~loc:_sloc (Ppat_tuple[_1;_3])) ) -# 26925 "parsing/parser.ml" +# 27334 "parsing/parser.ml" in -# 2619 "parsing/parser.mly" +# 2624 "parsing/parser.mly" ( _1 ) -# 26931 "parsing/parser.ml" +# 27340 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26957,14 +27366,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.pattern) = let _1 = -# 2633 "parsing/parser.mly" +# 2640 "parsing/parser.mly" ( Pat.attr _1 _2 ) -# 26963 "parsing/parser.ml" +# 27372 "parsing/parser.ml" in -# 2619 "parsing/parser.mly" +# 2624 "parsing/parser.mly" ( _1 ) -# 26968 "parsing/parser.ml" +# 27377 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -26987,14 +27396,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.pattern) = let _1 = -# 2635 "parsing/parser.mly" +# 2642 "parsing/parser.mly" ( _1 ) -# 26993 "parsing/parser.ml" +# 27402 "parsing/parser.ml" in -# 2619 "parsing/parser.mly" +# 2624 "parsing/parser.mly" ( _1 ) -# 26998 "parsing/parser.ml" +# 27407 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27039,15 +27448,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 27045 "parsing/parser.ml" +# 27454 "parsing/parser.ml" in -# 2638 "parsing/parser.mly" +# 2645 "parsing/parser.mly" ( Ppat_alias(_1, _3) ) -# 27051 "parsing/parser.ml" +# 27460 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined1_ in @@ -27055,21 +27464,21 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 27061 "parsing/parser.ml" +# 27470 "parsing/parser.ml" in -# 2649 "parsing/parser.mly" +# 2656 "parsing/parser.mly" ( _1 ) -# 27067 "parsing/parser.ml" +# 27476 "parsing/parser.ml" in -# 2619 "parsing/parser.mly" +# 2624 "parsing/parser.mly" ( _1 ) -# 27073 "parsing/parser.ml" +# 27482 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27110,9 +27519,9 @@ module Tables = struct let _1 = let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2640 "parsing/parser.mly" +# 2647 "parsing/parser.mly" ( expecting _loc__3_ "identifier" ) -# 27116 "parsing/parser.ml" +# 27525 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -27120,21 +27529,21 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 27126 "parsing/parser.ml" +# 27535 "parsing/parser.ml" in -# 2649 "parsing/parser.mly" +# 2656 "parsing/parser.mly" ( _1 ) -# 27132 "parsing/parser.ml" +# 27541 "parsing/parser.ml" in -# 2619 "parsing/parser.mly" +# 2624 "parsing/parser.mly" ( _1 ) -# 27138 "parsing/parser.ml" +# 27547 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27159,29 +27568,29 @@ module Tables = struct let _v : (Parsetree.pattern) = let _1 = let _1 = let _1 = -# 2642 "parsing/parser.mly" +# 2649 "parsing/parser.mly" ( Ppat_tuple(List.rev _1) ) -# 27165 "parsing/parser.ml" +# 27574 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 27173 "parsing/parser.ml" +# 27582 "parsing/parser.ml" in -# 2649 "parsing/parser.mly" +# 2656 "parsing/parser.mly" ( _1 ) -# 27179 "parsing/parser.ml" +# 27588 "parsing/parser.ml" in -# 2619 "parsing/parser.mly" +# 2624 "parsing/parser.mly" ( _1 ) -# 27185 "parsing/parser.ml" +# 27594 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27222,9 +27631,9 @@ module Tables = struct let _1 = let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2644 "parsing/parser.mly" +# 2651 "parsing/parser.mly" ( expecting _loc__3_ "pattern" ) -# 27228 "parsing/parser.ml" +# 27637 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -27232,21 +27641,21 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 27238 "parsing/parser.ml" +# 27647 "parsing/parser.ml" in -# 2649 "parsing/parser.mly" +# 2656 "parsing/parser.mly" ( _1 ) -# 27244 "parsing/parser.ml" +# 27653 "parsing/parser.ml" in -# 2619 "parsing/parser.mly" +# 2624 "parsing/parser.mly" ( _1 ) -# 27250 "parsing/parser.ml" +# 27659 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27285,30 +27694,30 @@ module Tables = struct let _v : (Parsetree.pattern) = let _1 = let _1 = let _1 = -# 2646 "parsing/parser.mly" +# 2653 "parsing/parser.mly" ( Ppat_or(_1, _3) ) -# 27291 "parsing/parser.ml" +# 27700 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 27300 "parsing/parser.ml" +# 27709 "parsing/parser.ml" in -# 2649 "parsing/parser.mly" +# 2656 "parsing/parser.mly" ( _1 ) -# 27306 "parsing/parser.ml" +# 27715 "parsing/parser.ml" in -# 2619 "parsing/parser.mly" +# 2624 "parsing/parser.mly" ( _1 ) -# 27312 "parsing/parser.ml" +# 27721 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27349,9 +27758,9 @@ module Tables = struct let _1 = let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2648 "parsing/parser.mly" +# 2655 "parsing/parser.mly" ( expecting _loc__3_ "pattern" ) -# 27355 "parsing/parser.ml" +# 27764 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -27359,21 +27768,21 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 27365 "parsing/parser.ml" +# 27774 "parsing/parser.ml" in -# 2649 "parsing/parser.mly" +# 2656 "parsing/parser.mly" ( _1 ) -# 27371 "parsing/parser.ml" +# 27780 "parsing/parser.ml" in -# 2619 "parsing/parser.mly" +# 2624 "parsing/parser.mly" ( _1 ) -# 27377 "parsing/parser.ml" +# 27786 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27421,24 +27830,66 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 27427 "parsing/parser.ml" +# 27836 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 27433 "parsing/parser.ml" +# 27842 "parsing/parser.ml" in let _endpos = _endpos__3_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2621 "parsing/parser.mly" +# 2626 "parsing/parser.mly" ( mkpat_attrs ~loc:_sloc (Ppat_exception _3) _2) -# 27442 "parsing/parser.ml" +# 27851 "parsing/parser.ml" + in + { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = Obj.repr _v; + MenhirLib.EngineTypes.startp = _startpos; + MenhirLib.EngineTypes.endp = _endpos; + MenhirLib.EngineTypes.next = _menhir_stack; + }); + (fun _menhir_env -> + let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in + let { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _3; + MenhirLib.EngineTypes.startp = _startpos__3_; + MenhirLib.EngineTypes.endp = _endpos__3_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _2; + MenhirLib.EngineTypes.startp = _startpos__2_; + MenhirLib.EngineTypes.endp = _endpos__2_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = _1; + MenhirLib.EngineTypes.startp = _startpos__1_; + MenhirLib.EngineTypes.endp = _endpos__1_; + MenhirLib.EngineTypes.next = _menhir_stack; + }; + }; + } = _menhir_stack in + let _3 : (Parsetree.pattern) = Obj.magic _3 in + let _2 : (Parsetree.pattern) = Obj.magic _2 in + let _1 : unit = Obj.magic _1 in + let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in + let _startpos = _startpos__1_ in + let _endpos = _endpos__3_ in + let _v : (Parsetree.pattern) = let _endpos = _endpos__3_ in + let _symbolstartpos = _startpos__1_ in + let _sloc = (_symbolstartpos, _endpos) in + +# 2628 "parsing/parser.mly" + ( mkpat ~loc:_sloc (Ppat_effect(_2,_3)) ) +# 27893 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27475,9 +27926,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.pattern list) = -# 2745 "parsing/parser.mly" +# 2752 "parsing/parser.mly" ( _3 :: _1 ) -# 27481 "parsing/parser.ml" +# 27932 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27514,9 +27965,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.pattern list) = -# 2746 "parsing/parser.mly" +# 2753 "parsing/parser.mly" ( [_3; _1] ) -# 27520 "parsing/parser.ml" +# 27971 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27554,9 +28005,9 @@ module Tables = struct let _endpos = _endpos__3_ in let _v : (Parsetree.pattern list) = let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2747 "parsing/parser.mly" +# 2754 "parsing/parser.mly" ( expecting _loc__3_ "pattern" ) -# 27560 "parsing/parser.ml" +# 28011 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27593,9 +28044,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.pattern list) = -# 2745 "parsing/parser.mly" +# 2752 "parsing/parser.mly" ( _3 :: _1 ) -# 27599 "parsing/parser.ml" +# 28050 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27632,9 +28083,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Parsetree.pattern list) = -# 2746 "parsing/parser.mly" +# 2753 "parsing/parser.mly" ( [_3; _1] ) -# 27638 "parsing/parser.ml" +# 28089 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27672,9 +28123,9 @@ module Tables = struct let _endpos = _endpos__3_ in let _v : (Parsetree.pattern list) = let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2747 "parsing/parser.mly" +# 2754 "parsing/parser.mly" ( expecting _loc__3_ "pattern" ) -# 27678 "parsing/parser.ml" +# 28129 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27697,9 +28148,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.pattern) = -# 2654 "parsing/parser.mly" +# 2661 "parsing/parser.mly" ( _1 ) -# 27703 "parsing/parser.ml" +# 28154 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27735,15 +28186,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 27741 "parsing/parser.ml" +# 28192 "parsing/parser.ml" in -# 2657 "parsing/parser.mly" +# 2664 "parsing/parser.mly" ( Ppat_construct(_1, Some _2) ) -# 27747 "parsing/parser.ml" +# 28198 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in @@ -27751,15 +28202,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 27757 "parsing/parser.ml" +# 28208 "parsing/parser.ml" in -# 2660 "parsing/parser.mly" +# 2667 "parsing/parser.mly" ( _1 ) -# 27763 "parsing/parser.ml" +# 28214 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27790,24 +28241,24 @@ module Tables = struct let _endpos = _endpos__2_ in let _v : (Parsetree.pattern) = let _1 = let _1 = -# 2659 "parsing/parser.mly" +# 2666 "parsing/parser.mly" ( Ppat_variant(_1, Some _2) ) -# 27796 "parsing/parser.ml" +# 28247 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 27805 "parsing/parser.ml" +# 28256 "parsing/parser.ml" in -# 2660 "parsing/parser.mly" +# 2667 "parsing/parser.mly" ( _1 ) -# 27811 "parsing/parser.ml" +# 28262 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27855,24 +28306,24 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 27861 "parsing/parser.ml" +# 28312 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 27867 "parsing/parser.ml" +# 28318 "parsing/parser.ml" in let _endpos = _endpos__3_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2662 "parsing/parser.mly" +# 2669 "parsing/parser.mly" ( mkpat_attrs ~loc:_sloc (Ppat_lazy _3) _2) -# 27876 "parsing/parser.ml" +# 28327 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27914,15 +28365,15 @@ module Tables = struct let _loc__2_ = (_startpos__2_, _endpos__2_) in let _sloc = (_symbolstartpos, _endpos) in -# 2631 "parsing/parser.mly" +# 2638 "parsing/parser.mly" ( mkpat_cons ~loc:_sloc _loc__2_ (ghpat ~loc:_sloc (Ppat_tuple[_1;_3])) ) -# 27920 "parsing/parser.ml" +# 28371 "parsing/parser.ml" in -# 2626 "parsing/parser.mly" +# 2633 "parsing/parser.mly" ( _1 ) -# 27926 "parsing/parser.ml" +# 28377 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27952,14 +28403,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.pattern) = let _1 = -# 2633 "parsing/parser.mly" +# 2640 "parsing/parser.mly" ( Pat.attr _1 _2 ) -# 27958 "parsing/parser.ml" +# 28409 "parsing/parser.ml" in -# 2626 "parsing/parser.mly" +# 2633 "parsing/parser.mly" ( _1 ) -# 27963 "parsing/parser.ml" +# 28414 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -27982,14 +28433,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.pattern) = let _1 = -# 2635 "parsing/parser.mly" +# 2642 "parsing/parser.mly" ( _1 ) -# 27988 "parsing/parser.ml" +# 28439 "parsing/parser.ml" in -# 2626 "parsing/parser.mly" +# 2633 "parsing/parser.mly" ( _1 ) -# 27993 "parsing/parser.ml" +# 28444 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28034,15 +28485,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 28040 "parsing/parser.ml" +# 28491 "parsing/parser.ml" in -# 2638 "parsing/parser.mly" +# 2645 "parsing/parser.mly" ( Ppat_alias(_1, _3) ) -# 28046 "parsing/parser.ml" +# 28497 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined1_ in @@ -28050,21 +28501,21 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 28056 "parsing/parser.ml" +# 28507 "parsing/parser.ml" in -# 2649 "parsing/parser.mly" +# 2656 "parsing/parser.mly" ( _1 ) -# 28062 "parsing/parser.ml" +# 28513 "parsing/parser.ml" in -# 2626 "parsing/parser.mly" +# 2633 "parsing/parser.mly" ( _1 ) -# 28068 "parsing/parser.ml" +# 28519 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28105,9 +28556,9 @@ module Tables = struct let _1 = let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2640 "parsing/parser.mly" +# 2647 "parsing/parser.mly" ( expecting _loc__3_ "identifier" ) -# 28111 "parsing/parser.ml" +# 28562 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -28115,21 +28566,21 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 28121 "parsing/parser.ml" +# 28572 "parsing/parser.ml" in -# 2649 "parsing/parser.mly" +# 2656 "parsing/parser.mly" ( _1 ) -# 28127 "parsing/parser.ml" +# 28578 "parsing/parser.ml" in -# 2626 "parsing/parser.mly" +# 2633 "parsing/parser.mly" ( _1 ) -# 28133 "parsing/parser.ml" +# 28584 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28154,29 +28605,29 @@ module Tables = struct let _v : (Parsetree.pattern) = let _1 = let _1 = let _1 = -# 2642 "parsing/parser.mly" +# 2649 "parsing/parser.mly" ( Ppat_tuple(List.rev _1) ) -# 28160 "parsing/parser.ml" +# 28611 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 28168 "parsing/parser.ml" +# 28619 "parsing/parser.ml" in -# 2649 "parsing/parser.mly" +# 2656 "parsing/parser.mly" ( _1 ) -# 28174 "parsing/parser.ml" +# 28625 "parsing/parser.ml" in -# 2626 "parsing/parser.mly" +# 2633 "parsing/parser.mly" ( _1 ) -# 28180 "parsing/parser.ml" +# 28631 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28217,9 +28668,9 @@ module Tables = struct let _1 = let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2644 "parsing/parser.mly" +# 2651 "parsing/parser.mly" ( expecting _loc__3_ "pattern" ) -# 28223 "parsing/parser.ml" +# 28674 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -28227,21 +28678,21 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 28233 "parsing/parser.ml" +# 28684 "parsing/parser.ml" in -# 2649 "parsing/parser.mly" +# 2656 "parsing/parser.mly" ( _1 ) -# 28239 "parsing/parser.ml" +# 28690 "parsing/parser.ml" in -# 2626 "parsing/parser.mly" +# 2633 "parsing/parser.mly" ( _1 ) -# 28245 "parsing/parser.ml" +# 28696 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28280,30 +28731,30 @@ module Tables = struct let _v : (Parsetree.pattern) = let _1 = let _1 = let _1 = -# 2646 "parsing/parser.mly" +# 2653 "parsing/parser.mly" ( Ppat_or(_1, _3) ) -# 28286 "parsing/parser.ml" +# 28737 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 28295 "parsing/parser.ml" +# 28746 "parsing/parser.ml" in -# 2649 "parsing/parser.mly" +# 2656 "parsing/parser.mly" ( _1 ) -# 28301 "parsing/parser.ml" +# 28752 "parsing/parser.ml" in -# 2626 "parsing/parser.mly" +# 2633 "parsing/parser.mly" ( _1 ) -# 28307 "parsing/parser.ml" +# 28758 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28344,9 +28795,9 @@ module Tables = struct let _1 = let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2648 "parsing/parser.mly" +# 2655 "parsing/parser.mly" ( expecting _loc__3_ "pattern" ) -# 28350 "parsing/parser.ml" +# 28801 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -28354,21 +28805,21 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 28360 "parsing/parser.ml" +# 28811 "parsing/parser.ml" in -# 2649 "parsing/parser.mly" +# 2656 "parsing/parser.mly" ( _1 ) -# 28366 "parsing/parser.ml" +# 28817 "parsing/parser.ml" in -# 2626 "parsing/parser.mly" +# 2633 "parsing/parser.mly" ( _1 ) -# 28372 "parsing/parser.ml" +# 28823 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28387,9 +28838,9 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 28393 "parsing/parser.ml" +# 28844 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -28401,30 +28852,30 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 28407 "parsing/parser.ml" +# 28858 "parsing/parser.ml" in -# 2104 "parsing/parser.mly" +# 2109 "parsing/parser.mly" ( Ppat_var _1 ) -# 28413 "parsing/parser.ml" +# 28864 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 28422 "parsing/parser.ml" +# 28873 "parsing/parser.ml" in -# 2106 "parsing/parser.mly" +# 2111 "parsing/parser.mly" ( _1 ) -# 28428 "parsing/parser.ml" +# 28879 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28448,23 +28899,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.pattern) = let _1 = let _1 = -# 2105 "parsing/parser.mly" +# 2110 "parsing/parser.mly" ( Ppat_any ) -# 28454 "parsing/parser.ml" +# 28905 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 28462 "parsing/parser.ml" +# 28913 "parsing/parser.ml" in -# 2106 "parsing/parser.mly" +# 2111 "parsing/parser.mly" ( _1 ) -# 28468 "parsing/parser.ml" +# 28919 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28487,9 +28938,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.payload) = -# 3766 "parsing/parser.mly" +# 3807 "parsing/parser.mly" ( PStr _1 ) -# 28493 "parsing/parser.ml" +# 28944 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28519,9 +28970,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.payload) = -# 3767 "parsing/parser.mly" +# 3808 "parsing/parser.mly" ( PSig _2 ) -# 28525 "parsing/parser.ml" +# 28976 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28551,9 +29002,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.payload) = -# 3768 "parsing/parser.mly" +# 3809 "parsing/parser.mly" ( PTyp _2 ) -# 28557 "parsing/parser.ml" +# 29008 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28583,9 +29034,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.payload) = -# 3769 "parsing/parser.mly" +# 3810 "parsing/parser.mly" ( PPat (_2, None) ) -# 28589 "parsing/parser.ml" +# 29040 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28629,9 +29080,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__4_ in let _v : (Parsetree.payload) = -# 3770 "parsing/parser.mly" +# 3811 "parsing/parser.mly" ( PPat (_2, Some _4) ) -# 28635 "parsing/parser.ml" +# 29086 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28654,9 +29105,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.core_type) = -# 3169 "parsing/parser.mly" +# 3210 "parsing/parser.mly" ( _1 ) -# 28660 "parsing/parser.ml" +# 29111 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28699,24 +29150,24 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 28703 "parsing/parser.ml" +# 29154 "parsing/parser.ml" in -# 915 "parsing/parser.mly" +# 916 "parsing/parser.mly" ( xs ) -# 28708 "parsing/parser.ml" +# 29159 "parsing/parser.ml" in -# 3161 "parsing/parser.mly" +# 3202 "parsing/parser.mly" ( _1 ) -# 28714 "parsing/parser.ml" +# 29165 "parsing/parser.ml" in -# 3165 "parsing/parser.mly" +# 3206 "parsing/parser.mly" ( Ptyp_poly(_1, _3) ) -# 28720 "parsing/parser.ml" +# 29171 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos__3_, _startpos_xs_) in @@ -28724,15 +29175,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 28730 "parsing/parser.ml" +# 29181 "parsing/parser.ml" in -# 3171 "parsing/parser.mly" +# 3212 "parsing/parser.mly" ( _1 ) -# 28736 "parsing/parser.ml" +# 29187 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28755,14 +29206,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.core_type) = let _1 = -# 3200 "parsing/parser.mly" +# 3241 "parsing/parser.mly" ( _1 ) -# 28761 "parsing/parser.ml" +# 29212 "parsing/parser.ml" in -# 3169 "parsing/parser.mly" +# 3210 "parsing/parser.mly" ( _1 ) -# 28766 "parsing/parser.ml" +# 29217 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28801,33 +29252,33 @@ module Tables = struct let _v : (Parsetree.core_type) = let _1 = let _1 = let _3 = -# 3200 "parsing/parser.mly" +# 3241 "parsing/parser.mly" ( _1 ) -# 28807 "parsing/parser.ml" +# 29258 "parsing/parser.ml" in let _1 = let _1 = let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 28814 "parsing/parser.ml" +# 29265 "parsing/parser.ml" in -# 915 "parsing/parser.mly" +# 916 "parsing/parser.mly" ( xs ) -# 28819 "parsing/parser.ml" +# 29270 "parsing/parser.ml" in -# 3161 "parsing/parser.mly" +# 3202 "parsing/parser.mly" ( _1 ) -# 28825 "parsing/parser.ml" +# 29276 "parsing/parser.ml" in -# 3165 "parsing/parser.mly" +# 3206 "parsing/parser.mly" ( Ptyp_poly(_1, _3) ) -# 28831 "parsing/parser.ml" +# 29282 "parsing/parser.ml" in let _startpos__1_ = _startpos_xs_ in @@ -28835,15 +29286,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 28841 "parsing/parser.ml" +# 29292 "parsing/parser.ml" in -# 3171 "parsing/parser.mly" +# 3212 "parsing/parser.mly" ( _1 ) -# 28847 "parsing/parser.ml" +# 29298 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28890,9 +29341,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3729 "parsing/parser.mly" +# 3770 "parsing/parser.mly" ( Attr.mk ~loc:(make_loc _sloc) _2 _3 ) -# 28896 "parsing/parser.ml" +# 29347 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -28973,9 +29424,9 @@ module Tables = struct let _v : (Parsetree.value_description * string Asttypes.loc option) = let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 28979 "parsing/parser.ml" +# 29430 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -28985,30 +29436,30 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 28991 "parsing/parser.ml" +# 29442 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 28999 "parsing/parser.ml" +# 29450 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2806 "parsing/parser.mly" +# 2813 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in let docs = symbol_docs _sloc in Val.mk id ty ~prim ~attrs ~loc ~docs, ext ) -# 29012 "parsing/parser.ml" +# 29463 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29024,14 +29475,14 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : (Asttypes.private_flag) = let _1 = -# 3597 "parsing/parser.mly" +# 3638 "parsing/parser.mly" ( Public ) -# 29030 "parsing/parser.ml" +# 29481 "parsing/parser.ml" in -# 3594 "parsing/parser.mly" +# 3635 "parsing/parser.mly" ( _1 ) -# 29035 "parsing/parser.ml" +# 29486 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29054,14 +29505,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.private_flag) = let _1 = -# 3598 "parsing/parser.mly" +# 3639 "parsing/parser.mly" ( Private ) -# 29060 "parsing/parser.ml" +# 29511 "parsing/parser.ml" in -# 3594 "parsing/parser.mly" +# 3635 "parsing/parser.mly" ( _1 ) -# 29065 "parsing/parser.ml" +# 29516 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29077,9 +29528,9 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : (Asttypes.private_flag * Asttypes.virtual_flag) = -# 3620 "parsing/parser.mly" +# 3661 "parsing/parser.mly" ( Public, Concrete ) -# 29083 "parsing/parser.ml" +# 29534 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29102,9 +29553,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.private_flag * Asttypes.virtual_flag) = -# 3621 "parsing/parser.mly" +# 3662 "parsing/parser.mly" ( Private, Concrete ) -# 29108 "parsing/parser.ml" +# 29559 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29127,9 +29578,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.private_flag * Asttypes.virtual_flag) = -# 3622 "parsing/parser.mly" +# 3663 "parsing/parser.mly" ( Public, Virtual ) -# 29133 "parsing/parser.ml" +# 29584 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29159,9 +29610,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.private_flag * Asttypes.virtual_flag) = -# 3623 "parsing/parser.mly" +# 3664 "parsing/parser.mly" ( Private, Virtual ) -# 29165 "parsing/parser.ml" +# 29616 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29191,9 +29642,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.private_flag * Asttypes.virtual_flag) = -# 3624 "parsing/parser.mly" +# 3665 "parsing/parser.mly" ( Private, Virtual ) -# 29197 "parsing/parser.ml" +# 29648 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29209,9 +29660,9 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : (Asttypes.rec_flag) = -# 3577 "parsing/parser.mly" +# 3618 "parsing/parser.mly" ( Nonrecursive ) -# 29215 "parsing/parser.ml" +# 29666 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29234,9 +29685,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.rec_flag) = -# 3578 "parsing/parser.mly" +# 3619 "parsing/parser.mly" ( Recursive ) -# 29240 "parsing/parser.ml" +# 29691 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29262,12 +29713,12 @@ module Tables = struct (Longident.t Asttypes.loc * Parsetree.expression) list) = let eo = # 124 "<standard.mly>" ( None ) -# 29266 "parsing/parser.ml" +# 29717 "parsing/parser.ml" in -# 2551 "parsing/parser.mly" +# 2556 "parsing/parser.mly" ( eo, fields ) -# 29271 "parsing/parser.ml" +# 29722 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29308,18 +29759,18 @@ module Tables = struct let x = # 191 "<standard.mly>" ( x ) -# 29312 "parsing/parser.ml" +# 29763 "parsing/parser.ml" in # 126 "<standard.mly>" ( Some x ) -# 29317 "parsing/parser.ml" +# 29768 "parsing/parser.ml" in -# 2551 "parsing/parser.mly" +# 2556 "parsing/parser.mly" ( eo, fields ) -# 29323 "parsing/parser.ml" +# 29774 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29344,17 +29795,17 @@ module Tables = struct let _startpos = _startpos_d_ in let _endpos = _endpos_d_ in let _v : (Parsetree.constructor_declaration list) = let x = -# 2991 "parsing/parser.mly" +# 2998 "parsing/parser.mly" ( let cid, args, res, attrs, loc, info = d in Type.constructor cid ~args ?res ~attrs ~loc ~info ) -# 29353 "parsing/parser.ml" +# 29804 "parsing/parser.ml" in -# 1025 "parsing/parser.mly" +# 1026 "parsing/parser.mly" ( [x] ) -# 29358 "parsing/parser.ml" +# 29809 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29379,17 +29830,17 @@ module Tables = struct let _startpos = _startpos_d_ in let _endpos = _endpos_d_ in let _v : (Parsetree.constructor_declaration list) = let x = -# 2991 "parsing/parser.mly" +# 2998 "parsing/parser.mly" ( let cid, args, res, attrs, loc, info = d in Type.constructor cid ~args ?res ~attrs ~loc ~info ) -# 29388 "parsing/parser.ml" +# 29839 "parsing/parser.ml" in -# 1028 "parsing/parser.mly" +# 1029 "parsing/parser.mly" ( [x] ) -# 29393 "parsing/parser.ml" +# 29844 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29421,17 +29872,17 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_d_ in let _v : (Parsetree.constructor_declaration list) = let x = -# 2991 "parsing/parser.mly" +# 2998 "parsing/parser.mly" ( let cid, args, res, attrs, loc, info = d in Type.constructor cid ~args ?res ~attrs ~loc ~info ) -# 29430 "parsing/parser.ml" +# 29881 "parsing/parser.ml" in -# 1032 "parsing/parser.mly" +# 1033 "parsing/parser.mly" ( x :: xs ) -# 29435 "parsing/parser.ml" +# 29886 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29457,23 +29908,23 @@ module Tables = struct let _endpos = _endpos_d_ in let _v : (Parsetree.extension_constructor list) = let x = let _1 = -# 3103 "parsing/parser.mly" +# 3144 "parsing/parser.mly" ( let cid, args, res, attrs, loc, info = d in Te.decl cid ~args ?res ~attrs ~loc ~info ) -# 29466 "parsing/parser.ml" +# 29917 "parsing/parser.ml" in -# 3097 "parsing/parser.mly" +# 3138 "parsing/parser.mly" ( _1 ) -# 29471 "parsing/parser.ml" +# 29922 "parsing/parser.ml" in -# 1025 "parsing/parser.mly" +# 1026 "parsing/parser.mly" ( [x] ) -# 29477 "parsing/parser.ml" +# 29928 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29496,14 +29947,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.extension_constructor list) = let x = -# 3099 "parsing/parser.mly" +# 3140 "parsing/parser.mly" ( _1 ) -# 29502 "parsing/parser.ml" +# 29953 "parsing/parser.ml" in -# 1025 "parsing/parser.mly" +# 1026 "parsing/parser.mly" ( [x] ) -# 29507 "parsing/parser.ml" +# 29958 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29529,23 +29980,23 @@ module Tables = struct let _endpos = _endpos_d_ in let _v : (Parsetree.extension_constructor list) = let x = let _1 = -# 3103 "parsing/parser.mly" +# 3144 "parsing/parser.mly" ( let cid, args, res, attrs, loc, info = d in Te.decl cid ~args ?res ~attrs ~loc ~info ) -# 29538 "parsing/parser.ml" +# 29989 "parsing/parser.ml" in -# 3097 "parsing/parser.mly" +# 3138 "parsing/parser.mly" ( _1 ) -# 29543 "parsing/parser.ml" +# 29994 "parsing/parser.ml" in -# 1028 "parsing/parser.mly" +# 1029 "parsing/parser.mly" ( [x] ) -# 29549 "parsing/parser.ml" +# 30000 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29568,14 +30019,14 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.extension_constructor list) = let x = -# 3099 "parsing/parser.mly" +# 3140 "parsing/parser.mly" ( _1 ) -# 29574 "parsing/parser.ml" +# 30025 "parsing/parser.ml" in -# 1028 "parsing/parser.mly" +# 1029 "parsing/parser.mly" ( [x] ) -# 29579 "parsing/parser.ml" +# 30030 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29608,23 +30059,23 @@ module Tables = struct let _endpos = _endpos_d_ in let _v : (Parsetree.extension_constructor list) = let x = let _1 = -# 3103 "parsing/parser.mly" +# 3144 "parsing/parser.mly" ( let cid, args, res, attrs, loc, info = d in Te.decl cid ~args ?res ~attrs ~loc ~info ) -# 29617 "parsing/parser.ml" +# 30068 "parsing/parser.ml" in -# 3097 "parsing/parser.mly" +# 3138 "parsing/parser.mly" ( _1 ) -# 29622 "parsing/parser.ml" +# 30073 "parsing/parser.ml" in -# 1032 "parsing/parser.mly" +# 1033 "parsing/parser.mly" ( x :: xs ) -# 29628 "parsing/parser.ml" +# 30079 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29654,14 +30105,14 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos__1_ in let _v : (Parsetree.extension_constructor list) = let x = -# 3099 "parsing/parser.mly" +# 3140 "parsing/parser.mly" ( _1 ) -# 29660 "parsing/parser.ml" +# 30111 "parsing/parser.ml" in -# 1032 "parsing/parser.mly" +# 1033 "parsing/parser.mly" ( x :: xs ) -# 29665 "parsing/parser.ml" +# 30116 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29686,17 +30137,17 @@ module Tables = struct let _startpos = _startpos_d_ in let _endpos = _endpos_d_ in let _v : (Parsetree.extension_constructor list) = let x = -# 3103 "parsing/parser.mly" +# 3144 "parsing/parser.mly" ( let cid, args, res, attrs, loc, info = d in Te.decl cid ~args ?res ~attrs ~loc ~info ) -# 29695 "parsing/parser.ml" +# 30146 "parsing/parser.ml" in -# 1025 "parsing/parser.mly" +# 1026 "parsing/parser.mly" ( [x] ) -# 29700 "parsing/parser.ml" +# 30151 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29721,17 +30172,17 @@ module Tables = struct let _startpos = _startpos_d_ in let _endpos = _endpos_d_ in let _v : (Parsetree.extension_constructor list) = let x = -# 3103 "parsing/parser.mly" +# 3144 "parsing/parser.mly" ( let cid, args, res, attrs, loc, info = d in Te.decl cid ~args ?res ~attrs ~loc ~info ) -# 29730 "parsing/parser.ml" +# 30181 "parsing/parser.ml" in -# 1028 "parsing/parser.mly" +# 1029 "parsing/parser.mly" ( [x] ) -# 29735 "parsing/parser.ml" +# 30186 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29763,17 +30214,17 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_d_ in let _v : (Parsetree.extension_constructor list) = let x = -# 3103 "parsing/parser.mly" +# 3144 "parsing/parser.mly" ( let cid, args, res, attrs, loc, info = d in Te.decl cid ~args ?res ~attrs ~loc ~info ) -# 29772 "parsing/parser.ml" +# 30223 "parsing/parser.ml" in -# 1032 "parsing/parser.mly" +# 1033 "parsing/parser.mly" ( x :: xs ) -# 29777 "parsing/parser.ml" +# 30228 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29789,9 +30240,9 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : ((Parsetree.core_type * Parsetree.core_type * Ast_helper.loc) list) = -# 891 "parsing/parser.mly" +# 892 "parsing/parser.mly" ( [] ) -# 29795 "parsing/parser.ml" +# 30246 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29848,21 +30299,21 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1984 "parsing/parser.mly" +# 1989 "parsing/parser.mly" ( _1, _3, make_loc _sloc ) -# 29854 "parsing/parser.ml" +# 30305 "parsing/parser.ml" in # 183 "<standard.mly>" ( x ) -# 29860 "parsing/parser.ml" +# 30311 "parsing/parser.ml" in -# 893 "parsing/parser.mly" +# 894 "parsing/parser.mly" ( x :: xs ) -# 29866 "parsing/parser.ml" +# 30317 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29885,9 +30336,9 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos_x_ in let _v : (Parsetree.functor_parameter list) = -# 905 "parsing/parser.mly" +# 906 "parsing/parser.mly" ( [ x ] ) -# 29891 "parsing/parser.ml" +# 30342 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29917,9 +30368,9 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_x_ in let _v : (Parsetree.functor_parameter list) = -# 907 "parsing/parser.mly" +# 908 "parsing/parser.mly" ( x :: xs ) -# 29923 "parsing/parser.ml" +# 30374 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29942,9 +30393,9 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos_x_ in let _v : ((Asttypes.arg_label * Parsetree.expression) list) = -# 905 "parsing/parser.mly" +# 906 "parsing/parser.mly" ( [ x ] ) -# 29948 "parsing/parser.ml" +# 30399 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29974,9 +30425,9 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_x_ in let _v : ((Asttypes.arg_label * Parsetree.expression) list) = -# 907 "parsing/parser.mly" +# 908 "parsing/parser.mly" ( x :: xs ) -# 29980 "parsing/parser.ml" +# 30431 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -29999,9 +30450,9 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos_x_ in let _v : (Asttypes.label list) = -# 905 "parsing/parser.mly" +# 906 "parsing/parser.mly" ( [ x ] ) -# 30005 "parsing/parser.ml" +# 30456 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30031,9 +30482,9 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_x_ in let _v : (Asttypes.label list) = -# 907 "parsing/parser.mly" +# 908 "parsing/parser.mly" ( x :: xs ) -# 30037 "parsing/parser.ml" +# 30488 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30069,21 +30520,21 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 30075 "parsing/parser.ml" +# 30526 "parsing/parser.ml" in -# 3157 "parsing/parser.mly" +# 3198 "parsing/parser.mly" ( _2 ) -# 30081 "parsing/parser.ml" +# 30532 "parsing/parser.ml" in -# 905 "parsing/parser.mly" +# 906 "parsing/parser.mly" ( [ x ] ) -# 30087 "parsing/parser.ml" +# 30538 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30126,21 +30577,21 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 30132 "parsing/parser.ml" +# 30583 "parsing/parser.ml" in -# 3157 "parsing/parser.mly" +# 3198 "parsing/parser.mly" ( _2 ) -# 30138 "parsing/parser.ml" +# 30589 "parsing/parser.ml" in -# 907 "parsing/parser.mly" +# 908 "parsing/parser.mly" ( x :: xs ) -# 30144 "parsing/parser.ml" +# 30595 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30165,12 +30616,12 @@ module Tables = struct let _v : (Parsetree.case list) = let _1 = # 124 "<standard.mly>" ( None ) -# 30169 "parsing/parser.ml" +# 30620 "parsing/parser.ml" in -# 996 "parsing/parser.mly" +# 997 "parsing/parser.mly" ( [x] ) -# 30174 "parsing/parser.ml" +# 30625 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30204,13 +30655,13 @@ module Tables = struct # 126 "<standard.mly>" ( Some x ) -# 30208 "parsing/parser.ml" +# 30659 "parsing/parser.ml" in -# 996 "parsing/parser.mly" +# 997 "parsing/parser.mly" ( [x] ) -# 30214 "parsing/parser.ml" +# 30665 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30247,9 +30698,9 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_x_ in let _v : (Parsetree.case list) = -# 1000 "parsing/parser.mly" +# 1001 "parsing/parser.mly" ( x :: xs ) -# 30253 "parsing/parser.ml" +# 30704 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30273,20 +30724,20 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.core_type list) = let xs = let x = -# 3200 "parsing/parser.mly" +# 3241 "parsing/parser.mly" ( _1 ) -# 30279 "parsing/parser.ml" +# 30730 "parsing/parser.ml" in -# 931 "parsing/parser.mly" +# 932 "parsing/parser.mly" ( [ x ] ) -# 30284 "parsing/parser.ml" +# 30735 "parsing/parser.ml" in -# 939 "parsing/parser.mly" +# 940 "parsing/parser.mly" ( xs ) -# 30290 "parsing/parser.ml" +# 30741 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30324,20 +30775,20 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.core_type list) = let xs = let x = -# 3200 "parsing/parser.mly" +# 3241 "parsing/parser.mly" ( _1 ) -# 30330 "parsing/parser.ml" +# 30781 "parsing/parser.ml" in -# 935 "parsing/parser.mly" +# 936 "parsing/parser.mly" ( x :: xs ) -# 30335 "parsing/parser.ml" +# 30786 "parsing/parser.ml" in -# 939 "parsing/parser.mly" +# 940 "parsing/parser.mly" ( xs ) -# 30341 "parsing/parser.ml" +# 30792 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30360,14 +30811,14 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos_x_ in let _v : (Parsetree.with_constraint list) = let xs = -# 931 "parsing/parser.mly" +# 932 "parsing/parser.mly" ( [ x ] ) -# 30366 "parsing/parser.ml" +# 30817 "parsing/parser.ml" in -# 939 "parsing/parser.mly" +# 940 "parsing/parser.mly" ( xs ) -# 30371 "parsing/parser.ml" +# 30822 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30404,14 +30855,14 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_x_ in let _v : (Parsetree.with_constraint list) = let xs = -# 935 "parsing/parser.mly" +# 936 "parsing/parser.mly" ( x :: xs ) -# 30410 "parsing/parser.ml" +# 30861 "parsing/parser.ml" in -# 939 "parsing/parser.mly" +# 940 "parsing/parser.mly" ( xs ) -# 30415 "parsing/parser.ml" +# 30866 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30434,14 +30885,14 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos_x_ in let _v : (Parsetree.row_field list) = let xs = -# 931 "parsing/parser.mly" +# 932 "parsing/parser.mly" ( [ x ] ) -# 30440 "parsing/parser.ml" +# 30891 "parsing/parser.ml" in -# 939 "parsing/parser.mly" +# 940 "parsing/parser.mly" ( xs ) -# 30445 "parsing/parser.ml" +# 30896 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30478,14 +30929,14 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_x_ in let _v : (Parsetree.row_field list) = let xs = -# 935 "parsing/parser.mly" +# 936 "parsing/parser.mly" ( x :: xs ) -# 30484 "parsing/parser.ml" +# 30935 "parsing/parser.ml" in -# 939 "parsing/parser.mly" +# 940 "parsing/parser.mly" ( xs ) -# 30489 "parsing/parser.ml" +# 30940 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30508,14 +30959,14 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos_x_ in let _v : (Parsetree.core_type list) = let xs = -# 931 "parsing/parser.mly" +# 932 "parsing/parser.mly" ( [ x ] ) -# 30514 "parsing/parser.ml" +# 30965 "parsing/parser.ml" in -# 939 "parsing/parser.mly" +# 940 "parsing/parser.mly" ( xs ) -# 30519 "parsing/parser.ml" +# 30970 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30552,14 +31003,14 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_x_ in let _v : (Parsetree.core_type list) = let xs = -# 935 "parsing/parser.mly" +# 936 "parsing/parser.mly" ( x :: xs ) -# 30558 "parsing/parser.ml" +# 31009 "parsing/parser.ml" in -# 939 "parsing/parser.mly" +# 940 "parsing/parser.mly" ( xs ) -# 30563 "parsing/parser.ml" +# 31014 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30582,14 +31033,14 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos_x_ in let _v : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = let xs = -# 931 "parsing/parser.mly" +# 932 "parsing/parser.mly" ( [ x ] ) -# 30588 "parsing/parser.ml" +# 31039 "parsing/parser.ml" in -# 939 "parsing/parser.mly" +# 940 "parsing/parser.mly" ( xs ) -# 30593 "parsing/parser.ml" +# 31044 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30626,14 +31077,14 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_x_ in let _v : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = let xs = -# 935 "parsing/parser.mly" +# 936 "parsing/parser.mly" ( x :: xs ) -# 30632 "parsing/parser.ml" +# 31083 "parsing/parser.ml" in -# 939 "parsing/parser.mly" +# 940 "parsing/parser.mly" ( xs ) -# 30637 "parsing/parser.ml" +# 31088 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30656,14 +31107,14 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos_x_ in let _v : (Parsetree.core_type list) = let xs = -# 931 "parsing/parser.mly" +# 932 "parsing/parser.mly" ( [ x ] ) -# 30662 "parsing/parser.ml" +# 31113 "parsing/parser.ml" in -# 939 "parsing/parser.mly" +# 940 "parsing/parser.mly" ( xs ) -# 30667 "parsing/parser.ml" +# 31118 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30700,14 +31151,14 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_x_ in let _v : (Parsetree.core_type list) = let xs = -# 935 "parsing/parser.mly" +# 936 "parsing/parser.mly" ( x :: xs ) -# 30706 "parsing/parser.ml" +# 31157 "parsing/parser.ml" in -# 939 "parsing/parser.mly" +# 940 "parsing/parser.mly" ( xs ) -# 30711 "parsing/parser.ml" +# 31162 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30744,9 +31195,9 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_x_ in let _v : (Parsetree.core_type list) = -# 962 "parsing/parser.mly" +# 963 "parsing/parser.mly" ( x :: xs ) -# 30750 "parsing/parser.ml" +# 31201 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30783,9 +31234,9 @@ module Tables = struct let _startpos = _startpos_x1_ in let _endpos = _endpos_x2_ in let _v : (Parsetree.core_type list) = -# 966 "parsing/parser.mly" +# 967 "parsing/parser.mly" ( [ x2; x1 ] ) -# 30789 "parsing/parser.ml" +# 31240 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30822,9 +31273,9 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_x_ in let _v : (Parsetree.expression list) = -# 962 "parsing/parser.mly" +# 963 "parsing/parser.mly" ( x :: xs ) -# 30828 "parsing/parser.ml" +# 31279 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30861,9 +31312,9 @@ module Tables = struct let _startpos = _startpos_x1_ in let _endpos = _endpos_x2_ in let _v : (Parsetree.expression list) = -# 966 "parsing/parser.mly" +# 967 "parsing/parser.mly" ( [ x2; x1 ] ) -# 30867 "parsing/parser.ml" +# 31318 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30900,9 +31351,9 @@ module Tables = struct let _startpos = _startpos_xs_ in let _endpos = _endpos_x_ in let _v : (Parsetree.core_type list) = -# 962 "parsing/parser.mly" +# 963 "parsing/parser.mly" ( x :: xs ) -# 30906 "parsing/parser.ml" +# 31357 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30939,9 +31390,9 @@ module Tables = struct let _startpos = _startpos_x1_ in let _endpos = _endpos_x2_ in let _v : (Parsetree.core_type list) = -# 966 "parsing/parser.mly" +# 967 "parsing/parser.mly" ( [ x2; x1 ] ) -# 30945 "parsing/parser.ml" +# 31396 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30964,9 +31415,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.row_field) = -# 3340 "parsing/parser.mly" +# 3381 "parsing/parser.mly" ( _1 ) -# 30970 "parsing/parser.ml" +# 31421 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -30992,9 +31443,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3342 "parsing/parser.mly" +# 3383 "parsing/parser.mly" ( Rf.inherit_ ~loc:(make_loc _sloc) _1 ) -# 30998 "parsing/parser.ml" +# 31449 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31019,12 +31470,12 @@ module Tables = struct let _v : (Parsetree.expression list) = let _2 = # 124 "<standard.mly>" ( None ) -# 31023 "parsing/parser.ml" +# 31474 "parsing/parser.ml" in -# 983 "parsing/parser.mly" +# 984 "parsing/parser.mly" ( [x] ) -# 31028 "parsing/parser.ml" +# 31479 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31058,13 +31509,13 @@ module Tables = struct # 126 "<standard.mly>" ( Some x ) -# 31062 "parsing/parser.ml" +# 31513 "parsing/parser.ml" in -# 983 "parsing/parser.mly" +# 984 "parsing/parser.mly" ( [x] ) -# 31068 "parsing/parser.ml" +# 31519 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31101,9 +31552,9 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos_xs_ in let _v : (Parsetree.expression list) = -# 987 "parsing/parser.mly" +# 988 "parsing/parser.mly" ( x :: xs ) -# 31107 "parsing/parser.ml" +# 31558 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31129,9 +31580,9 @@ module Tables = struct } = _menhir_stack in let oe : (Parsetree.expression option) = Obj.magic oe in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 31135 "parsing/parser.ml" +# 31586 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -31139,22 +31590,22 @@ module Tables = struct let _v : ((Asttypes.label Asttypes.loc * Parsetree.expression) list) = let _2 = # 124 "<standard.mly>" ( None ) -# 31143 "parsing/parser.ml" +# 31594 "parsing/parser.ml" in let x = let label = let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 31150 "parsing/parser.ml" +# 31601 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 31158 "parsing/parser.ml" +# 31609 "parsing/parser.ml" in let _startpos_label_ = _startpos__1_ in @@ -31162,7 +31613,7 @@ module Tables = struct let _symbolstartpos = _startpos_label_ in let _sloc = (_symbolstartpos, _endpos) in -# 2574 "parsing/parser.mly" +# 2579 "parsing/parser.mly" ( let e = match oe with | None -> @@ -31172,13 +31623,13 @@ module Tables = struct e in label, e ) -# 31176 "parsing/parser.ml" +# 31627 "parsing/parser.ml" in -# 983 "parsing/parser.mly" +# 984 "parsing/parser.mly" ( [x] ) -# 31182 "parsing/parser.ml" +# 31633 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31211,9 +31662,9 @@ module Tables = struct let x : unit = Obj.magic x in let oe : (Parsetree.expression option) = Obj.magic oe in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 31217 "parsing/parser.ml" +# 31668 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -31221,22 +31672,22 @@ module Tables = struct let _v : ((Asttypes.label Asttypes.loc * Parsetree.expression) list) = let _2 = # 126 "<standard.mly>" ( Some x ) -# 31225 "parsing/parser.ml" +# 31676 "parsing/parser.ml" in let x = let label = let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 31232 "parsing/parser.ml" +# 31683 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 31240 "parsing/parser.ml" +# 31691 "parsing/parser.ml" in let _startpos_label_ = _startpos__1_ in @@ -31244,7 +31695,7 @@ module Tables = struct let _symbolstartpos = _startpos_label_ in let _sloc = (_symbolstartpos, _endpos) in -# 2574 "parsing/parser.mly" +# 2579 "parsing/parser.mly" ( let e = match oe with | None -> @@ -31254,13 +31705,13 @@ module Tables = struct e in label, e ) -# 31258 "parsing/parser.ml" +# 31709 "parsing/parser.ml" in -# 983 "parsing/parser.mly" +# 984 "parsing/parser.mly" ( [x] ) -# 31264 "parsing/parser.ml" +# 31715 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31300,9 +31751,9 @@ module Tables = struct let _2 : unit = Obj.magic _2 in let oe : (Parsetree.expression option) = Obj.magic oe in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 31306 "parsing/parser.ml" +# 31757 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -31310,17 +31761,17 @@ module Tables = struct let _v : ((Asttypes.label Asttypes.loc * Parsetree.expression) list) = let x = let label = let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 31316 "parsing/parser.ml" +# 31767 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 31324 "parsing/parser.ml" +# 31775 "parsing/parser.ml" in let _startpos_label_ = _startpos__1_ in @@ -31328,7 +31779,7 @@ module Tables = struct let _symbolstartpos = _startpos_label_ in let _sloc = (_symbolstartpos, _endpos) in -# 2574 "parsing/parser.mly" +# 2579 "parsing/parser.mly" ( let e = match oe with | None -> @@ -31338,13 +31789,13 @@ module Tables = struct e in label, e ) -# 31342 "parsing/parser.ml" +# 31793 "parsing/parser.ml" in -# 987 "parsing/parser.mly" +# 988 "parsing/parser.mly" ( x :: xs ) -# 31348 "parsing/parser.ml" +# 31799 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31369,12 +31820,12 @@ module Tables = struct let _v : (Parsetree.pattern list) = let _2 = # 124 "<standard.mly>" ( None ) -# 31373 "parsing/parser.ml" +# 31824 "parsing/parser.ml" in -# 983 "parsing/parser.mly" +# 984 "parsing/parser.mly" ( [x] ) -# 31378 "parsing/parser.ml" +# 31829 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31408,13 +31859,13 @@ module Tables = struct # 126 "<standard.mly>" ( Some x ) -# 31412 "parsing/parser.ml" +# 31863 "parsing/parser.ml" in -# 983 "parsing/parser.mly" +# 984 "parsing/parser.mly" ( [x] ) -# 31418 "parsing/parser.ml" +# 31869 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31451,9 +31902,9 @@ module Tables = struct let _startpos = _startpos_x_ in let _endpos = _endpos_xs_ in let _v : (Parsetree.pattern list) = -# 987 "parsing/parser.mly" +# 988 "parsing/parser.mly" ( x :: xs ) -# 31457 "parsing/parser.ml" +# 31908 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31492,7 +31943,7 @@ module Tables = struct let _v : ((Longident.t Asttypes.loc * Parsetree.expression) list) = let _2 = # 124 "<standard.mly>" ( None ) -# 31496 "parsing/parser.ml" +# 31947 "parsing/parser.ml" in let x = let label = @@ -31500,9 +31951,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 31506 "parsing/parser.ml" +# 31957 "parsing/parser.ml" in let _startpos_label_ = _startpos__1_ in @@ -31510,7 +31961,7 @@ module Tables = struct let _symbolstartpos = _startpos_label_ in let _sloc = (_symbolstartpos, _endpos) in -# 2557 "parsing/parser.mly" +# 2562 "parsing/parser.mly" ( let e = match eo with | None -> @@ -31520,13 +31971,13 @@ module Tables = struct e in label, mkexp_opt_constraint ~loc:_sloc e c ) -# 31524 "parsing/parser.ml" +# 31975 "parsing/parser.ml" in -# 983 "parsing/parser.mly" +# 984 "parsing/parser.mly" ( [x] ) -# 31530 "parsing/parser.ml" +# 31981 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31572,7 +32023,7 @@ module Tables = struct let _v : ((Longident.t Asttypes.loc * Parsetree.expression) list) = let _2 = # 126 "<standard.mly>" ( Some x ) -# 31576 "parsing/parser.ml" +# 32027 "parsing/parser.ml" in let x = let label = @@ -31580,9 +32031,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 31586 "parsing/parser.ml" +# 32037 "parsing/parser.ml" in let _startpos_label_ = _startpos__1_ in @@ -31590,7 +32041,7 @@ module Tables = struct let _symbolstartpos = _startpos_label_ in let _sloc = (_symbolstartpos, _endpos) in -# 2557 "parsing/parser.mly" +# 2562 "parsing/parser.mly" ( let e = match eo with | None -> @@ -31600,13 +32051,13 @@ module Tables = struct e in label, mkexp_opt_constraint ~loc:_sloc e c ) -# 31604 "parsing/parser.ml" +# 32055 "parsing/parser.ml" in -# 983 "parsing/parser.mly" +# 984 "parsing/parser.mly" ( [x] ) -# 31610 "parsing/parser.ml" +# 32061 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31662,9 +32113,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 31668 "parsing/parser.ml" +# 32119 "parsing/parser.ml" in let _startpos_label_ = _startpos__1_ in @@ -31672,7 +32123,7 @@ module Tables = struct let _symbolstartpos = _startpos_label_ in let _sloc = (_symbolstartpos, _endpos) in -# 2557 "parsing/parser.mly" +# 2562 "parsing/parser.mly" ( let e = match eo with | None -> @@ -31682,13 +32133,13 @@ module Tables = struct e in label, mkexp_opt_constraint ~loc:_sloc e c ) -# 31686 "parsing/parser.ml" +# 32137 "parsing/parser.ml" in -# 987 "parsing/parser.mly" +# 988 "parsing/parser.mly" ( x :: xs ) -# 31692 "parsing/parser.ml" +# 32143 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31711,9 +32162,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.expression) = -# 2073 "parsing/parser.mly" +# 2078 "parsing/parser.mly" ( _1 ) -# 31717 "parsing/parser.ml" +# 32168 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31743,9 +32194,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.expression) = -# 2074 "parsing/parser.mly" +# 2079 "parsing/parser.mly" ( _1 ) -# 31749 "parsing/parser.ml" +# 32200 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31783,24 +32234,24 @@ module Tables = struct let _endpos = _endpos__3_ in let _v : (Parsetree.expression) = let _1 = let _1 = -# 2076 "parsing/parser.mly" +# 2081 "parsing/parser.mly" ( Pexp_sequence(_1, _3) ) -# 31789 "parsing/parser.ml" +# 32240 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 31798 "parsing/parser.ml" +# 32249 "parsing/parser.ml" in -# 2077 "parsing/parser.mly" +# 2082 "parsing/parser.mly" ( _1 ) -# 31804 "parsing/parser.ml" +# 32255 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31854,11 +32305,11 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2079 "parsing/parser.mly" +# 2084 "parsing/parser.mly" ( let seq = mkexp ~loc:_sloc (Pexp_sequence (_1, _5)) in let payload = PStr [mkstrexp seq []] in mkexp ~loc:_sloc (Pexp_extension (_4, payload)) ) -# 31862 "parsing/parser.ml" +# 32313 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31925,18 +32376,18 @@ module Tables = struct let _v : (Parsetree.type_exception * string Asttypes.loc option) = let attrs = let _1 = _1_inlined4 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 31931 "parsing/parser.ml" +# 32382 "parsing/parser.ml" in let _endpos_attrs_ = _endpos__1_inlined4_ in let attrs2 = let _1 = _1_inlined3 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 31940 "parsing/parser.ml" +# 32391 "parsing/parser.ml" in let id = @@ -31945,31 +32396,31 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 31951 "parsing/parser.ml" +# 32402 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 31959 "parsing/parser.ml" +# 32410 "parsing/parser.ml" in let _endpos = _endpos_attrs_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3021 "parsing/parser.mly" +# 3028 "parsing/parser.mly" ( let args, res = args_res in let loc = make_loc _sloc in let docs = symbol_docs _sloc in Te.mk_exception ~attrs (Te.decl id ~args ?res ~attrs:(attrs1 @ attrs2) ~loc ~docs) , ext ) -# 31973 "parsing/parser.ml" +# 32424 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -31995,21 +32446,21 @@ module Tables = struct let _1 = # 260 "<standard.mly>" ( List.flatten xss ) -# 31999 "parsing/parser.ml" +# 32450 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 806 "parsing/parser.mly" +# 807 "parsing/parser.mly" ( extra_sig _startpos _endpos _1 ) -# 32007 "parsing/parser.ml" +# 32458 "parsing/parser.ml" in -# 1542 "parsing/parser.mly" +# 1545 "parsing/parser.mly" ( _1 ) -# 32013 "parsing/parser.ml" +# 32464 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -32041,9 +32492,9 @@ module Tables = struct let _v : (Parsetree.signature_item) = let _2 = let _1 = _1_inlined1 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 32047 "parsing/parser.ml" +# 32498 "parsing/parser.ml" in let _endpos__2_ = _endpos__1_inlined1_ in @@ -32051,10 +32502,45 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1557 "parsing/parser.mly" +# 1560 "parsing/parser.mly" ( let docs = symbol_docs _sloc in mksig ~loc:_sloc (Psig_extension (_1, (add_docs_attrs docs _2))) ) -# 32058 "parsing/parser.ml" +# 32509 "parsing/parser.ml" + in + { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = Obj.repr _v; + MenhirLib.EngineTypes.startp = _startpos; + MenhirLib.EngineTypes.endp = _endpos; + MenhirLib.EngineTypes.next = _menhir_stack; + }); + (fun _menhir_env -> + let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in + let { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _2; + MenhirLib.EngineTypes.startp = _startpos__2_; + MenhirLib.EngineTypes.endp = _endpos__2_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = _1; + MenhirLib.EngineTypes.startp = _startpos__1_; + MenhirLib.EngineTypes.endp = _endpos__1_; + MenhirLib.EngineTypes.next = _menhir_stack; + }; + } = _menhir_stack in + let _2 : (Parsetree.effect_constructor) = Obj.magic _2 in + let _1 : unit = Obj.magic _1 in + let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in + let _startpos = _startpos__1_ in + let _endpos = _endpos__2_ in + let _v : (Parsetree.signature_item) = let _endpos = _endpos__2_ in + let _symbolstartpos = _startpos__1_ in + let _sloc = (_symbolstartpos, _endpos) in + +# 1563 "parsing/parser.mly" + ( mksig ~loc:_sloc (Psig_effect _2) ) +# 32544 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -32078,23 +32564,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.signature_item) = let _1 = let _1 = -# 1561 "parsing/parser.mly" +# 1566 "parsing/parser.mly" ( Psig_attribute _1 ) -# 32084 "parsing/parser.ml" +# 32570 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 854 "parsing/parser.mly" +# 855 "parsing/parser.mly" ( mksig ~loc:_sloc _1 ) -# 32092 "parsing/parser.ml" +# 32578 "parsing/parser.ml" in -# 1563 "parsing/parser.mly" +# 1568 "parsing/parser.mly" ( _1 ) -# 32098 "parsing/parser.ml" +# 32584 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -32118,23 +32604,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.signature_item) = let _1 = let _1 = -# 1566 "parsing/parser.mly" +# 1571 "parsing/parser.mly" ( psig_value _1 ) -# 32124 "parsing/parser.ml" +# 32610 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 32132 "parsing/parser.ml" +# 32618 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 32138 "parsing/parser.ml" +# 32624 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -32158,23 +32644,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.signature_item) = let _1 = let _1 = -# 1568 "parsing/parser.mly" +# 1573 "parsing/parser.mly" ( psig_value _1 ) -# 32164 "parsing/parser.ml" +# 32650 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 32172 "parsing/parser.ml" +# 32658 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 32178 "parsing/parser.ml" +# 32664 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -32209,26 +32695,26 @@ module Tables = struct let _1 = let _1 = let _1 = -# 1044 "parsing/parser.mly" +# 1045 "parsing/parser.mly" ( let (x, b) = a in x, b :: bs ) -# 32215 "parsing/parser.ml" +# 32701 "parsing/parser.ml" in -# 2842 "parsing/parser.mly" +# 2849 "parsing/parser.mly" ( _1 ) -# 32220 "parsing/parser.ml" +# 32706 "parsing/parser.ml" in -# 2825 "parsing/parser.mly" +# 2832 "parsing/parser.mly" ( _1 ) -# 32226 "parsing/parser.ml" +# 32712 "parsing/parser.ml" in -# 1570 "parsing/parser.mly" +# 1575 "parsing/parser.mly" ( psig_type _1 ) -# 32232 "parsing/parser.ml" +# 32718 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_bs_, _startpos_a_) in @@ -32236,15 +32722,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 32242 "parsing/parser.ml" +# 32728 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 32248 "parsing/parser.ml" +# 32734 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -32279,26 +32765,26 @@ module Tables = struct let _1 = let _1 = let _1 = -# 1044 "parsing/parser.mly" +# 1045 "parsing/parser.mly" ( let (x, b) = a in x, b :: bs ) -# 32285 "parsing/parser.ml" +# 32771 "parsing/parser.ml" in -# 2842 "parsing/parser.mly" +# 2849 "parsing/parser.mly" ( _1 ) -# 32290 "parsing/parser.ml" +# 32776 "parsing/parser.ml" in -# 2830 "parsing/parser.mly" +# 2837 "parsing/parser.mly" ( _1 ) -# 32296 "parsing/parser.ml" +# 32782 "parsing/parser.ml" in -# 1572 "parsing/parser.mly" +# 1577 "parsing/parser.mly" ( psig_typesubst _1 ) -# 32302 "parsing/parser.ml" +# 32788 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_bs_, _startpos_a_) in @@ -32306,15 +32792,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 32312 "parsing/parser.ml" +# 32798 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 32318 "parsing/parser.ml" +# 32804 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -32399,16 +32885,16 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 32405 "parsing/parser.ml" +# 32891 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in let cs = -# 1036 "parsing/parser.mly" +# 1037 "parsing/parser.mly" ( List.rev xs ) -# 32412 "parsing/parser.ml" +# 32898 "parsing/parser.ml" in let tid = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in @@ -32416,46 +32902,46 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 32422 "parsing/parser.ml" +# 32908 "parsing/parser.ml" in let _4 = -# 3585 "parsing/parser.mly" +# 3626 "parsing/parser.mly" ( Recursive ) -# 32428 "parsing/parser.ml" +# 32914 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 32435 "parsing/parser.ml" +# 32921 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3090 "parsing/parser.mly" +# 3131 "parsing/parser.mly" ( let docs = symbol_docs _sloc in let attrs = attrs1 @ attrs2 in Te.mk tid cs ~params ~priv ~attrs ~docs, ext ) -# 32447 "parsing/parser.ml" +# 32933 "parsing/parser.ml" in -# 3077 "parsing/parser.mly" +# 3118 "parsing/parser.mly" ( _1 ) -# 32453 "parsing/parser.ml" +# 32939 "parsing/parser.ml" in -# 1574 "parsing/parser.mly" +# 1579 "parsing/parser.mly" ( psig_typext _1 ) -# 32459 "parsing/parser.ml" +# 32945 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined3_ in @@ -32463,15 +32949,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 32469 "parsing/parser.ml" +# 32955 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 32475 "parsing/parser.ml" +# 32961 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -32563,16 +33049,16 @@ module Tables = struct let attrs2 = let _1 = _1_inlined4 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 32569 "parsing/parser.ml" +# 33055 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined4_ in let cs = -# 1036 "parsing/parser.mly" +# 1037 "parsing/parser.mly" ( List.rev xs ) -# 32576 "parsing/parser.ml" +# 33062 "parsing/parser.ml" in let tid = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in @@ -32580,9 +33066,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 32586 "parsing/parser.ml" +# 33072 "parsing/parser.ml" in let _4 = @@ -32591,41 +33077,41 @@ module Tables = struct let _startpos = _startpos__1_ in let _loc = (_startpos, _endpos) in -# 3586 "parsing/parser.mly" +# 3627 "parsing/parser.mly" ( not_expecting _loc "nonrec flag" ) -# 32597 "parsing/parser.ml" +# 33083 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 32605 "parsing/parser.ml" +# 33091 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3090 "parsing/parser.mly" +# 3131 "parsing/parser.mly" ( let docs = symbol_docs _sloc in let attrs = attrs1 @ attrs2 in Te.mk tid cs ~params ~priv ~attrs ~docs, ext ) -# 32617 "parsing/parser.ml" +# 33103 "parsing/parser.ml" in -# 3077 "parsing/parser.mly" +# 3118 "parsing/parser.mly" ( _1 ) -# 32623 "parsing/parser.ml" +# 33109 "parsing/parser.ml" in -# 1574 "parsing/parser.mly" +# 1579 "parsing/parser.mly" ( psig_typext _1 ) -# 32629 "parsing/parser.ml" +# 33115 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined4_ in @@ -32633,15 +33119,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 32639 "parsing/parser.ml" +# 33125 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 32645 "parsing/parser.ml" +# 33131 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -32665,23 +33151,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.signature_item) = let _1 = let _1 = -# 1576 "parsing/parser.mly" +# 1581 "parsing/parser.mly" ( psig_exception _1 ) -# 32671 "parsing/parser.ml" +# 33157 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 32679 "parsing/parser.ml" +# 33165 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 32685 "parsing/parser.ml" +# 33171 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -32744,9 +33230,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 32750 "parsing/parser.ml" +# 33236 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -32756,37 +33242,37 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 32762 "parsing/parser.ml" +# 33248 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 32770 "parsing/parser.ml" +# 33256 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1605 "parsing/parser.mly" +# 1610 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in let docs = symbol_docs _sloc in Md.mk name body ~attrs ~loc ~docs, ext ) -# 32784 "parsing/parser.ml" +# 33270 "parsing/parser.ml" in -# 1578 "parsing/parser.mly" +# 1583 "parsing/parser.mly" ( let (body, ext) = _1 in (Psig_module body, ext) ) -# 32790 "parsing/parser.ml" +# 33276 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined3_ in @@ -32794,15 +33280,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 32800 "parsing/parser.ml" +# 33286 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 32806 "parsing/parser.ml" +# 33292 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -32872,9 +33358,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined4 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 32878 "parsing/parser.ml" +# 33364 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined4_ in @@ -32885,9 +33371,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 32891 "parsing/parser.ml" +# 33377 "parsing/parser.ml" in let (_endpos_id_, _startpos_id_) = (_endpos__1_, _startpos__1_) in @@ -32895,9 +33381,9 @@ module Tables = struct let _symbolstartpos = _startpos_id_ in let _sloc = (_symbolstartpos, _endpos) in -# 1641 "parsing/parser.mly" +# 1646 "parsing/parser.mly" ( Mty.alias ~loc:(make_loc _sloc) id ) -# 32901 "parsing/parser.ml" +# 33387 "parsing/parser.ml" in let name = @@ -32906,37 +33392,37 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 32912 "parsing/parser.ml" +# 33398 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 32920 "parsing/parser.ml" +# 33406 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1632 "parsing/parser.mly" +# 1637 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in let docs = symbol_docs _sloc in Md.mk name body ~attrs ~loc ~docs, ext ) -# 32934 "parsing/parser.ml" +# 33420 "parsing/parser.ml" in -# 1580 "parsing/parser.mly" +# 1585 "parsing/parser.mly" ( let (body, ext) = _1 in (Psig_module body, ext) ) -# 32940 "parsing/parser.ml" +# 33426 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined4_ in @@ -32944,15 +33430,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 32950 "parsing/parser.ml" +# 33436 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 32956 "parsing/parser.ml" +# 33442 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -32976,23 +33462,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.signature_item) = let _1 = let _1 = -# 1582 "parsing/parser.mly" +# 1587 "parsing/parser.mly" ( let (body, ext) = _1 in (Psig_modsubst body, ext) ) -# 32982 "parsing/parser.ml" +# 33468 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 32990 "parsing/parser.ml" +# 33476 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 32996 "parsing/parser.ml" +# 33482 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33078,9 +33564,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 33084 "parsing/parser.ml" +# 33570 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -33090,49 +33576,49 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 33096 "parsing/parser.ml" +# 33582 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 33104 "parsing/parser.ml" +# 33590 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1675 "parsing/parser.mly" +# 1680 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in let docs = symbol_docs _sloc in ext, Md.mk name mty ~attrs ~loc ~docs ) -# 33118 "parsing/parser.ml" +# 33604 "parsing/parser.ml" in -# 1044 "parsing/parser.mly" +# 1045 "parsing/parser.mly" ( let (x, b) = a in x, b :: bs ) -# 33124 "parsing/parser.ml" +# 33610 "parsing/parser.ml" in -# 1664 "parsing/parser.mly" +# 1669 "parsing/parser.mly" ( _1 ) -# 33130 "parsing/parser.ml" +# 33616 "parsing/parser.ml" in -# 1584 "parsing/parser.mly" +# 1589 "parsing/parser.mly" ( let (ext, l) = _1 in (Psig_recmodule l, ext) ) -# 33136 "parsing/parser.ml" +# 33622 "parsing/parser.ml" in let _endpos__1_ = _endpos_bs_ in @@ -33140,15 +33626,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 33146 "parsing/parser.ml" +# 33632 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 33152 "parsing/parser.ml" +# 33638 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33172,23 +33658,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.signature_item) = let _1 = let _1 = -# 1586 "parsing/parser.mly" +# 1591 "parsing/parser.mly" ( let (body, ext) = _1 in (Psig_modtype body, ext) ) -# 33178 "parsing/parser.ml" +# 33664 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 33186 "parsing/parser.ml" +# 33672 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 33192 "parsing/parser.ml" +# 33678 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33212,23 +33698,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.signature_item) = let _1 = let _1 = -# 1588 "parsing/parser.mly" +# 1593 "parsing/parser.mly" ( let (body, ext) = _1 in (Psig_open body, ext) ) -# 33218 "parsing/parser.ml" +# 33704 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 33226 "parsing/parser.ml" +# 33712 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 33232 "parsing/parser.ml" +# 33718 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33284,38 +33770,38 @@ module Tables = struct let attrs2 = let _1 = _1_inlined2 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 33290 "parsing/parser.ml" +# 33776 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined2_ in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 33299 "parsing/parser.ml" +# 33785 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1434 "parsing/parser.mly" +# 1437 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in let docs = symbol_docs _sloc in Incl.mk thing ~attrs ~loc ~docs, ext ) -# 33313 "parsing/parser.ml" +# 33799 "parsing/parser.ml" in -# 1590 "parsing/parser.mly" +# 1595 "parsing/parser.mly" ( psig_include _1 ) -# 33319 "parsing/parser.ml" +# 33805 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined2_ in @@ -33323,15 +33809,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 33329 "parsing/parser.ml" +# 33815 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 33335 "parsing/parser.ml" +# 33821 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33408,9 +33894,9 @@ module Tables = struct let cty : (Parsetree.class_type) = Obj.magic cty in let _7 : unit = Obj.magic _7 in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 33414 "parsing/parser.ml" +# 33900 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let params : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = Obj.magic params in let virt : (Asttypes.virtual_flag) = Obj.magic virt in @@ -33428,9 +33914,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 33434 "parsing/parser.ml" +# 33920 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -33440,24 +33926,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 33446 "parsing/parser.ml" +# 33932 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 33454 "parsing/parser.ml" +# 33940 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2005 "parsing/parser.mly" +# 2010 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in @@ -33465,25 +33951,25 @@ module Tables = struct ext, Ci.mk id cty ~virt ~params ~attrs ~loc ~docs ) -# 33469 "parsing/parser.ml" +# 33955 "parsing/parser.ml" in -# 1044 "parsing/parser.mly" +# 1045 "parsing/parser.mly" ( let (x, b) = a in x, b :: bs ) -# 33475 "parsing/parser.ml" +# 33961 "parsing/parser.ml" in -# 1993 "parsing/parser.mly" +# 1998 "parsing/parser.mly" ( _1 ) -# 33481 "parsing/parser.ml" +# 33967 "parsing/parser.ml" in -# 1592 "parsing/parser.mly" +# 1597 "parsing/parser.mly" ( let (ext, l) = _1 in (Psig_class l, ext) ) -# 33487 "parsing/parser.ml" +# 33973 "parsing/parser.ml" in let _endpos__1_ = _endpos_bs_ in @@ -33491,15 +33977,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 33497 "parsing/parser.ml" +# 33983 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 33503 "parsing/parser.ml" +# 33989 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33523,23 +34009,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.signature_item) = let _1 = let _1 = -# 1594 "parsing/parser.mly" +# 1599 "parsing/parser.mly" ( let (ext, l) = _1 in (Psig_class_type l, ext) ) -# 33529 "parsing/parser.ml" +# 34015 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 871 "parsing/parser.mly" +# 872 "parsing/parser.mly" ( wrap_mksig_ext ~loc:_sloc _1 ) -# 33537 "parsing/parser.ml" +# 34023 "parsing/parser.ml" in -# 1596 "parsing/parser.mly" +# 1601 "parsing/parser.mly" ( _1 ) -# 33543 "parsing/parser.ml" +# 34029 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33562,9 +34048,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.constant) = -# 3416 "parsing/parser.mly" +# 3457 "parsing/parser.mly" ( _1 ) -# 33568 "parsing/parser.ml" +# 34054 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33589,18 +34075,18 @@ module Tables = struct }; } = _menhir_stack in let _2 : ( -# 633 "parsing/parser.mly" +# 634 "parsing/parser.mly" (string * char option) -# 33595 "parsing/parser.ml" +# 34081 "parsing/parser.ml" ) = Obj.magic _2 in let _1 : unit = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.constant) = -# 3417 "parsing/parser.mly" +# 3458 "parsing/parser.mly" ( let (n, m) = _2 in Pconst_integer("-" ^ n, m) ) -# 33604 "parsing/parser.ml" +# 34090 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33625,18 +34111,18 @@ module Tables = struct }; } = _menhir_stack in let _2 : ( -# 612 "parsing/parser.mly" +# 613 "parsing/parser.mly" (string * char option) -# 33631 "parsing/parser.ml" +# 34117 "parsing/parser.ml" ) = Obj.magic _2 in let _1 : unit = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.constant) = -# 3418 "parsing/parser.mly" +# 3459 "parsing/parser.mly" ( let (f, m) = _2 in Pconst_float("-" ^ f, m) ) -# 33640 "parsing/parser.ml" +# 34126 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33661,18 +34147,18 @@ module Tables = struct }; } = _menhir_stack in let _2 : ( -# 633 "parsing/parser.mly" +# 634 "parsing/parser.mly" (string * char option) -# 33667 "parsing/parser.ml" +# 34153 "parsing/parser.ml" ) = Obj.magic _2 in let _1 : unit = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.constant) = -# 3419 "parsing/parser.mly" +# 3460 "parsing/parser.mly" ( let (n, m) = _2 in Pconst_integer (n, m) ) -# 33676 "parsing/parser.ml" +# 34162 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33697,18 +34183,18 @@ module Tables = struct }; } = _menhir_stack in let _2 : ( -# 612 "parsing/parser.mly" +# 613 "parsing/parser.mly" (string * char option) -# 33703 "parsing/parser.ml" +# 34189 "parsing/parser.ml" ) = Obj.magic _2 in let _1 : unit = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.constant) = -# 3420 "parsing/parser.mly" +# 3461 "parsing/parser.mly" ( let (f, m) = _2 in Pconst_float(f, m) ) -# 33712 "parsing/parser.ml" +# 34198 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33749,18 +34235,18 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 2757 "parsing/parser.mly" +# 2764 "parsing/parser.mly" ( let fields, closed = _1 in let closed = match closed with Some () -> Open | None -> Closed in fields, closed ) -# 33757 "parsing/parser.ml" +# 34243 "parsing/parser.ml" in -# 2728 "parsing/parser.mly" +# 2735 "parsing/parser.mly" ( let (fields, closed) = _2 in Ppat_record(fields, closed) ) -# 33764 "parsing/parser.ml" +# 34250 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -33768,15 +34254,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 33774 "parsing/parser.ml" +# 34260 "parsing/parser.ml" in -# 2742 "parsing/parser.mly" +# 2749 "parsing/parser.mly" ( _1 ) -# 33780 "parsing/parser.ml" +# 34266 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33817,19 +34303,19 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 2757 "parsing/parser.mly" +# 2764 "parsing/parser.mly" ( let fields, closed = _1 in let closed = match closed with Some () -> Open | None -> Closed in fields, closed ) -# 33825 "parsing/parser.ml" +# 34311 "parsing/parser.ml" in let _loc__3_ = (_startpos__3_, _endpos__3_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2731 "parsing/parser.mly" +# 2738 "parsing/parser.mly" ( unclosed "{" _loc__1_ "}" _loc__3_ ) -# 33833 "parsing/parser.ml" +# 34319 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -33837,15 +34323,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 33843 "parsing/parser.ml" +# 34329 "parsing/parser.ml" in -# 2742 "parsing/parser.mly" +# 2749 "parsing/parser.mly" ( _1 ) -# 33849 "parsing/parser.ml" +# 34335 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33884,15 +34370,15 @@ module Tables = struct let _v : (Parsetree.pattern) = let _1 = let _1 = let _2 = -# 2751 "parsing/parser.mly" +# 2758 "parsing/parser.mly" ( ps ) -# 33890 "parsing/parser.ml" +# 34376 "parsing/parser.ml" in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2733 "parsing/parser.mly" +# 2740 "parsing/parser.mly" ( fst (mktailpat _loc__3_ _2) ) -# 33896 "parsing/parser.ml" +# 34382 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -33900,15 +34386,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 33906 "parsing/parser.ml" +# 34392 "parsing/parser.ml" in -# 2742 "parsing/parser.mly" +# 2749 "parsing/parser.mly" ( _1 ) -# 33912 "parsing/parser.ml" +# 34398 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -33947,16 +34433,16 @@ module Tables = struct let _v : (Parsetree.pattern) = let _1 = let _1 = let _2 = -# 2751 "parsing/parser.mly" +# 2758 "parsing/parser.mly" ( ps ) -# 33953 "parsing/parser.ml" +# 34439 "parsing/parser.ml" in let _loc__3_ = (_startpos__3_, _endpos__3_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2735 "parsing/parser.mly" +# 2742 "parsing/parser.mly" ( unclosed "[" _loc__1_ "]" _loc__3_ ) -# 33960 "parsing/parser.ml" +# 34446 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -33964,15 +34450,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 33970 "parsing/parser.ml" +# 34456 "parsing/parser.ml" in -# 2742 "parsing/parser.mly" +# 2749 "parsing/parser.mly" ( _1 ) -# 33976 "parsing/parser.ml" +# 34462 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34011,14 +34497,14 @@ module Tables = struct let _v : (Parsetree.pattern) = let _1 = let _1 = let _2 = -# 2751 "parsing/parser.mly" +# 2758 "parsing/parser.mly" ( ps ) -# 34017 "parsing/parser.ml" +# 34503 "parsing/parser.ml" in -# 2737 "parsing/parser.mly" +# 2744 "parsing/parser.mly" ( Ppat_array _2 ) -# 34022 "parsing/parser.ml" +# 34508 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -34026,15 +34512,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 34032 "parsing/parser.ml" +# 34518 "parsing/parser.ml" in -# 2742 "parsing/parser.mly" +# 2749 "parsing/parser.mly" ( _1 ) -# 34038 "parsing/parser.ml" +# 34524 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34065,24 +34551,24 @@ module Tables = struct let _endpos = _endpos__2_ in let _v : (Parsetree.pattern) = let _1 = let _1 = -# 2739 "parsing/parser.mly" +# 2746 "parsing/parser.mly" ( Ppat_array [] ) -# 34071 "parsing/parser.ml" +# 34557 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 34080 "parsing/parser.ml" +# 34566 "parsing/parser.ml" in -# 2742 "parsing/parser.mly" +# 2749 "parsing/parser.mly" ( _1 ) -# 34086 "parsing/parser.ml" +# 34572 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34121,16 +34607,16 @@ module Tables = struct let _v : (Parsetree.pattern) = let _1 = let _1 = let _2 = -# 2751 "parsing/parser.mly" +# 2758 "parsing/parser.mly" ( ps ) -# 34127 "parsing/parser.ml" +# 34613 "parsing/parser.ml" in let _loc__3_ = (_startpos__3_, _endpos__3_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2741 "parsing/parser.mly" +# 2748 "parsing/parser.mly" ( unclosed "[|" _loc__1_ "|]" _loc__3_ ) -# 34134 "parsing/parser.ml" +# 34620 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -34138,15 +34624,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 34144 "parsing/parser.ml" +# 34630 "parsing/parser.ml" in -# 2742 "parsing/parser.mly" +# 2749 "parsing/parser.mly" ( _1 ) -# 34150 "parsing/parser.ml" +# 34636 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34186,9 +34672,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2240 "parsing/parser.mly" +# 2245 "parsing/parser.mly" ( reloc_exp ~loc:_sloc _2 ) -# 34192 "parsing/parser.ml" +# 34678 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34227,9 +34713,9 @@ module Tables = struct let _v : (Parsetree.expression) = let _loc__3_ = (_startpos__3_, _endpos__3_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2242 "parsing/parser.mly" +# 2247 "parsing/parser.mly" ( unclosed "(" _loc__1_ ")" _loc__3_ ) -# 34233 "parsing/parser.ml" +# 34719 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34276,9 +34762,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2244 "parsing/parser.mly" +# 2249 "parsing/parser.mly" ( mkexp_constraint ~loc:_sloc _2 _3 ) -# 34282 "parsing/parser.ml" +# 34768 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34332,9 +34818,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2246 "parsing/parser.mly" +# 2251 "parsing/parser.mly" ( array_get ~loc:_sloc _1 _4 ) -# 34338 "parsing/parser.ml" +# 34824 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34387,9 +34873,9 @@ module Tables = struct let _v : (Parsetree.expression) = let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2248 "parsing/parser.mly" +# 2253 "parsing/parser.mly" ( unclosed "(" _loc__3_ ")" _loc__5_ ) -# 34393 "parsing/parser.ml" +# 34879 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34443,9 +34929,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2250 "parsing/parser.mly" +# 2255 "parsing/parser.mly" ( string_get ~loc:_sloc _1 _4 ) -# 34449 "parsing/parser.ml" +# 34935 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34498,9 +34984,9 @@ module Tables = struct let _v : (Parsetree.expression) = let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2252 "parsing/parser.mly" +# 2257 "parsing/parser.mly" ( unclosed "[" _loc__3_ "]" _loc__5_ ) -# 34504 "parsing/parser.ml" +# 34990 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34546,26 +35032,26 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _3 : unit = Obj.magic _3 in let _2 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 34552 "parsing/parser.ml" +# 35038 "parsing/parser.ml" ) = Obj.magic _2 in let _1 : (Parsetree.expression) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__5_ in let _v : (Parsetree.expression) = let _4 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 34561 "parsing/parser.ml" +# 35047 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2254 "parsing/parser.mly" +# 2259 "parsing/parser.mly" ( dotop_get ~loc:_sloc lident bracket _2 _1 _4 ) -# 34569 "parsing/parser.ml" +# 35055 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34611,25 +35097,25 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _3 : unit = Obj.magic _3 in let _2 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 34617 "parsing/parser.ml" +# 35103 "parsing/parser.ml" ) = Obj.magic _2 in let _1 : (Parsetree.expression) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__5_ in let _v : (Parsetree.expression) = let _4 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 34626 "parsing/parser.ml" +# 35112 "parsing/parser.ml" in let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2256 "parsing/parser.mly" +# 2261 "parsing/parser.mly" ( unclosed "[" _loc__3_ "]" _loc__5_ ) -# 34633 "parsing/parser.ml" +# 35119 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34675,26 +35161,26 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _3 : unit = Obj.magic _3 in let _2 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 34681 "parsing/parser.ml" +# 35167 "parsing/parser.ml" ) = Obj.magic _2 in let _1 : (Parsetree.expression) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__5_ in let _v : (Parsetree.expression) = let _4 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 34690 "parsing/parser.ml" +# 35176 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2258 "parsing/parser.mly" +# 2263 "parsing/parser.mly" ( dotop_get ~loc:_sloc lident paren _2 _1 _4 ) -# 34698 "parsing/parser.ml" +# 35184 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34740,25 +35226,25 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _3 : unit = Obj.magic _3 in let _2 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 34746 "parsing/parser.ml" +# 35232 "parsing/parser.ml" ) = Obj.magic _2 in let _1 : (Parsetree.expression) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__5_ in let _v : (Parsetree.expression) = let _4 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 34755 "parsing/parser.ml" +# 35241 "parsing/parser.ml" in let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2260 "parsing/parser.mly" +# 2265 "parsing/parser.mly" ( unclosed "(" _loc__3_ ")" _loc__5_ ) -# 34762 "parsing/parser.ml" +# 35248 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34804,26 +35290,26 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _3 : unit = Obj.magic _3 in let _2 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 34810 "parsing/parser.ml" +# 35296 "parsing/parser.ml" ) = Obj.magic _2 in let _1 : (Parsetree.expression) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__5_ in let _v : (Parsetree.expression) = let _4 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 34819 "parsing/parser.ml" +# 35305 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2262 "parsing/parser.mly" +# 2267 "parsing/parser.mly" ( dotop_get ~loc:_sloc lident brace _2 _1 _4 ) -# 34827 "parsing/parser.ml" +# 35313 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34869,9 +35355,9 @@ module Tables = struct let _4 : (Parsetree.expression) = Obj.magic _4 in let _3 : unit = Obj.magic _3 in let _2 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 34875 "parsing/parser.ml" +# 35361 "parsing/parser.ml" ) = Obj.magic _2 in let _1 : (Parsetree.expression) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -34880,9 +35366,9 @@ module Tables = struct let _v : (Parsetree.expression) = let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2264 "parsing/parser.mly" +# 2269 "parsing/parser.mly" ( unclosed "{" _loc__3_ "}" _loc__5_ ) -# 34886 "parsing/parser.ml" +# 35372 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -34940,9 +35426,9 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _5 : unit = Obj.magic _5 in let _4 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 34946 "parsing/parser.ml" +# 35432 "parsing/parser.ml" ) = Obj.magic _4 in let _3 : (Longident.t) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in @@ -34951,17 +35437,17 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__7_ in let _v : (Parsetree.expression) = let _6 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 34957 "parsing/parser.ml" +# 35443 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2266 "parsing/parser.mly" +# 2271 "parsing/parser.mly" ( dotop_get ~loc:_sloc (ldot _3) bracket _4 _1 _6 ) -# 34965 "parsing/parser.ml" +# 35451 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -35019,9 +35505,9 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _5 : unit = Obj.magic _5 in let _4 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 35025 "parsing/parser.ml" +# 35511 "parsing/parser.ml" ) = Obj.magic _4 in let _3 : (Longident.t) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in @@ -35030,16 +35516,16 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__7_ in let _v : (Parsetree.expression) = let _6 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 35036 "parsing/parser.ml" +# 35522 "parsing/parser.ml" in let _loc__7_ = (_startpos__7_, _endpos__7_) in let _loc__5_ = (_startpos__5_, _endpos__5_) in -# 2269 "parsing/parser.mly" +# 2274 "parsing/parser.mly" ( unclosed "[" _loc__5_ "]" _loc__7_ ) -# 35043 "parsing/parser.ml" +# 35529 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -35097,9 +35583,9 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _5 : unit = Obj.magic _5 in let _4 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 35103 "parsing/parser.ml" +# 35589 "parsing/parser.ml" ) = Obj.magic _4 in let _3 : (Longident.t) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in @@ -35108,17 +35594,17 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__7_ in let _v : (Parsetree.expression) = let _6 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 35114 "parsing/parser.ml" +# 35600 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2271 "parsing/parser.mly" +# 2276 "parsing/parser.mly" ( dotop_get ~loc:_sloc (ldot _3) paren _4 _1 _6 ) -# 35122 "parsing/parser.ml" +# 35608 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -35176,9 +35662,9 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _5 : unit = Obj.magic _5 in let _4 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 35182 "parsing/parser.ml" +# 35668 "parsing/parser.ml" ) = Obj.magic _4 in let _3 : (Longident.t) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in @@ -35187,16 +35673,16 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__7_ in let _v : (Parsetree.expression) = let _6 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 35193 "parsing/parser.ml" +# 35679 "parsing/parser.ml" in let _loc__7_ = (_startpos__7_, _endpos__7_) in let _loc__5_ = (_startpos__5_, _endpos__5_) in -# 2274 "parsing/parser.mly" +# 2279 "parsing/parser.mly" ( unclosed "(" _loc__5_ ")" _loc__7_ ) -# 35200 "parsing/parser.ml" +# 35686 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -35254,9 +35740,9 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _5 : unit = Obj.magic _5 in let _4 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 35260 "parsing/parser.ml" +# 35746 "parsing/parser.ml" ) = Obj.magic _4 in let _3 : (Longident.t) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in @@ -35265,17 +35751,17 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__7_ in let _v : (Parsetree.expression) = let _6 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 35271 "parsing/parser.ml" +# 35757 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2276 "parsing/parser.mly" +# 2281 "parsing/parser.mly" ( dotop_get ~loc:_sloc (ldot _3) brace _4 _1 _6 ) -# 35279 "parsing/parser.ml" +# 35765 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -35333,9 +35819,9 @@ module Tables = struct let es : (Parsetree.expression list) = Obj.magic es in let _5 : unit = Obj.magic _5 in let _4 : ( -# 628 "parsing/parser.mly" +# 629 "parsing/parser.mly" (string) -# 35339 "parsing/parser.ml" +# 35825 "parsing/parser.ml" ) = Obj.magic _4 in let _3 : (Longident.t) = Obj.magic _3 in let _2 : unit = Obj.magic _2 in @@ -35344,16 +35830,16 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__7_ in let _v : (Parsetree.expression) = let _6 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 35350 "parsing/parser.ml" +# 35836 "parsing/parser.ml" in let _loc__7_ = (_startpos__7_, _endpos__7_) in let _loc__5_ = (_startpos__5_, _endpos__5_) in -# 2279 "parsing/parser.mly" +# 2284 "parsing/parser.mly" ( unclosed "{" _loc__5_ "}" _loc__7_ ) -# 35357 "parsing/parser.ml" +# 35843 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -35407,9 +35893,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2281 "parsing/parser.mly" +# 2286 "parsing/parser.mly" ( bigarray_get ~loc:_sloc _1 _4 ) -# 35413 "parsing/parser.ml" +# 35899 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -35462,9 +35948,9 @@ module Tables = struct let _v : (Parsetree.expression) = let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2283 "parsing/parser.mly" +# 2288 "parsing/parser.mly" ( unclosed "{" _loc__3_ "}" _loc__5_ ) -# 35468 "parsing/parser.ml" +# 35954 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -35518,15 +36004,15 @@ module Tables = struct let attrs = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 35524 "parsing/parser.ml" +# 36010 "parsing/parser.ml" in -# 2292 "parsing/parser.mly" +# 2297 "parsing/parser.mly" ( e.pexp_desc, (ext, attrs @ e.pexp_attributes) ) -# 35530 "parsing/parser.ml" +# 36016 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -35534,10 +36020,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2285 "parsing/parser.mly" +# 2290 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 35541 "parsing/parser.ml" +# 36027 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -35586,24 +36072,24 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 35592 "parsing/parser.ml" +# 36078 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 35598 "parsing/parser.ml" +# 36084 "parsing/parser.ml" in let _endpos = _endpos__3_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2294 "parsing/parser.mly" +# 2299 "parsing/parser.mly" ( Pexp_construct (mkloc (Lident "()") (make_loc _sloc), None), _2 ) -# 35607 "parsing/parser.ml" +# 36093 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -35611,10 +36097,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2285 "parsing/parser.mly" +# 2290 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 35618 "parsing/parser.ml" +# 36104 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -35670,23 +36156,23 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 35676 "parsing/parser.ml" +# 36162 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 35682 "parsing/parser.ml" +# 36168 "parsing/parser.ml" in let _loc__4_ = (_startpos__4_, _endpos__4_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2296 "parsing/parser.mly" +# 2301 "parsing/parser.mly" ( unclosed "begin" _loc__1_ "end" _loc__4_ ) -# 35690 "parsing/parser.ml" +# 36176 "parsing/parser.ml" in let _endpos__1_ = _endpos__4_ in @@ -35694,10 +36180,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2285 "parsing/parser.mly" +# 2290 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 35701 "parsing/parser.ml" +# 36187 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -35747,9 +36233,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 35753 "parsing/parser.ml" +# 36239 "parsing/parser.ml" in let _2 = @@ -35757,21 +36243,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 35763 "parsing/parser.ml" +# 36249 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 35769 "parsing/parser.ml" +# 36255 "parsing/parser.ml" in -# 2298 "parsing/parser.mly" +# 2303 "parsing/parser.mly" ( Pexp_new(_3), _2 ) -# 35775 "parsing/parser.ml" +# 36261 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined3_ in @@ -35779,10 +36265,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2285 "parsing/parser.mly" +# 2290 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 35786 "parsing/parser.ml" +# 36272 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -35845,21 +36331,21 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 35851 "parsing/parser.ml" +# 36337 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 35857 "parsing/parser.ml" +# 36343 "parsing/parser.ml" in -# 2300 "parsing/parser.mly" +# 2305 "parsing/parser.mly" ( Pexp_pack _4, _3 ) -# 35863 "parsing/parser.ml" +# 36349 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -35867,10 +36353,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2285 "parsing/parser.mly" +# 2290 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 35874 "parsing/parser.ml" +# 36360 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -35948,11 +36434,11 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3330 "parsing/parser.mly" +# 3371 "parsing/parser.mly" ( let (lid, cstrs, attrs) = package_type_of_module_type _1 in let descr = Ptyp_package (lid, cstrs) in mktyp ~loc:_sloc ~attrs descr ) -# 35956 "parsing/parser.ml" +# 36442 "parsing/parser.ml" in let _3 = @@ -35960,24 +36446,24 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 35966 "parsing/parser.ml" +# 36452 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 35972 "parsing/parser.ml" +# 36458 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2302 "parsing/parser.mly" +# 2307 "parsing/parser.mly" ( Pexp_constraint (ghexp ~loc:_sloc (Pexp_pack _4), _6), _3 ) -# 35981 "parsing/parser.ml" +# 36467 "parsing/parser.ml" in let _endpos__1_ = _endpos__7_ in @@ -35985,10 +36471,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2285 "parsing/parser.mly" +# 2290 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 35992 "parsing/parser.ml" +# 36478 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36058,23 +36544,23 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 36064 "parsing/parser.ml" +# 36550 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 36070 "parsing/parser.ml" +# 36556 "parsing/parser.ml" in let _loc__6_ = (_startpos__6_, _endpos__6_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2304 "parsing/parser.mly" +# 2309 "parsing/parser.mly" ( unclosed "(" _loc__1_ ")" _loc__6_ ) -# 36078 "parsing/parser.ml" +# 36564 "parsing/parser.ml" in let _endpos__1_ = _endpos__6_ in @@ -36082,10 +36568,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2285 "parsing/parser.mly" +# 2290 "parsing/parser.mly" ( let desc, attrs = _1 in mkexp_attrs ~loc:_sloc desc attrs ) -# 36089 "parsing/parser.ml" +# 36575 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36114,30 +36600,30 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 36120 "parsing/parser.ml" +# 36606 "parsing/parser.ml" in -# 2308 "parsing/parser.mly" +# 2313 "parsing/parser.mly" ( Pexp_ident (_1) ) -# 36126 "parsing/parser.ml" +# 36612 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 36135 "parsing/parser.ml" +# 36621 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 36141 "parsing/parser.ml" +# 36627 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36161,23 +36647,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.expression) = let _1 = let _1 = -# 2310 "parsing/parser.mly" +# 2315 "parsing/parser.mly" ( Pexp_constant _1 ) -# 36167 "parsing/parser.ml" +# 36653 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 36175 "parsing/parser.ml" +# 36661 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 36181 "parsing/parser.ml" +# 36667 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36206,30 +36692,30 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 36212 "parsing/parser.ml" +# 36698 "parsing/parser.ml" in -# 2312 "parsing/parser.mly" +# 2317 "parsing/parser.mly" ( Pexp_construct(_1, None) ) -# 36218 "parsing/parser.ml" +# 36704 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 36227 "parsing/parser.ml" +# 36713 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 36233 "parsing/parser.ml" +# 36719 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36253,23 +36739,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.expression) = let _1 = let _1 = -# 2314 "parsing/parser.mly" +# 2319 "parsing/parser.mly" ( Pexp_variant(_1, None) ) -# 36259 "parsing/parser.ml" +# 36745 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 36267 "parsing/parser.ml" +# 36753 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 36273 "parsing/parser.ml" +# 36759 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36295,9 +36781,9 @@ module Tables = struct } = _menhir_stack in let _2 : (Parsetree.expression) = Obj.magic _2 in let _1 : ( -# 671 "parsing/parser.mly" +# 672 "parsing/parser.mly" (string) -# 36301 "parsing/parser.ml" +# 36787 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in @@ -36309,15 +36795,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 36315 "parsing/parser.ml" +# 36801 "parsing/parser.ml" in -# 2316 "parsing/parser.mly" +# 2321 "parsing/parser.mly" ( Pexp_apply(_1, [Nolabel,_2]) ) -# 36321 "parsing/parser.ml" +# 36807 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in @@ -36325,15 +36811,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 36331 "parsing/parser.ml" +# 36817 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 36337 "parsing/parser.ml" +# 36823 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36366,23 +36852,23 @@ module Tables = struct let _1 = let _1 = let _1 = -# 2317 "parsing/parser.mly" +# 2322 "parsing/parser.mly" ("!") -# 36372 "parsing/parser.ml" +# 36858 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 36380 "parsing/parser.ml" +# 36866 "parsing/parser.ml" in -# 2318 "parsing/parser.mly" +# 2323 "parsing/parser.mly" ( Pexp_apply(_1, [Nolabel,_2]) ) -# 36386 "parsing/parser.ml" +# 36872 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in @@ -36390,15 +36876,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 36396 "parsing/parser.ml" +# 36882 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 36402 "parsing/parser.ml" +# 36888 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36437,14 +36923,14 @@ module Tables = struct let _v : (Parsetree.expression) = let _1 = let _1 = let _2 = -# 2569 "parsing/parser.mly" +# 2574 "parsing/parser.mly" ( xs ) -# 36443 "parsing/parser.ml" +# 36929 "parsing/parser.ml" in -# 2320 "parsing/parser.mly" +# 2325 "parsing/parser.mly" ( Pexp_override _2 ) -# 36448 "parsing/parser.ml" +# 36934 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -36452,15 +36938,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 36458 "parsing/parser.ml" +# 36944 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 36464 "parsing/parser.ml" +# 36950 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36499,16 +36985,16 @@ module Tables = struct let _v : (Parsetree.expression) = let _1 = let _1 = let _2 = -# 2569 "parsing/parser.mly" +# 2574 "parsing/parser.mly" ( xs ) -# 36505 "parsing/parser.ml" +# 36991 "parsing/parser.ml" in let _loc__3_ = (_startpos__3_, _endpos__3_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2322 "parsing/parser.mly" +# 2327 "parsing/parser.mly" ( unclosed "{<" _loc__1_ ">}" _loc__3_ ) -# 36512 "parsing/parser.ml" +# 36998 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -36516,15 +37002,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 36522 "parsing/parser.ml" +# 37008 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 36528 "parsing/parser.ml" +# 37014 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36555,24 +37041,24 @@ module Tables = struct let _endpos = _endpos__2_ in let _v : (Parsetree.expression) = let _1 = let _1 = -# 2324 "parsing/parser.mly" +# 2329 "parsing/parser.mly" ( Pexp_override [] ) -# 36561 "parsing/parser.ml" +# 37047 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 36570 "parsing/parser.ml" +# 37056 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 36576 "parsing/parser.ml" +# 37062 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36616,15 +37102,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 36622 "parsing/parser.ml" +# 37108 "parsing/parser.ml" in -# 2326 "parsing/parser.mly" +# 2331 "parsing/parser.mly" ( Pexp_field(_1, _3) ) -# 36628 "parsing/parser.ml" +# 37114 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined1_ in @@ -36632,15 +37118,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 36638 "parsing/parser.ml" +# 37124 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 36644 "parsing/parser.ml" +# 37130 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36698,24 +37184,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 36704 "parsing/parser.ml" +# 37190 "parsing/parser.ml" in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1493 "parsing/parser.mly" +# 1496 "parsing/parser.mly" ( let loc = make_loc _loc__1_ in let me = Mod.ident ~loc _1 in Opn.mk ~loc me ) -# 36713 "parsing/parser.ml" +# 37199 "parsing/parser.ml" in -# 2328 "parsing/parser.mly" +# 2333 "parsing/parser.mly" ( Pexp_open(od, _4) ) -# 36719 "parsing/parser.ml" +# 37205 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -36723,15 +37209,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 36729 "parsing/parser.ml" +# 37215 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 36735 "parsing/parser.ml" +# 37221 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36784,9 +37270,9 @@ module Tables = struct let _v : (Parsetree.expression) = let _1 = let _1 = let _4 = -# 2569 "parsing/parser.mly" +# 2574 "parsing/parser.mly" ( xs ) -# 36790 "parsing/parser.ml" +# 37276 "parsing/parser.ml" in let od = let _1 = @@ -36794,18 +37280,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 36800 "parsing/parser.ml" +# 37286 "parsing/parser.ml" in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1493 "parsing/parser.mly" +# 1496 "parsing/parser.mly" ( let loc = make_loc _loc__1_ in let me = Mod.ident ~loc _1 in Opn.mk ~loc me ) -# 36809 "parsing/parser.ml" +# 37295 "parsing/parser.ml" in let _startpos_od_ = _startpos__1_ in @@ -36813,10 +37299,10 @@ module Tables = struct let _symbolstartpos = _startpos_od_ in let _sloc = (_symbolstartpos, _endpos) in -# 2330 "parsing/parser.mly" +# 2335 "parsing/parser.mly" ( (* TODO: review the location of Pexp_override *) Pexp_open(od, mkexp ~loc:_sloc (Pexp_override _4)) ) -# 36820 "parsing/parser.ml" +# 37306 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -36824,15 +37310,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 36830 "parsing/parser.ml" +# 37316 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 36836 "parsing/parser.ml" +# 37322 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36885,16 +37371,16 @@ module Tables = struct let _v : (Parsetree.expression) = let _1 = let _1 = let _4 = -# 2569 "parsing/parser.mly" +# 2574 "parsing/parser.mly" ( xs ) -# 36891 "parsing/parser.ml" +# 37377 "parsing/parser.ml" in let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2333 "parsing/parser.mly" +# 2338 "parsing/parser.mly" ( unclosed "{<" _loc__3_ ">}" _loc__5_ ) -# 36898 "parsing/parser.ml" +# 37384 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -36902,15 +37388,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 36908 "parsing/parser.ml" +# 37394 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 36914 "parsing/parser.ml" +# 37400 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -36941,9 +37427,9 @@ module Tables = struct }; } = _menhir_stack in let _1_inlined1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 36947 "parsing/parser.ml" +# 37433 "parsing/parser.ml" ) = Obj.magic _1_inlined1 in let _2 : unit = Obj.magic _2 in let _1 : (Parsetree.expression) = Obj.magic _1 in @@ -36955,23 +37441,23 @@ module Tables = struct let _3 = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 36961 "parsing/parser.ml" +# 37447 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 36969 "parsing/parser.ml" +# 37455 "parsing/parser.ml" in -# 2335 "parsing/parser.mly" +# 2340 "parsing/parser.mly" ( Pexp_send(_1, _3) ) -# 36975 "parsing/parser.ml" +# 37461 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined1_ in @@ -36979,15 +37465,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 36985 "parsing/parser.ml" +# 37471 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 36991 "parsing/parser.ml" +# 37477 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -37019,9 +37505,9 @@ module Tables = struct } = _menhir_stack in let _3 : (Parsetree.expression) = Obj.magic _3 in let _1_inlined1 : ( -# 682 "parsing/parser.mly" +# 683 "parsing/parser.mly" (string) -# 37025 "parsing/parser.ml" +# 37511 "parsing/parser.ml" ) = Obj.magic _1_inlined1 in let _1 : (Parsetree.expression) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in @@ -37035,15 +37521,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 840 "parsing/parser.mly" +# 841 "parsing/parser.mly" ( mkoperator ~loc:_sloc _1 ) -# 37041 "parsing/parser.ml" +# 37527 "parsing/parser.ml" in -# 2337 "parsing/parser.mly" +# 2342 "parsing/parser.mly" ( mkinfix _1 _2 _3 ) -# 37047 "parsing/parser.ml" +# 37533 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -37051,15 +37537,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 37057 "parsing/parser.ml" +# 37543 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 37063 "parsing/parser.ml" +# 37549 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -37083,23 +37569,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.expression) = let _1 = let _1 = -# 2339 "parsing/parser.mly" +# 2344 "parsing/parser.mly" ( Pexp_extension _1 ) -# 37089 "parsing/parser.ml" +# 37575 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 37097 "parsing/parser.ml" +# 37583 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 37103 "parsing/parser.ml" +# 37589 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -37147,18 +37633,18 @@ module Tables = struct let _3 = let (_endpos__2_, _startpos__1_, _2, _1) = (_endpos__2_inlined1_, _startpos__1_inlined1_, _2_inlined1, _1_inlined1) in let _1 = -# 2340 "parsing/parser.mly" +# 2345 "parsing/parser.mly" (Lident "()") -# 37153 "parsing/parser.ml" +# 37639 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 37162 "parsing/parser.ml" +# 37648 "parsing/parser.ml" in let _endpos__3_ = _endpos__2_inlined1_ in @@ -37168,18 +37654,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 37174 "parsing/parser.ml" +# 37660 "parsing/parser.ml" in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1493 "parsing/parser.mly" +# 1496 "parsing/parser.mly" ( let loc = make_loc _loc__1_ in let me = Mod.ident ~loc _1 in Opn.mk ~loc me ) -# 37183 "parsing/parser.ml" +# 37669 "parsing/parser.ml" in let _startpos_od_ = _startpos__1_ in @@ -37187,10 +37673,10 @@ module Tables = struct let _symbolstartpos = _startpos_od_ in let _sloc = (_symbolstartpos, _endpos) in -# 2341 "parsing/parser.mly" +# 2346 "parsing/parser.mly" ( (* TODO: review the location of Pexp_construct *) Pexp_open(od, mkexp ~loc:_sloc (Pexp_construct(_3, None))) ) -# 37194 "parsing/parser.ml" +# 37680 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_inlined1_ in @@ -37198,15 +37684,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 37204 "parsing/parser.ml" +# 37690 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 37210 "parsing/parser.ml" +# 37696 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -37261,9 +37747,9 @@ module Tables = struct let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2344 "parsing/parser.mly" +# 2349 "parsing/parser.mly" ( unclosed "(" _loc__3_ ")" _loc__5_ ) -# 37267 "parsing/parser.ml" +# 37753 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -37271,15 +37757,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 37277 "parsing/parser.ml" +# 37763 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 37283 "parsing/parser.ml" +# 37769 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -37318,25 +37804,25 @@ module Tables = struct let _endpos = _endpos__3_ in let _v : (Parsetree.expression) = let _1 = let _1 = -# 2346 "parsing/parser.mly" +# 2351 "parsing/parser.mly" ( let (exten, fields) = _2 in Pexp_record(fields, exten) ) -# 37325 "parsing/parser.ml" +# 37811 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 37334 "parsing/parser.ml" +# 37820 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 37340 "parsing/parser.ml" +# 37826 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -37378,9 +37864,9 @@ module Tables = struct let _loc__3_ = (_startpos__3_, _endpos__3_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2349 "parsing/parser.mly" +# 2354 "parsing/parser.mly" ( unclosed "{" _loc__1_ "}" _loc__3_ ) -# 37384 "parsing/parser.ml" +# 37870 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -37388,15 +37874,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 37394 "parsing/parser.ml" +# 37880 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 37400 "parsing/parser.ml" +# 37886 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -37455,18 +37941,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 37461 "parsing/parser.ml" +# 37947 "parsing/parser.ml" in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1493 "parsing/parser.mly" +# 1496 "parsing/parser.mly" ( let loc = make_loc _loc__1_ in let me = Mod.ident ~loc _1 in Opn.mk ~loc me ) -# 37470 "parsing/parser.ml" +# 37956 "parsing/parser.ml" in let _startpos_od_ = _startpos__1_ in @@ -37474,11 +37960,11 @@ module Tables = struct let _symbolstartpos = _startpos_od_ in let _sloc = (_symbolstartpos, _endpos) in -# 2351 "parsing/parser.mly" +# 2356 "parsing/parser.mly" ( let (exten, fields) = _4 in (* TODO: review the location of Pexp_construct *) Pexp_open(od, mkexp ~loc:_sloc (Pexp_record(fields, exten))) ) -# 37482 "parsing/parser.ml" +# 37968 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -37486,15 +37972,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 37492 "parsing/parser.ml" +# 37978 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 37498 "parsing/parser.ml" +# 37984 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -37550,9 +38036,9 @@ module Tables = struct let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2355 "parsing/parser.mly" +# 2360 "parsing/parser.mly" ( unclosed "{" _loc__3_ "}" _loc__5_ ) -# 37556 "parsing/parser.ml" +# 38042 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -37560,15 +38046,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 37566 "parsing/parser.ml" +# 38052 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 37572 "parsing/parser.ml" +# 38058 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -37607,14 +38093,14 @@ module Tables = struct let _v : (Parsetree.expression) = let _1 = let _1 = let _2 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 37613 "parsing/parser.ml" +# 38099 "parsing/parser.ml" in -# 2357 "parsing/parser.mly" +# 2362 "parsing/parser.mly" ( Pexp_array(_2) ) -# 37618 "parsing/parser.ml" +# 38104 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -37622,15 +38108,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 37628 "parsing/parser.ml" +# 38114 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 37634 "parsing/parser.ml" +# 38120 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -37669,16 +38155,16 @@ module Tables = struct let _v : (Parsetree.expression) = let _1 = let _1 = let _2 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 37675 "parsing/parser.ml" +# 38161 "parsing/parser.ml" in let _loc__3_ = (_startpos__3_, _endpos__3_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2359 "parsing/parser.mly" +# 2364 "parsing/parser.mly" ( unclosed "[|" _loc__1_ "|]" _loc__3_ ) -# 37682 "parsing/parser.ml" +# 38168 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -37686,15 +38172,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 37692 "parsing/parser.ml" +# 38178 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 37698 "parsing/parser.ml" +# 38184 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -37725,24 +38211,24 @@ module Tables = struct let _endpos = _endpos__2_ in let _v : (Parsetree.expression) = let _1 = let _1 = -# 2361 "parsing/parser.mly" +# 2366 "parsing/parser.mly" ( Pexp_array [] ) -# 37731 "parsing/parser.ml" +# 38217 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 37740 "parsing/parser.ml" +# 38226 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 37746 "parsing/parser.ml" +# 38232 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -37795,9 +38281,9 @@ module Tables = struct let _v : (Parsetree.expression) = let _1 = let _1 = let _4 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 37801 "parsing/parser.ml" +# 38287 "parsing/parser.ml" in let od = let _1 = @@ -37805,18 +38291,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 37811 "parsing/parser.ml" +# 38297 "parsing/parser.ml" in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1493 "parsing/parser.mly" +# 1496 "parsing/parser.mly" ( let loc = make_loc _loc__1_ in let me = Mod.ident ~loc _1 in Opn.mk ~loc me ) -# 37820 "parsing/parser.ml" +# 38306 "parsing/parser.ml" in let _startpos_od_ = _startpos__1_ in @@ -37824,10 +38310,10 @@ module Tables = struct let _symbolstartpos = _startpos_od_ in let _sloc = (_symbolstartpos, _endpos) in -# 2363 "parsing/parser.mly" +# 2368 "parsing/parser.mly" ( (* TODO: review the location of Pexp_array *) Pexp_open(od, mkexp ~loc:_sloc (Pexp_array(_4))) ) -# 37831 "parsing/parser.ml" +# 38317 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -37835,15 +38321,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 37841 "parsing/parser.ml" +# 38327 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 37847 "parsing/parser.ml" +# 38333 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -37894,18 +38380,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 37900 "parsing/parser.ml" +# 38386 "parsing/parser.ml" in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1493 "parsing/parser.mly" +# 1496 "parsing/parser.mly" ( let loc = make_loc _loc__1_ in let me = Mod.ident ~loc _1 in Opn.mk ~loc me ) -# 37909 "parsing/parser.ml" +# 38395 "parsing/parser.ml" in let _startpos_od_ = _startpos__1_ in @@ -37913,10 +38399,10 @@ module Tables = struct let _symbolstartpos = _startpos_od_ in let _sloc = (_symbolstartpos, _endpos) in -# 2366 "parsing/parser.mly" +# 2371 "parsing/parser.mly" ( (* TODO: review the location of Pexp_array *) Pexp_open(od, mkexp ~loc:_sloc (Pexp_array [])) ) -# 37920 "parsing/parser.ml" +# 38406 "parsing/parser.ml" in let _endpos__1_ = _endpos__4_ in @@ -37924,15 +38410,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 37930 "parsing/parser.ml" +# 38416 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 37936 "parsing/parser.ml" +# 38422 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -37985,16 +38471,16 @@ module Tables = struct let _v : (Parsetree.expression) = let _1 = let _1 = let _4 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 37991 "parsing/parser.ml" +# 38477 "parsing/parser.ml" in let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2370 "parsing/parser.mly" +# 2375 "parsing/parser.mly" ( unclosed "[|" _loc__3_ "|]" _loc__5_ ) -# 37998 "parsing/parser.ml" +# 38484 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -38002,15 +38488,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 38008 "parsing/parser.ml" +# 38494 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 38014 "parsing/parser.ml" +# 38500 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -38049,15 +38535,15 @@ module Tables = struct let _v : (Parsetree.expression) = let _1 = let _1 = let _2 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 38055 "parsing/parser.ml" +# 38541 "parsing/parser.ml" in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2372 "parsing/parser.mly" +# 2377 "parsing/parser.mly" ( fst (mktailexp _loc__3_ _2) ) -# 38061 "parsing/parser.ml" +# 38547 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -38065,15 +38551,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 38071 "parsing/parser.ml" +# 38557 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 38077 "parsing/parser.ml" +# 38563 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -38112,16 +38598,16 @@ module Tables = struct let _v : (Parsetree.expression) = let _1 = let _1 = let _2 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 38118 "parsing/parser.ml" +# 38604 "parsing/parser.ml" in let _loc__3_ = (_startpos__3_, _endpos__3_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2374 "parsing/parser.mly" +# 2379 "parsing/parser.mly" ( unclosed "[" _loc__1_ "]" _loc__3_ ) -# 38125 "parsing/parser.ml" +# 38611 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -38129,15 +38615,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 38135 "parsing/parser.ml" +# 38621 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 38141 "parsing/parser.ml" +# 38627 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -38190,9 +38676,9 @@ module Tables = struct let _v : (Parsetree.expression) = let _1 = let _1 = let _4 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 38196 "parsing/parser.ml" +# 38682 "parsing/parser.ml" in let od = let _1 = @@ -38200,18 +38686,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 38206 "parsing/parser.ml" +# 38692 "parsing/parser.ml" in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1493 "parsing/parser.mly" +# 1496 "parsing/parser.mly" ( let loc = make_loc _loc__1_ in let me = Mod.ident ~loc _1 in Opn.mk ~loc me ) -# 38215 "parsing/parser.ml" +# 38701 "parsing/parser.ml" in let _startpos_od_ = _startpos__1_ in @@ -38220,13 +38706,13 @@ module Tables = struct let _loc__5_ = (_startpos__5_, _endpos__5_) in let _sloc = (_symbolstartpos, _endpos) in -# 2376 "parsing/parser.mly" +# 2381 "parsing/parser.mly" ( let list_exp = (* TODO: review the location of list_exp *) let tail_exp, _tail_loc = mktailexp _loc__5_ _4 in mkexp ~loc:_sloc tail_exp in Pexp_open(od, list_exp) ) -# 38230 "parsing/parser.ml" +# 38716 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -38234,15 +38720,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 38240 "parsing/parser.ml" +# 38726 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 38246 "parsing/parser.ml" +# 38732 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -38290,18 +38776,18 @@ module Tables = struct let _3 = let (_endpos__2_, _startpos__1_, _2, _1) = (_endpos__2_inlined1_, _startpos__1_inlined1_, _2_inlined1, _1_inlined1) in let _1 = -# 2381 "parsing/parser.mly" +# 2386 "parsing/parser.mly" (Lident "[]") -# 38296 "parsing/parser.ml" +# 38782 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 38305 "parsing/parser.ml" +# 38791 "parsing/parser.ml" in let _endpos__3_ = _endpos__2_inlined1_ in @@ -38311,18 +38797,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 38317 "parsing/parser.ml" +# 38803 "parsing/parser.ml" in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1493 "parsing/parser.mly" +# 1496 "parsing/parser.mly" ( let loc = make_loc _loc__1_ in let me = Mod.ident ~loc _1 in Opn.mk ~loc me ) -# 38326 "parsing/parser.ml" +# 38812 "parsing/parser.ml" in let _startpos_od_ = _startpos__1_ in @@ -38330,10 +38816,10 @@ module Tables = struct let _symbolstartpos = _startpos_od_ in let _sloc = (_symbolstartpos, _endpos) in -# 2382 "parsing/parser.mly" +# 2387 "parsing/parser.mly" ( (* TODO: review the location of Pexp_construct *) Pexp_open(od, mkexp ~loc:_sloc (Pexp_construct(_3, None))) ) -# 38337 "parsing/parser.ml" +# 38823 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_inlined1_ in @@ -38341,15 +38827,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 38347 "parsing/parser.ml" +# 38833 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 38353 "parsing/parser.ml" +# 38839 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -38402,16 +38888,16 @@ module Tables = struct let _v : (Parsetree.expression) = let _1 = let _1 = let _4 = -# 2586 "parsing/parser.mly" +# 2591 "parsing/parser.mly" ( es ) -# 38408 "parsing/parser.ml" +# 38894 "parsing/parser.ml" in let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2386 "parsing/parser.mly" +# 2391 "parsing/parser.mly" ( unclosed "[" _loc__3_ "]" _loc__5_ ) -# 38415 "parsing/parser.ml" +# 38901 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -38419,15 +38905,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 38425 "parsing/parser.ml" +# 38911 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 38431 "parsing/parser.ml" +# 38917 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -38520,11 +39006,11 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3330 "parsing/parser.mly" +# 3371 "parsing/parser.mly" ( let (lid, cstrs, attrs) = package_type_of_module_type _1 in let descr = Ptyp_package (lid, cstrs) in mktyp ~loc:_sloc ~attrs descr ) -# 38528 "parsing/parser.ml" +# 39014 "parsing/parser.ml" in let _5 = @@ -38532,15 +39018,15 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 38538 "parsing/parser.ml" +# 39024 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 38544 "parsing/parser.ml" +# 39030 "parsing/parser.ml" in let od = @@ -38549,18 +39035,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 38555 "parsing/parser.ml" +# 39041 "parsing/parser.ml" in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 1493 "parsing/parser.mly" +# 1496 "parsing/parser.mly" ( let loc = make_loc _loc__1_ in let me = Mod.ident ~loc _1 in Opn.mk ~loc me ) -# 38564 "parsing/parser.ml" +# 39050 "parsing/parser.ml" in let _startpos_od_ = _startpos__1_ in @@ -38568,13 +39054,13 @@ module Tables = struct let _symbolstartpos = _startpos_od_ in let _sloc = (_symbolstartpos, _endpos) in -# 2389 "parsing/parser.mly" +# 2394 "parsing/parser.mly" ( (* TODO: review the location of Pexp_constraint *) let modexp = mkexp_attrs ~loc:_sloc (Pexp_constraint (ghexp ~loc:_sloc (Pexp_pack _6), _8)) _5 in Pexp_open(od, modexp) ) -# 38578 "parsing/parser.ml" +# 39064 "parsing/parser.ml" in let _endpos__1_ = _endpos__9_ in @@ -38582,15 +39068,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 38588 "parsing/parser.ml" +# 39074 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 38594 "parsing/parser.ml" +# 39080 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -38675,23 +39161,23 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 38681 "parsing/parser.ml" +# 39167 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 38687 "parsing/parser.ml" +# 39173 "parsing/parser.ml" in let _loc__8_ = (_startpos__8_, _endpos__8_) in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2396 "parsing/parser.mly" +# 2401 "parsing/parser.mly" ( unclosed "(" _loc__3_ ")" _loc__8_ ) -# 38695 "parsing/parser.ml" +# 39181 "parsing/parser.ml" in let _endpos__1_ = _endpos__8_ in @@ -38699,15 +39185,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 846 "parsing/parser.mly" +# 847 "parsing/parser.mly" ( mkexp ~loc:_sloc _1 ) -# 38705 "parsing/parser.ml" +# 39191 "parsing/parser.ml" in -# 2288 "parsing/parser.mly" +# 2293 "parsing/parser.mly" ( _1 ) -# 38711 "parsing/parser.ml" +# 39197 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -38736,30 +39222,30 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 38742 "parsing/parser.ml" +# 39228 "parsing/parser.ml" in -# 2666 "parsing/parser.mly" +# 2673 "parsing/parser.mly" ( Ppat_var (_1) ) -# 38748 "parsing/parser.ml" +# 39234 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 38757 "parsing/parser.ml" +# 39243 "parsing/parser.ml" in -# 2667 "parsing/parser.mly" +# 2674 "parsing/parser.mly" ( _1 ) -# 38763 "parsing/parser.ml" +# 39249 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -38782,9 +39268,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.pattern) = -# 2668 "parsing/parser.mly" +# 2675 "parsing/parser.mly" ( _1 ) -# 38788 "parsing/parser.ml" +# 39274 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -38824,9 +39310,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2673 "parsing/parser.mly" +# 2680 "parsing/parser.mly" ( reloc_pat ~loc:_sloc _2 ) -# 38830 "parsing/parser.ml" +# 39316 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -38849,9 +39335,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.pattern) = -# 2675 "parsing/parser.mly" +# 2682 "parsing/parser.mly" ( _1 ) -# 38855 "parsing/parser.ml" +# 39341 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -38914,9 +39400,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 38920 "parsing/parser.ml" +# 39406 "parsing/parser.ml" in let _3 = @@ -38924,24 +39410,24 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 38930 "parsing/parser.ml" +# 39416 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 38936 "parsing/parser.ml" +# 39422 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2677 "parsing/parser.mly" +# 2684 "parsing/parser.mly" ( mkpat_attrs ~loc:_sloc (Ppat_unpack _4) _3 ) -# 38945 "parsing/parser.ml" +# 39431 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39018,11 +39504,11 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3330 "parsing/parser.mly" +# 3371 "parsing/parser.mly" ( let (lid, cstrs, attrs) = package_type_of_module_type _1 in let descr = Ptyp_package (lid, cstrs) in mktyp ~loc:_sloc ~attrs descr ) -# 39026 "parsing/parser.ml" +# 39512 "parsing/parser.ml" in let _4 = @@ -39031,9 +39517,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 39037 "parsing/parser.ml" +# 39523 "parsing/parser.ml" in let _3 = @@ -39041,26 +39527,26 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 39047 "parsing/parser.ml" +# 39533 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 39053 "parsing/parser.ml" +# 39539 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2679 "parsing/parser.mly" +# 2686 "parsing/parser.mly" ( mkpat_attrs ~loc:_sloc (Ppat_constraint(mkpat ~loc:_sloc (Ppat_unpack _4), _6)) _3 ) -# 39064 "parsing/parser.ml" +# 39550 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39084,23 +39570,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.pattern) = let _1 = let _1 = -# 2687 "parsing/parser.mly" +# 2694 "parsing/parser.mly" ( Ppat_any ) -# 39090 "parsing/parser.ml" +# 39576 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 39098 "parsing/parser.ml" +# 39584 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 39104 "parsing/parser.ml" +# 39590 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39124,23 +39610,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.pattern) = let _1 = let _1 = -# 2689 "parsing/parser.mly" +# 2696 "parsing/parser.mly" ( Ppat_constant _1 ) -# 39130 "parsing/parser.ml" +# 39616 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 39138 "parsing/parser.ml" +# 39624 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 39144 "parsing/parser.ml" +# 39630 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39178,24 +39664,24 @@ module Tables = struct let _endpos = _endpos__3_ in let _v : (Parsetree.pattern) = let _1 = let _1 = -# 2691 "parsing/parser.mly" +# 2698 "parsing/parser.mly" ( Ppat_interval (_1, _3) ) -# 39184 "parsing/parser.ml" +# 39670 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 39193 "parsing/parser.ml" +# 39679 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 39199 "parsing/parser.ml" +# 39685 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39224,30 +39710,30 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 39230 "parsing/parser.ml" +# 39716 "parsing/parser.ml" in -# 2693 "parsing/parser.mly" +# 2700 "parsing/parser.mly" ( Ppat_construct(_1, None) ) -# 39236 "parsing/parser.ml" +# 39722 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 39245 "parsing/parser.ml" +# 39731 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 39251 "parsing/parser.ml" +# 39737 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39271,23 +39757,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.pattern) = let _1 = let _1 = -# 2695 "parsing/parser.mly" +# 2702 "parsing/parser.mly" ( Ppat_variant(_1, None) ) -# 39277 "parsing/parser.ml" +# 39763 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 39285 "parsing/parser.ml" +# 39771 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 39291 "parsing/parser.ml" +# 39777 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39324,15 +39810,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 39330 "parsing/parser.ml" +# 39816 "parsing/parser.ml" in -# 2697 "parsing/parser.mly" +# 2704 "parsing/parser.mly" ( Ppat_type (_2) ) -# 39336 "parsing/parser.ml" +# 39822 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined1_ in @@ -39340,15 +39826,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 39346 "parsing/parser.ml" +# 39832 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 39352 "parsing/parser.ml" +# 39838 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39391,15 +39877,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 39397 "parsing/parser.ml" +# 39883 "parsing/parser.ml" in -# 2699 "parsing/parser.mly" +# 2706 "parsing/parser.mly" ( Ppat_open(_1, _3) ) -# 39403 "parsing/parser.ml" +# 39889 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -39407,15 +39893,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 39413 "parsing/parser.ml" +# 39899 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 39419 "parsing/parser.ml" +# 39905 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39463,18 +39949,18 @@ module Tables = struct let _3 = let (_endpos__2_, _startpos__1_, _2, _1) = (_endpos__2_inlined1_, _startpos__1_inlined1_, _2_inlined1, _1_inlined1) in let _1 = -# 2700 "parsing/parser.mly" +# 2707 "parsing/parser.mly" (Lident "[]") -# 39469 "parsing/parser.ml" +# 39955 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 39478 "parsing/parser.ml" +# 39964 "parsing/parser.ml" in let _endpos__3_ = _endpos__2_inlined1_ in @@ -39483,18 +39969,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 39489 "parsing/parser.ml" +# 39975 "parsing/parser.ml" in let _endpos = _endpos__3_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2701 "parsing/parser.mly" +# 2708 "parsing/parser.mly" ( Ppat_open(_1, mkpat ~loc:_sloc (Ppat_construct(_3, None))) ) -# 39498 "parsing/parser.ml" +# 39984 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_inlined1_ in @@ -39502,15 +39988,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 39508 "parsing/parser.ml" +# 39994 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 39514 "parsing/parser.ml" +# 40000 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39558,18 +40044,18 @@ module Tables = struct let _3 = let (_endpos__2_, _startpos__1_, _2, _1) = (_endpos__2_inlined1_, _startpos__1_inlined1_, _2_inlined1, _1_inlined1) in let _1 = -# 2702 "parsing/parser.mly" +# 2709 "parsing/parser.mly" (Lident "()") -# 39564 "parsing/parser.ml" +# 40050 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 39573 "parsing/parser.ml" +# 40059 "parsing/parser.ml" in let _endpos__3_ = _endpos__2_inlined1_ in @@ -39578,18 +40064,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 39584 "parsing/parser.ml" +# 40070 "parsing/parser.ml" in let _endpos = _endpos__3_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2703 "parsing/parser.mly" +# 2710 "parsing/parser.mly" ( Ppat_open(_1, mkpat ~loc:_sloc (Ppat_construct(_3, None))) ) -# 39593 "parsing/parser.ml" +# 40079 "parsing/parser.ml" in let _endpos__1_ = _endpos__2_inlined1_ in @@ -39597,15 +40083,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 39603 "parsing/parser.ml" +# 40089 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 39609 "parsing/parser.ml" +# 40095 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39662,15 +40148,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 39668 "parsing/parser.ml" +# 40154 "parsing/parser.ml" in -# 2705 "parsing/parser.mly" +# 2712 "parsing/parser.mly" ( Ppat_open (_1, _4) ) -# 39674 "parsing/parser.ml" +# 40160 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -39678,15 +40164,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 39684 "parsing/parser.ml" +# 40170 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 39690 "parsing/parser.ml" +# 40176 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39741,9 +40227,9 @@ module Tables = struct let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 2707 "parsing/parser.mly" +# 2714 "parsing/parser.mly" ( unclosed "(" _loc__3_ ")" _loc__5_ ) -# 39747 "parsing/parser.ml" +# 40233 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -39751,15 +40237,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 39757 "parsing/parser.ml" +# 40243 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 39763 "parsing/parser.ml" +# 40249 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39806,9 +40292,9 @@ module Tables = struct let _1 = let _loc__4_ = (_startpos__4_, _endpos__4_) in -# 2709 "parsing/parser.mly" +# 2716 "parsing/parser.mly" ( expecting _loc__4_ "pattern" ) -# 39812 "parsing/parser.ml" +# 40298 "parsing/parser.ml" in let _endpos__1_ = _endpos__4_ in @@ -39816,15 +40302,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 39822 "parsing/parser.ml" +# 40308 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 39828 "parsing/parser.ml" +# 40314 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39865,9 +40351,9 @@ module Tables = struct let _loc__3_ = (_startpos__3_, _endpos__3_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2711 "parsing/parser.mly" +# 2718 "parsing/parser.mly" ( unclosed "(" _loc__1_ ")" _loc__3_ ) -# 39871 "parsing/parser.ml" +# 40357 "parsing/parser.ml" in let _endpos__1_ = _endpos__3_ in @@ -39875,15 +40361,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 39881 "parsing/parser.ml" +# 40367 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 39887 "parsing/parser.ml" +# 40373 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -39935,24 +40421,24 @@ module Tables = struct let _endpos = _endpos__5_ in let _v : (Parsetree.pattern) = let _1 = let _1 = -# 2713 "parsing/parser.mly" +# 2720 "parsing/parser.mly" ( Ppat_constraint(_2, _4) ) -# 39941 "parsing/parser.ml" +# 40427 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 39950 "parsing/parser.ml" +# 40436 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 39956 "parsing/parser.ml" +# 40442 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40007,9 +40493,9 @@ module Tables = struct let _loc__5_ = (_startpos__5_, _endpos__5_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2715 "parsing/parser.mly" +# 2722 "parsing/parser.mly" ( unclosed "(" _loc__1_ ")" _loc__5_ ) -# 40013 "parsing/parser.ml" +# 40499 "parsing/parser.ml" in let _endpos__1_ = _endpos__5_ in @@ -40017,15 +40503,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 40023 "parsing/parser.ml" +# 40509 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 40029 "parsing/parser.ml" +# 40515 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40072,9 +40558,9 @@ module Tables = struct let _1 = let _loc__4_ = (_startpos__4_, _endpos__4_) in -# 2717 "parsing/parser.mly" +# 2724 "parsing/parser.mly" ( expecting _loc__4_ "type" ) -# 40078 "parsing/parser.ml" +# 40564 "parsing/parser.ml" in let _endpos__1_ = _endpos__4_ in @@ -40082,15 +40568,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 40088 "parsing/parser.ml" +# 40574 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 40094 "parsing/parser.ml" +# 40580 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40169,11 +40655,11 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3330 "parsing/parser.mly" +# 3371 "parsing/parser.mly" ( let (lid, cstrs, attrs) = package_type_of_module_type _1 in let descr = Ptyp_package (lid, cstrs) in mktyp ~loc:_sloc ~attrs descr ) -# 40177 "parsing/parser.ml" +# 40663 "parsing/parser.ml" in let _3 = @@ -40181,23 +40667,23 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 40187 "parsing/parser.ml" +# 40673 "parsing/parser.ml" in -# 3753 "parsing/parser.mly" +# 3794 "parsing/parser.mly" ( _1, _2 ) -# 40193 "parsing/parser.ml" +# 40679 "parsing/parser.ml" in let _loc__7_ = (_startpos__7_, _endpos__7_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2720 "parsing/parser.mly" +# 2727 "parsing/parser.mly" ( unclosed "(" _loc__1_ ")" _loc__7_ ) -# 40201 "parsing/parser.ml" +# 40687 "parsing/parser.ml" in let _endpos__1_ = _endpos__7_ in @@ -40205,15 +40691,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 40211 "parsing/parser.ml" +# 40697 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 40217 "parsing/parser.ml" +# 40703 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40237,23 +40723,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.pattern) = let _1 = let _1 = -# 2722 "parsing/parser.mly" +# 2729 "parsing/parser.mly" ( Ppat_extension _1 ) -# 40243 "parsing/parser.ml" +# 40729 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 848 "parsing/parser.mly" +# 849 "parsing/parser.mly" ( mkpat ~loc:_sloc _1 ) -# 40251 "parsing/parser.ml" +# 40737 "parsing/parser.ml" in -# 2683 "parsing/parser.mly" +# 2690 "parsing/parser.mly" ( _1 ) -# 40257 "parsing/parser.ml" +# 40743 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40272,17 +40758,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 40278 "parsing/parser.ml" +# 40764 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3663 "parsing/parser.mly" +# 3704 "parsing/parser.mly" ( _1 ) -# 40286 "parsing/parser.ml" +# 40772 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40301,17 +40787,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 697 "parsing/parser.mly" +# 698 "parsing/parser.mly" (string) -# 40307 "parsing/parser.ml" +# 40793 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3664 "parsing/parser.mly" +# 3705 "parsing/parser.mly" ( _1 ) -# 40315 "parsing/parser.ml" +# 40801 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40334,9 +40820,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3665 "parsing/parser.mly" +# 3706 "parsing/parser.mly" ( "and" ) -# 40340 "parsing/parser.ml" +# 40826 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40359,9 +40845,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3666 "parsing/parser.mly" +# 3707 "parsing/parser.mly" ( "as" ) -# 40365 "parsing/parser.ml" +# 40851 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40384,9 +40870,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3667 "parsing/parser.mly" +# 3708 "parsing/parser.mly" ( "assert" ) -# 40390 "parsing/parser.ml" +# 40876 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40409,9 +40895,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3668 "parsing/parser.mly" +# 3709 "parsing/parser.mly" ( "begin" ) -# 40415 "parsing/parser.ml" +# 40901 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40434,9 +40920,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3669 "parsing/parser.mly" +# 3710 "parsing/parser.mly" ( "class" ) -# 40440 "parsing/parser.ml" +# 40926 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40459,9 +40945,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3670 "parsing/parser.mly" +# 3711 "parsing/parser.mly" ( "constraint" ) -# 40465 "parsing/parser.ml" +# 40951 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40484,9 +40970,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3671 "parsing/parser.mly" +# 3712 "parsing/parser.mly" ( "do" ) -# 40490 "parsing/parser.ml" +# 40976 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40509,9 +40995,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3672 "parsing/parser.mly" +# 3713 "parsing/parser.mly" ( "done" ) -# 40515 "parsing/parser.ml" +# 41001 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40534,9 +41020,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3673 "parsing/parser.mly" +# 3714 "parsing/parser.mly" ( "downto" ) -# 40540 "parsing/parser.ml" +# 41026 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40559,9 +41045,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3674 "parsing/parser.mly" +# 3715 "parsing/parser.mly" ( "else" ) -# 40565 "parsing/parser.ml" +# 41051 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40584,9 +41070,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3675 "parsing/parser.mly" +# 3716 "parsing/parser.mly" ( "end" ) -# 40590 "parsing/parser.ml" +# 41076 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40609,9 +41095,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3676 "parsing/parser.mly" +# 3717 "parsing/parser.mly" ( "exception" ) -# 40615 "parsing/parser.ml" +# 41101 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40634,9 +41120,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3677 "parsing/parser.mly" +# 3718 "parsing/parser.mly" ( "external" ) -# 40640 "parsing/parser.ml" +# 41126 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40659,9 +41145,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3678 "parsing/parser.mly" +# 3719 "parsing/parser.mly" ( "false" ) -# 40665 "parsing/parser.ml" +# 41151 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40684,9 +41170,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3679 "parsing/parser.mly" +# 3720 "parsing/parser.mly" ( "for" ) -# 40690 "parsing/parser.ml" +# 41176 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40709,9 +41195,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3680 "parsing/parser.mly" +# 3721 "parsing/parser.mly" ( "fun" ) -# 40715 "parsing/parser.ml" +# 41201 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40734,9 +41220,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3681 "parsing/parser.mly" +# 3722 "parsing/parser.mly" ( "function" ) -# 40740 "parsing/parser.ml" +# 41226 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40759,9 +41245,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3682 "parsing/parser.mly" +# 3723 "parsing/parser.mly" ( "functor" ) -# 40765 "parsing/parser.ml" +# 41251 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40784,9 +41270,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3683 "parsing/parser.mly" +# 3724 "parsing/parser.mly" ( "if" ) -# 40790 "parsing/parser.ml" +# 41276 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40809,9 +41295,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3684 "parsing/parser.mly" +# 3725 "parsing/parser.mly" ( "in" ) -# 40815 "parsing/parser.ml" +# 41301 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40834,9 +41320,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3685 "parsing/parser.mly" +# 3726 "parsing/parser.mly" ( "include" ) -# 40840 "parsing/parser.ml" +# 41326 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40859,9 +41345,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3686 "parsing/parser.mly" +# 3727 "parsing/parser.mly" ( "inherit" ) -# 40865 "parsing/parser.ml" +# 41351 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40884,9 +41370,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3687 "parsing/parser.mly" +# 3728 "parsing/parser.mly" ( "initializer" ) -# 40890 "parsing/parser.ml" +# 41376 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40909,9 +41395,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3688 "parsing/parser.mly" +# 3729 "parsing/parser.mly" ( "lazy" ) -# 40915 "parsing/parser.ml" +# 41401 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40934,9 +41420,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3689 "parsing/parser.mly" +# 3730 "parsing/parser.mly" ( "let" ) -# 40940 "parsing/parser.ml" +# 41426 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40959,9 +41445,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3690 "parsing/parser.mly" +# 3731 "parsing/parser.mly" ( "match" ) -# 40965 "parsing/parser.ml" +# 41451 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -40984,9 +41470,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3691 "parsing/parser.mly" +# 3732 "parsing/parser.mly" ( "method" ) -# 40990 "parsing/parser.ml" +# 41476 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41009,9 +41495,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3692 "parsing/parser.mly" +# 3733 "parsing/parser.mly" ( "module" ) -# 41015 "parsing/parser.ml" +# 41501 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41034,9 +41520,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3693 "parsing/parser.mly" +# 3734 "parsing/parser.mly" ( "mutable" ) -# 41040 "parsing/parser.ml" +# 41526 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41059,9 +41545,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3694 "parsing/parser.mly" +# 3735 "parsing/parser.mly" ( "new" ) -# 41065 "parsing/parser.ml" +# 41551 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41084,9 +41570,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3695 "parsing/parser.mly" +# 3736 "parsing/parser.mly" ( "nonrec" ) -# 41090 "parsing/parser.ml" +# 41576 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41109,9 +41595,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3696 "parsing/parser.mly" +# 3737 "parsing/parser.mly" ( "object" ) -# 41115 "parsing/parser.ml" +# 41601 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41134,9 +41620,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3697 "parsing/parser.mly" +# 3738 "parsing/parser.mly" ( "of" ) -# 41140 "parsing/parser.ml" +# 41626 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41159,9 +41645,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3698 "parsing/parser.mly" +# 3739 "parsing/parser.mly" ( "open" ) -# 41165 "parsing/parser.ml" +# 41651 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41184,9 +41670,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3699 "parsing/parser.mly" +# 3740 "parsing/parser.mly" ( "or" ) -# 41190 "parsing/parser.ml" +# 41676 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41209,9 +41695,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3700 "parsing/parser.mly" +# 3741 "parsing/parser.mly" ( "private" ) -# 41215 "parsing/parser.ml" +# 41701 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41234,9 +41720,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3701 "parsing/parser.mly" +# 3742 "parsing/parser.mly" ( "rec" ) -# 41240 "parsing/parser.ml" +# 41726 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41259,9 +41745,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3702 "parsing/parser.mly" +# 3743 "parsing/parser.mly" ( "sig" ) -# 41265 "parsing/parser.ml" +# 41751 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41284,9 +41770,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3703 "parsing/parser.mly" +# 3744 "parsing/parser.mly" ( "struct" ) -# 41290 "parsing/parser.ml" +# 41776 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41309,9 +41795,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3704 "parsing/parser.mly" +# 3745 "parsing/parser.mly" ( "then" ) -# 41315 "parsing/parser.ml" +# 41801 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41334,9 +41820,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3705 "parsing/parser.mly" +# 3746 "parsing/parser.mly" ( "to" ) -# 41340 "parsing/parser.ml" +# 41826 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41359,9 +41845,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3706 "parsing/parser.mly" +# 3747 "parsing/parser.mly" ( "true" ) -# 41365 "parsing/parser.ml" +# 41851 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41384,9 +41870,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3707 "parsing/parser.mly" +# 3748 "parsing/parser.mly" ( "try" ) -# 41390 "parsing/parser.ml" +# 41876 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41409,9 +41895,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3708 "parsing/parser.mly" +# 3749 "parsing/parser.mly" ( "type" ) -# 41415 "parsing/parser.ml" +# 41901 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41434,9 +41920,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3709 "parsing/parser.mly" +# 3750 "parsing/parser.mly" ( "val" ) -# 41440 "parsing/parser.ml" +# 41926 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41459,9 +41945,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3710 "parsing/parser.mly" +# 3751 "parsing/parser.mly" ( "virtual" ) -# 41465 "parsing/parser.ml" +# 41951 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41484,9 +41970,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3711 "parsing/parser.mly" +# 3752 "parsing/parser.mly" ( "when" ) -# 41490 "parsing/parser.ml" +# 41976 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41509,9 +41995,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3712 "parsing/parser.mly" +# 3753 "parsing/parser.mly" ( "while" ) -# 41515 "parsing/parser.ml" +# 42001 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41534,9 +42020,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3713 "parsing/parser.mly" +# 3754 "parsing/parser.mly" ( "with" ) -# 41540 "parsing/parser.ml" +# 42026 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41559,9 +42045,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Parsetree.type_exception * string Asttypes.loc option) = -# 2998 "parsing/parser.mly" +# 3005 "parsing/parser.mly" ( _1 ) -# 41565 "parsing/parser.ml" +# 42051 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41635,18 +42121,18 @@ module Tables = struct let _v : (Parsetree.type_exception * string Asttypes.loc option) = let attrs = let _1 = _1_inlined5 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 41641 "parsing/parser.ml" +# 42127 "parsing/parser.ml" in let _endpos_attrs_ = _endpos__1_inlined5_ in let attrs2 = let _1 = _1_inlined4 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 41650 "parsing/parser.ml" +# 42136 "parsing/parser.ml" in let lid = @@ -41655,9 +42141,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 41661 "parsing/parser.ml" +# 42147 "parsing/parser.ml" in let id = @@ -41666,30 +42152,30 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 41672 "parsing/parser.ml" +# 42158 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 41680 "parsing/parser.ml" +# 42166 "parsing/parser.ml" in let _endpos = _endpos_attrs_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3007 "parsing/parser.mly" +# 3014 "parsing/parser.mly" ( let loc = make_loc _sloc in let docs = symbol_docs _sloc in Te.mk_exception ~attrs (Te.rebind id lid ~attrs:(attrs1 @ attrs2) ~loc ~docs) , ext ) -# 41693 "parsing/parser.ml" +# 42179 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41719,9 +42205,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.expression) = -# 2511 "parsing/parser.mly" +# 2516 "parsing/parser.mly" ( _2 ) -# 41725 "parsing/parser.ml" +# 42211 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41754,9 +42240,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2513 "parsing/parser.mly" +# 2518 "parsing/parser.mly" ( let (l, o, p) = _1 in ghexp ~loc:_sloc (Pexp_fun(l, o, p, _2)) ) -# 41760 "parsing/parser.ml" +# 42246 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41807,17 +42293,17 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__5_ in let _v : (Parsetree.expression) = let _3 = -# 2414 "parsing/parser.mly" +# 2419 "parsing/parser.mly" ( xs ) -# 41813 "parsing/parser.ml" +# 42299 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2515 "parsing/parser.mly" +# 2520 "parsing/parser.mly" ( mk_newtypes ~loc:_sloc _3 _5 ) -# 41821 "parsing/parser.ml" +# 42307 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41844,39 +42330,39 @@ module Tables = struct let ys = # 260 "<standard.mly>" ( List.flatten xss ) -# 41848 "parsing/parser.ml" +# 42334 "parsing/parser.ml" in let xs = let items = -# 883 "parsing/parser.mly" +# 884 "parsing/parser.mly" ( [] ) -# 41854 "parsing/parser.ml" +# 42340 "parsing/parser.ml" in -# 1297 "parsing/parser.mly" +# 1298 "parsing/parser.mly" ( items ) -# 41859 "parsing/parser.ml" +# 42345 "parsing/parser.ml" in # 267 "<standard.mly>" ( xs @ ys ) -# 41865 "parsing/parser.ml" +# 42351 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 805 "parsing/parser.mly" +# 806 "parsing/parser.mly" ( extra_str _startpos _endpos _1 ) -# 41874 "parsing/parser.ml" +# 42360 "parsing/parser.ml" in -# 1290 "parsing/parser.mly" +# 1291 "parsing/parser.mly" ( _1 ) -# 41880 "parsing/parser.ml" +# 42366 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -41917,7 +42403,7 @@ module Tables = struct let ys = # 260 "<standard.mly>" ( List.flatten xss ) -# 41921 "parsing/parser.ml" +# 42407 "parsing/parser.ml" in let xs = let items = @@ -41925,65 +42411,65 @@ module Tables = struct let _1 = let _1 = let attrs = -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 41931 "parsing/parser.ml" +# 42417 "parsing/parser.ml" in -# 1304 "parsing/parser.mly" +# 1305 "parsing/parser.mly" ( mkstrexp e attrs ) -# 41936 "parsing/parser.ml" +# 42422 "parsing/parser.ml" in let _startpos__1_ = _startpos_e_ in let _startpos = _startpos__1_ in -# 817 "parsing/parser.mly" +# 818 "parsing/parser.mly" ( text_str _startpos @ [_1] ) -# 41944 "parsing/parser.ml" +# 42430 "parsing/parser.ml" in let _startpos__1_ = _startpos_e_ in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 836 "parsing/parser.mly" +# 837 "parsing/parser.mly" ( mark_rhs_docs _startpos _endpos; _1 ) -# 41954 "parsing/parser.ml" +# 42440 "parsing/parser.ml" in -# 885 "parsing/parser.mly" +# 886 "parsing/parser.mly" ( x ) -# 41960 "parsing/parser.ml" +# 42446 "parsing/parser.ml" in -# 1297 "parsing/parser.mly" +# 1298 "parsing/parser.mly" ( items ) -# 41966 "parsing/parser.ml" +# 42452 "parsing/parser.ml" in # 267 "<standard.mly>" ( xs @ ys ) -# 41972 "parsing/parser.ml" +# 42458 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_e_) in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 805 "parsing/parser.mly" +# 806 "parsing/parser.mly" ( extra_str _startpos _endpos _1 ) -# 41981 "parsing/parser.ml" +# 42467 "parsing/parser.ml" in -# 1290 "parsing/parser.mly" +# 1291 "parsing/parser.mly" ( _1 ) -# 41987 "parsing/parser.ml" +# 42473 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -42009,9 +42495,44 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1319 "parsing/parser.mly" +# 1320 "parsing/parser.mly" ( val_of_let_bindings ~loc:_sloc _1 ) -# 42015 "parsing/parser.ml" +# 42501 "parsing/parser.ml" + in + { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = Obj.repr _v; + MenhirLib.EngineTypes.startp = _startpos; + MenhirLib.EngineTypes.endp = _endpos; + MenhirLib.EngineTypes.next = _menhir_stack; + }); + (fun _menhir_env -> + let _menhir_stack = _menhir_env.MenhirLib.EngineTypes.stack in + let { + MenhirLib.EngineTypes.state = _; + MenhirLib.EngineTypes.semv = _2; + MenhirLib.EngineTypes.startp = _startpos__2_; + MenhirLib.EngineTypes.endp = _endpos__2_; + MenhirLib.EngineTypes.next = { + MenhirLib.EngineTypes.state = _menhir_s; + MenhirLib.EngineTypes.semv = _1; + MenhirLib.EngineTypes.startp = _startpos__1_; + MenhirLib.EngineTypes.endp = _endpos__1_; + MenhirLib.EngineTypes.next = _menhir_stack; + }; + } = _menhir_stack in + let _2 : (Parsetree.effect_constructor) = Obj.magic _2 in + let _1 : unit = Obj.magic _1 in + let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in + let _startpos = _startpos__1_ in + let _endpos = _endpos__2_ in + let _v : (Parsetree.structure_item) = let _endpos = _endpos__2_ in + let _symbolstartpos = _startpos__1_ in + let _sloc = (_symbolstartpos, _endpos) in + +# 1322 "parsing/parser.mly" + ( mkstr ~loc:_sloc (Pstr_effect _2) ) +# 42536 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -42045,9 +42566,9 @@ module Tables = struct let _2 = let _1 = _1_inlined1 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 42051 "parsing/parser.ml" +# 42572 "parsing/parser.ml" in let _endpos__2_ = _endpos__1_inlined1_ in @@ -42055,10 +42576,10 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1322 "parsing/parser.mly" +# 1325 "parsing/parser.mly" ( let docs = symbol_docs _sloc in Pstr_extension (_1, add_docs_attrs docs _2) ) -# 42062 "parsing/parser.ml" +# 42583 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined1_ in @@ -42066,15 +42587,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 852 "parsing/parser.mly" +# 853 "parsing/parser.mly" ( mkstr ~loc:_sloc _1 ) -# 42072 "parsing/parser.ml" +# 42593 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 42078 "parsing/parser.ml" +# 42599 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -42098,23 +42619,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.structure_item) = let _1 = let _1 = -# 1325 "parsing/parser.mly" +# 1328 "parsing/parser.mly" ( Pstr_attribute _1 ) -# 42104 "parsing/parser.ml" +# 42625 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 852 "parsing/parser.mly" +# 853 "parsing/parser.mly" ( mkstr ~loc:_sloc _1 ) -# 42112 "parsing/parser.ml" +# 42633 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 42118 "parsing/parser.ml" +# 42639 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -42138,23 +42659,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.structure_item) = let _1 = let _1 = -# 1329 "parsing/parser.mly" +# 1332 "parsing/parser.mly" ( pstr_primitive _1 ) -# 42144 "parsing/parser.ml" +# 42665 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 869 "parsing/parser.mly" +# 870 "parsing/parser.mly" ( wrap_mkstr_ext ~loc:_sloc _1 ) -# 42152 "parsing/parser.ml" +# 42673 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 42158 "parsing/parser.ml" +# 42679 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -42178,23 +42699,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.structure_item) = let _1 = let _1 = -# 1331 "parsing/parser.mly" +# 1334 "parsing/parser.mly" ( pstr_primitive _1 ) -# 42184 "parsing/parser.ml" +# 42705 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 869 "parsing/parser.mly" +# 870 "parsing/parser.mly" ( wrap_mkstr_ext ~loc:_sloc _1 ) -# 42192 "parsing/parser.ml" +# 42713 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 42198 "parsing/parser.ml" +# 42719 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -42229,26 +42750,26 @@ module Tables = struct let _1 = let _1 = let _1 = -# 1044 "parsing/parser.mly" +# 1045 "parsing/parser.mly" ( let (x, b) = a in x, b :: bs ) -# 42235 "parsing/parser.ml" +# 42756 "parsing/parser.ml" in -# 2842 "parsing/parser.mly" +# 2849 "parsing/parser.mly" ( _1 ) -# 42240 "parsing/parser.ml" +# 42761 "parsing/parser.ml" in -# 2825 "parsing/parser.mly" +# 2832 "parsing/parser.mly" ( _1 ) -# 42246 "parsing/parser.ml" +# 42767 "parsing/parser.ml" in -# 1333 "parsing/parser.mly" +# 1336 "parsing/parser.mly" ( pstr_type _1 ) -# 42252 "parsing/parser.ml" +# 42773 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_bs_, _startpos_a_) in @@ -42256,15 +42777,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 869 "parsing/parser.mly" +# 870 "parsing/parser.mly" ( wrap_mkstr_ext ~loc:_sloc _1 ) -# 42262 "parsing/parser.ml" +# 42783 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 42268 "parsing/parser.ml" +# 42789 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -42349,16 +42870,16 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 42355 "parsing/parser.ml" +# 42876 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in let cs = -# 1036 "parsing/parser.mly" +# 1037 "parsing/parser.mly" ( List.rev xs ) -# 42362 "parsing/parser.ml" +# 42883 "parsing/parser.ml" in let tid = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in @@ -42366,46 +42887,46 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 42372 "parsing/parser.ml" +# 42893 "parsing/parser.ml" in let _4 = -# 3585 "parsing/parser.mly" +# 3626 "parsing/parser.mly" ( Recursive ) -# 42378 "parsing/parser.ml" +# 42899 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 42385 "parsing/parser.ml" +# 42906 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3090 "parsing/parser.mly" +# 3131 "parsing/parser.mly" ( let docs = symbol_docs _sloc in let attrs = attrs1 @ attrs2 in Te.mk tid cs ~params ~priv ~attrs ~docs, ext ) -# 42397 "parsing/parser.ml" +# 42918 "parsing/parser.ml" in -# 3073 "parsing/parser.mly" +# 3114 "parsing/parser.mly" ( _1 ) -# 42403 "parsing/parser.ml" +# 42924 "parsing/parser.ml" in -# 1335 "parsing/parser.mly" +# 1338 "parsing/parser.mly" ( pstr_typext _1 ) -# 42409 "parsing/parser.ml" +# 42930 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined3_ in @@ -42413,15 +42934,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 869 "parsing/parser.mly" +# 870 "parsing/parser.mly" ( wrap_mkstr_ext ~loc:_sloc _1 ) -# 42419 "parsing/parser.ml" +# 42940 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 42425 "parsing/parser.ml" +# 42946 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -42513,16 +43034,16 @@ module Tables = struct let attrs2 = let _1 = _1_inlined4 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 42519 "parsing/parser.ml" +# 43040 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined4_ in let cs = -# 1036 "parsing/parser.mly" +# 1037 "parsing/parser.mly" ( List.rev xs ) -# 42526 "parsing/parser.ml" +# 43047 "parsing/parser.ml" in let tid = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined3_, _startpos__1_inlined3_, _1_inlined3) in @@ -42530,9 +43051,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 42536 "parsing/parser.ml" +# 43057 "parsing/parser.ml" in let _4 = @@ -42541,41 +43062,41 @@ module Tables = struct let _startpos = _startpos__1_ in let _loc = (_startpos, _endpos) in -# 3586 "parsing/parser.mly" +# 3627 "parsing/parser.mly" ( not_expecting _loc "nonrec flag" ) -# 42547 "parsing/parser.ml" +# 43068 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 42555 "parsing/parser.ml" +# 43076 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3090 "parsing/parser.mly" +# 3131 "parsing/parser.mly" ( let docs = symbol_docs _sloc in let attrs = attrs1 @ attrs2 in Te.mk tid cs ~params ~priv ~attrs ~docs, ext ) -# 42567 "parsing/parser.ml" +# 43088 "parsing/parser.ml" in -# 3073 "parsing/parser.mly" +# 3114 "parsing/parser.mly" ( _1 ) -# 42573 "parsing/parser.ml" +# 43094 "parsing/parser.ml" in -# 1335 "parsing/parser.mly" +# 1338 "parsing/parser.mly" ( pstr_typext _1 ) -# 42579 "parsing/parser.ml" +# 43100 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined4_ in @@ -42583,15 +43104,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 869 "parsing/parser.mly" +# 870 "parsing/parser.mly" ( wrap_mkstr_ext ~loc:_sloc _1 ) -# 42589 "parsing/parser.ml" +# 43110 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 42595 "parsing/parser.ml" +# 43116 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -42615,23 +43136,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.structure_item) = let _1 = let _1 = -# 1337 "parsing/parser.mly" +# 1340 "parsing/parser.mly" ( pstr_exception _1 ) -# 42621 "parsing/parser.ml" +# 43142 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 869 "parsing/parser.mly" +# 870 "parsing/parser.mly" ( wrap_mkstr_ext ~loc:_sloc _1 ) -# 42629 "parsing/parser.ml" +# 43150 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 42635 "parsing/parser.ml" +# 43156 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -42694,9 +43215,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 42700 "parsing/parser.ml" +# 43221 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -42706,36 +43227,36 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 42712 "parsing/parser.ml" +# 43233 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 42720 "parsing/parser.ml" +# 43241 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1363 "parsing/parser.mly" +# 1366 "parsing/parser.mly" ( let docs = symbol_docs _sloc in let loc = make_loc _sloc in let attrs = attrs1 @ attrs2 in let body = Mb.mk name body ~attrs ~loc ~docs in Pstr_module body, ext ) -# 42733 "parsing/parser.ml" +# 43254 "parsing/parser.ml" in -# 1339 "parsing/parser.mly" +# 1342 "parsing/parser.mly" ( _1 ) -# 42739 "parsing/parser.ml" +# 43260 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined3_ in @@ -42743,15 +43264,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 869 "parsing/parser.mly" +# 870 "parsing/parser.mly" ( wrap_mkstr_ext ~loc:_sloc _1 ) -# 42749 "parsing/parser.ml" +# 43270 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 42755 "parsing/parser.ml" +# 43276 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -42830,9 +43351,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 42836 "parsing/parser.ml" +# 43357 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -42842,24 +43363,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 42848 "parsing/parser.ml" +# 43369 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 42856 "parsing/parser.ml" +# 43377 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1397 "parsing/parser.mly" +# 1400 "parsing/parser.mly" ( let loc = make_loc _sloc in let attrs = attrs1 @ attrs2 in @@ -42867,25 +43388,25 @@ module Tables = struct ext, Mb.mk name body ~attrs ~loc ~docs ) -# 42871 "parsing/parser.ml" +# 43392 "parsing/parser.ml" in -# 1044 "parsing/parser.mly" +# 1045 "parsing/parser.mly" ( let (x, b) = a in x, b :: bs ) -# 42877 "parsing/parser.ml" +# 43398 "parsing/parser.ml" in -# 1385 "parsing/parser.mly" +# 1388 "parsing/parser.mly" ( _1 ) -# 42883 "parsing/parser.ml" +# 43404 "parsing/parser.ml" in -# 1341 "parsing/parser.mly" +# 1344 "parsing/parser.mly" ( pstr_recmodule _1 ) -# 42889 "parsing/parser.ml" +# 43410 "parsing/parser.ml" in let _endpos__1_ = _endpos_bs_ in @@ -42893,15 +43414,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 869 "parsing/parser.mly" +# 870 "parsing/parser.mly" ( wrap_mkstr_ext ~loc:_sloc _1 ) -# 42899 "parsing/parser.ml" +# 43420 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 42905 "parsing/parser.ml" +# 43426 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -42925,23 +43446,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.structure_item) = let _1 = let _1 = -# 1343 "parsing/parser.mly" +# 1346 "parsing/parser.mly" ( let (body, ext) = _1 in (Pstr_modtype body, ext) ) -# 42931 "parsing/parser.ml" +# 43452 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 869 "parsing/parser.mly" +# 870 "parsing/parser.mly" ( wrap_mkstr_ext ~loc:_sloc _1 ) -# 42939 "parsing/parser.ml" +# 43460 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 42945 "parsing/parser.ml" +# 43466 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -42965,23 +43486,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.structure_item) = let _1 = let _1 = -# 1345 "parsing/parser.mly" +# 1348 "parsing/parser.mly" ( let (body, ext) = _1 in (Pstr_open body, ext) ) -# 42971 "parsing/parser.ml" +# 43492 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 869 "parsing/parser.mly" +# 870 "parsing/parser.mly" ( wrap_mkstr_ext ~loc:_sloc _1 ) -# 42979 "parsing/parser.ml" +# 43500 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 42985 "parsing/parser.ml" +# 43506 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -43051,9 +43572,9 @@ module Tables = struct let _1_inlined3 : (Parsetree.attributes) = Obj.magic _1_inlined3 in let body : (Parsetree.class_expr) = Obj.magic body in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 43057 "parsing/parser.ml" +# 43578 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let params : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = Obj.magic params in let virt : (Asttypes.virtual_flag) = Obj.magic virt in @@ -43071,9 +43592,9 @@ module Tables = struct let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 43077 "parsing/parser.ml" +# 43598 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -43083,24 +43604,24 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 43089 "parsing/parser.ml" +# 43610 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 43097 "parsing/parser.ml" +# 43618 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1715 "parsing/parser.mly" +# 1720 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in @@ -43108,25 +43629,25 @@ module Tables = struct ext, Ci.mk id body ~virt ~params ~attrs ~loc ~docs ) -# 43112 "parsing/parser.ml" +# 43633 "parsing/parser.ml" in -# 1044 "parsing/parser.mly" +# 1045 "parsing/parser.mly" ( let (x, b) = a in x, b :: bs ) -# 43118 "parsing/parser.ml" +# 43639 "parsing/parser.ml" in -# 1704 "parsing/parser.mly" +# 1709 "parsing/parser.mly" ( _1 ) -# 43124 "parsing/parser.ml" +# 43645 "parsing/parser.ml" in -# 1347 "parsing/parser.mly" +# 1350 "parsing/parser.mly" ( let (ext, l) = _1 in (Pstr_class l, ext) ) -# 43130 "parsing/parser.ml" +# 43651 "parsing/parser.ml" in let _endpos__1_ = _endpos_bs_ in @@ -43134,15 +43655,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 869 "parsing/parser.mly" +# 870 "parsing/parser.mly" ( wrap_mkstr_ext ~loc:_sloc _1 ) -# 43140 "parsing/parser.ml" +# 43661 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 43146 "parsing/parser.ml" +# 43667 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -43166,23 +43687,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.structure_item) = let _1 = let _1 = -# 1349 "parsing/parser.mly" +# 1352 "parsing/parser.mly" ( let (ext, l) = _1 in (Pstr_class_type l, ext) ) -# 43172 "parsing/parser.ml" +# 43693 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 869 "parsing/parser.mly" +# 870 "parsing/parser.mly" ( wrap_mkstr_ext ~loc:_sloc _1 ) -# 43180 "parsing/parser.ml" +# 43701 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 43186 "parsing/parser.ml" +# 43707 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -43238,38 +43759,38 @@ module Tables = struct let attrs2 = let _1 = _1_inlined2 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 43244 "parsing/parser.ml" +# 43765 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined2_ in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 43253 "parsing/parser.ml" +# 43774 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 1434 "parsing/parser.mly" +# 1437 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in let docs = symbol_docs _sloc in Incl.mk thing ~attrs ~loc ~docs, ext ) -# 43267 "parsing/parser.ml" +# 43788 "parsing/parser.ml" in -# 1351 "parsing/parser.mly" +# 1354 "parsing/parser.mly" ( pstr_include _1 ) -# 43273 "parsing/parser.ml" +# 43794 "parsing/parser.ml" in let _endpos__1_ = _endpos__1_inlined2_ in @@ -43277,15 +43798,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 869 "parsing/parser.mly" +# 870 "parsing/parser.mly" ( wrap_mkstr_ext ~loc:_sloc _1 ) -# 43283 "parsing/parser.ml" +# 43804 "parsing/parser.ml" in -# 1353 "parsing/parser.mly" +# 1356 "parsing/parser.mly" ( _1 ) -# 43289 "parsing/parser.ml" +# 43810 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -43308,9 +43829,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3648 "parsing/parser.mly" +# 3689 "parsing/parser.mly" ( "-" ) -# 43314 "parsing/parser.ml" +# 43835 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -43333,9 +43854,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (string) = -# 3649 "parsing/parser.mly" +# 3690 "parsing/parser.mly" ( "-." ) -# 43339 "parsing/parser.ml" +# 43860 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -43388,9 +43909,9 @@ module Tables = struct let _v : (Parsetree.row_field) = let _5 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 43394 "parsing/parser.ml" +# 43915 "parsing/parser.ml" in let _endpos__5_ = _endpos__1_inlined1_ in @@ -43399,18 +43920,18 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 43403 "parsing/parser.ml" +# 43924 "parsing/parser.ml" in -# 947 "parsing/parser.mly" +# 948 "parsing/parser.mly" ( xs ) -# 43408 "parsing/parser.ml" +# 43929 "parsing/parser.ml" in -# 3360 "parsing/parser.mly" +# 3401 "parsing/parser.mly" ( _1 ) -# 43414 "parsing/parser.ml" +# 43935 "parsing/parser.ml" in let _1 = @@ -43418,20 +43939,20 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 43424 "parsing/parser.ml" +# 43945 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3346 "parsing/parser.mly" +# 3387 "parsing/parser.mly" ( let info = symbol_info _endpos in let attrs = add_info_attrs info _5 in Rf.tag ~loc:(make_loc _sloc) ~attrs _1 _3 _4 ) -# 43435 "parsing/parser.ml" +# 43956 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -43463,9 +43984,9 @@ module Tables = struct let _v : (Parsetree.row_field) = let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 43469 "parsing/parser.ml" +# 43990 "parsing/parser.ml" in let _endpos__2_ = _endpos__1_inlined1_ in @@ -43474,20 +43995,20 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 43480 "parsing/parser.ml" +# 44001 "parsing/parser.ml" in let _endpos = _endpos__2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3350 "parsing/parser.mly" +# 3391 "parsing/parser.mly" ( let info = symbol_info _endpos in let attrs = add_info_attrs info _2 in Rf.tag ~loc:(make_loc _sloc) ~attrs _1 true [] ) -# 43491 "parsing/parser.ml" +# 44012 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -43519,7 +44040,7 @@ module Tables = struct let _v : (Parsetree.toplevel_phrase) = let arg = # 124 "<standard.mly>" ( None ) -# 43523 "parsing/parser.ml" +# 44044 "parsing/parser.ml" in let _endpos_arg_ = _endpos__1_inlined1_ in let dir = @@ -43528,18 +44049,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 43534 "parsing/parser.ml" +# 44055 "parsing/parser.ml" in let _endpos = _endpos_arg_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3548 "parsing/parser.mly" +# 3589 "parsing/parser.mly" ( mk_directive ~loc:_sloc dir arg ) -# 43543 "parsing/parser.ml" +# 44064 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -43570,9 +44091,9 @@ module Tables = struct }; } = _menhir_stack in let _1_inlined2 : ( -# 685 "parsing/parser.mly" +# 686 "parsing/parser.mly" (string * Location.t * string option) -# 43576 "parsing/parser.ml" +# 44097 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let _1_inlined1 : (Asttypes.label) = Obj.magic _1_inlined1 in let _1 : unit = Obj.magic _1 in @@ -43583,23 +44104,23 @@ module Tables = struct let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in let x = let _1 = -# 3552 "parsing/parser.mly" +# 3593 "parsing/parser.mly" ( let (s, _, _) = _1 in Pdir_string s ) -# 43589 "parsing/parser.ml" +# 44110 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 874 "parsing/parser.mly" +# 875 "parsing/parser.mly" ( mk_directive_arg ~loc:_sloc _1 ) -# 43597 "parsing/parser.ml" +# 44118 "parsing/parser.ml" in # 126 "<standard.mly>" ( Some x ) -# 43603 "parsing/parser.ml" +# 44124 "parsing/parser.ml" in let _endpos_arg_ = _endpos__1_inlined2_ in @@ -43609,18 +44130,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 43615 "parsing/parser.ml" +# 44136 "parsing/parser.ml" in let _endpos = _endpos_arg_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3548 "parsing/parser.mly" +# 3589 "parsing/parser.mly" ( mk_directive ~loc:_sloc dir arg ) -# 43624 "parsing/parser.ml" +# 44145 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -43651,9 +44172,9 @@ module Tables = struct }; } = _menhir_stack in let _1_inlined2 : ( -# 633 "parsing/parser.mly" +# 634 "parsing/parser.mly" (string * char option) -# 43657 "parsing/parser.ml" +# 44178 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let _1_inlined1 : (Asttypes.label) = Obj.magic _1_inlined1 in let _1 : unit = Obj.magic _1 in @@ -43664,23 +44185,23 @@ module Tables = struct let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in let x = let _1 = -# 3553 "parsing/parser.mly" +# 3594 "parsing/parser.mly" ( let (n, m) = _1 in Pdir_int (n ,m) ) -# 43670 "parsing/parser.ml" +# 44191 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 874 "parsing/parser.mly" +# 875 "parsing/parser.mly" ( mk_directive_arg ~loc:_sloc _1 ) -# 43678 "parsing/parser.ml" +# 44199 "parsing/parser.ml" in # 126 "<standard.mly>" ( Some x ) -# 43684 "parsing/parser.ml" +# 44205 "parsing/parser.ml" in let _endpos_arg_ = _endpos__1_inlined2_ in @@ -43690,18 +44211,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 43696 "parsing/parser.ml" +# 44217 "parsing/parser.ml" in let _endpos = _endpos_arg_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3548 "parsing/parser.mly" +# 3589 "parsing/parser.mly" ( mk_directive ~loc:_sloc dir arg ) -# 43705 "parsing/parser.ml" +# 44226 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -43741,23 +44262,23 @@ module Tables = struct let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in let x = let _1 = -# 3554 "parsing/parser.mly" +# 3595 "parsing/parser.mly" ( Pdir_ident _1 ) -# 43747 "parsing/parser.ml" +# 44268 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 874 "parsing/parser.mly" +# 875 "parsing/parser.mly" ( mk_directive_arg ~loc:_sloc _1 ) -# 43755 "parsing/parser.ml" +# 44276 "parsing/parser.ml" in # 126 "<standard.mly>" ( Some x ) -# 43761 "parsing/parser.ml" +# 44282 "parsing/parser.ml" in let _endpos_arg_ = _endpos__1_inlined2_ in @@ -43767,18 +44288,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 43773 "parsing/parser.ml" +# 44294 "parsing/parser.ml" in let _endpos = _endpos_arg_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3548 "parsing/parser.mly" +# 3589 "parsing/parser.mly" ( mk_directive ~loc:_sloc dir arg ) -# 43782 "parsing/parser.ml" +# 44303 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -43818,23 +44339,23 @@ module Tables = struct let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in let x = let _1 = -# 3555 "parsing/parser.mly" +# 3596 "parsing/parser.mly" ( Pdir_ident _1 ) -# 43824 "parsing/parser.ml" +# 44345 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 874 "parsing/parser.mly" +# 875 "parsing/parser.mly" ( mk_directive_arg ~loc:_sloc _1 ) -# 43832 "parsing/parser.ml" +# 44353 "parsing/parser.ml" in # 126 "<standard.mly>" ( Some x ) -# 43838 "parsing/parser.ml" +# 44359 "parsing/parser.ml" in let _endpos_arg_ = _endpos__1_inlined2_ in @@ -43844,18 +44365,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 43850 "parsing/parser.ml" +# 44371 "parsing/parser.ml" in let _endpos = _endpos_arg_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3548 "parsing/parser.mly" +# 3589 "parsing/parser.mly" ( mk_directive ~loc:_sloc dir arg ) -# 43859 "parsing/parser.ml" +# 44380 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -43895,23 +44416,23 @@ module Tables = struct let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in let x = let _1 = -# 3556 "parsing/parser.mly" +# 3597 "parsing/parser.mly" ( Pdir_bool false ) -# 43901 "parsing/parser.ml" +# 44422 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 874 "parsing/parser.mly" +# 875 "parsing/parser.mly" ( mk_directive_arg ~loc:_sloc _1 ) -# 43909 "parsing/parser.ml" +# 44430 "parsing/parser.ml" in # 126 "<standard.mly>" ( Some x ) -# 43915 "parsing/parser.ml" +# 44436 "parsing/parser.ml" in let _endpos_arg_ = _endpos__1_inlined2_ in @@ -43921,18 +44442,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 43927 "parsing/parser.ml" +# 44448 "parsing/parser.ml" in let _endpos = _endpos_arg_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3548 "parsing/parser.mly" +# 3589 "parsing/parser.mly" ( mk_directive ~loc:_sloc dir arg ) -# 43936 "parsing/parser.ml" +# 44457 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -43972,23 +44493,23 @@ module Tables = struct let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in let x = let _1 = -# 3557 "parsing/parser.mly" +# 3598 "parsing/parser.mly" ( Pdir_bool true ) -# 43978 "parsing/parser.ml" +# 44499 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 874 "parsing/parser.mly" +# 875 "parsing/parser.mly" ( mk_directive_arg ~loc:_sloc _1 ) -# 43986 "parsing/parser.ml" +# 44507 "parsing/parser.ml" in # 126 "<standard.mly>" ( Some x ) -# 43992 "parsing/parser.ml" +# 44513 "parsing/parser.ml" in let _endpos_arg_ = _endpos__1_inlined2_ in @@ -43998,18 +44519,18 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 44004 "parsing/parser.ml" +# 44525 "parsing/parser.ml" in let _endpos = _endpos_arg_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3548 "parsing/parser.mly" +# 3589 "parsing/parser.mly" ( mk_directive ~loc:_sloc dir arg ) -# 44013 "parsing/parser.ml" +# 44534 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44046,44 +44567,44 @@ module Tables = struct let _startpos = _startpos_e_ in let _endpos = _endpos__2_ in let _v : ( -# 781 "parsing/parser.mly" +# 782 "parsing/parser.mly" (Parsetree.toplevel_phrase) -# 44052 "parsing/parser.ml" +# 44573 "parsing/parser.ml" ) = let _1 = let _1 = let _1 = let attrs = -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 44059 "parsing/parser.ml" +# 44580 "parsing/parser.ml" in -# 1304 "parsing/parser.mly" +# 1305 "parsing/parser.mly" ( mkstrexp e attrs ) -# 44064 "parsing/parser.ml" +# 44585 "parsing/parser.ml" in let _startpos__1_ = _startpos_e_ in let _startpos = _startpos__1_ in -# 817 "parsing/parser.mly" +# 818 "parsing/parser.mly" ( text_str _startpos @ [_1] ) -# 44072 "parsing/parser.ml" +# 44593 "parsing/parser.ml" in let _startpos__1_ = _startpos_e_ in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 805 "parsing/parser.mly" +# 806 "parsing/parser.mly" ( extra_str _startpos _endpos _1 ) -# 44081 "parsing/parser.ml" +# 44602 "parsing/parser.ml" in -# 1082 "parsing/parser.mly" +# 1083 "parsing/parser.mly" ( Ptop_def _1 ) -# 44087 "parsing/parser.ml" +# 44608 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44113,28 +44634,28 @@ module Tables = struct let _startpos = _startpos_xss_ in let _endpos = _endpos__2_ in let _v : ( -# 781 "parsing/parser.mly" +# 782 "parsing/parser.mly" (Parsetree.toplevel_phrase) -# 44119 "parsing/parser.ml" +# 44640 "parsing/parser.ml" ) = let _1 = let _1 = # 260 "<standard.mly>" ( List.flatten xss ) -# 44124 "parsing/parser.ml" +# 44645 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 805 "parsing/parser.mly" +# 806 "parsing/parser.mly" ( extra_str _startpos _endpos _1 ) -# 44132 "parsing/parser.ml" +# 44653 "parsing/parser.ml" in -# 1086 "parsing/parser.mly" +# 1087 "parsing/parser.mly" ( Ptop_def _1 ) -# 44138 "parsing/parser.ml" +# 44659 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44164,13 +44685,13 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : ( -# 781 "parsing/parser.mly" +# 782 "parsing/parser.mly" (Parsetree.toplevel_phrase) -# 44170 "parsing/parser.ml" +# 44691 "parsing/parser.ml" ) = -# 1090 "parsing/parser.mly" +# 1091 "parsing/parser.mly" ( _1 ) -# 44174 "parsing/parser.ml" +# 44695 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44193,13 +44714,13 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : ( -# 781 "parsing/parser.mly" +# 782 "parsing/parser.mly" (Parsetree.toplevel_phrase) -# 44199 "parsing/parser.ml" +# 44720 "parsing/parser.ml" ) = -# 1093 "parsing/parser.mly" +# 1094 "parsing/parser.mly" ( raise End_of_file ) -# 44203 "parsing/parser.ml" +# 44724 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44222,9 +44743,9 @@ module Tables = struct let _startpos = _startpos_ty_ in let _endpos = _endpos_ty_ in let _v : (Parsetree.core_type) = -# 3252 "parsing/parser.mly" +# 3293 "parsing/parser.mly" ( ty ) -# 44228 "parsing/parser.ml" +# 44749 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44252,18 +44773,18 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 44256 "parsing/parser.ml" +# 44777 "parsing/parser.ml" in -# 975 "parsing/parser.mly" +# 976 "parsing/parser.mly" ( xs ) -# 44261 "parsing/parser.ml" +# 44782 "parsing/parser.ml" in -# 3255 "parsing/parser.mly" +# 3296 "parsing/parser.mly" ( Ptyp_tuple tys ) -# 44267 "parsing/parser.ml" +# 44788 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_xs_, _startpos_xs_) in @@ -44271,15 +44792,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 44277 "parsing/parser.ml" +# 44798 "parsing/parser.ml" in -# 3257 "parsing/parser.mly" +# 3298 "parsing/parser.mly" ( _1 ) -# 44283 "parsing/parser.ml" +# 44804 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44309,9 +44830,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.core_type option * Parsetree.core_type option) = -# 2589 "parsing/parser.mly" +# 2594 "parsing/parser.mly" ( (Some _2, None) ) -# 44315 "parsing/parser.ml" +# 44836 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44355,9 +44876,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__4_ in let _v : (Parsetree.core_type option * Parsetree.core_type option) = -# 2590 "parsing/parser.mly" +# 2595 "parsing/parser.mly" ( (Some _2, Some _4) ) -# 44361 "parsing/parser.ml" +# 44882 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44387,9 +44908,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.core_type option * Parsetree.core_type option) = -# 2591 "parsing/parser.mly" +# 2596 "parsing/parser.mly" ( (None, Some _2) ) -# 44393 "parsing/parser.ml" +# 44914 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44419,9 +44940,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.core_type option * Parsetree.core_type option) = -# 2592 "parsing/parser.mly" +# 2597 "parsing/parser.mly" ( syntax_error() ) -# 44425 "parsing/parser.ml" +# 44946 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44451,9 +44972,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.core_type option * Parsetree.core_type option) = -# 2593 "parsing/parser.mly" +# 2598 "parsing/parser.mly" ( syntax_error() ) -# 44457 "parsing/parser.ml" +# 44978 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44469,9 +44990,9 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = -# 2916 "parsing/parser.mly" +# 2923 "parsing/parser.mly" ( (Ptype_abstract, Public, None) ) -# 44475 "parsing/parser.ml" +# 44996 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44501,9 +45022,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.type_kind * Asttypes.private_flag * Parsetree.core_type option) = -# 2918 "parsing/parser.mly" +# 2925 "parsing/parser.mly" ( _2 ) -# 44507 "parsing/parser.ml" +# 45028 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44526,9 +45047,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3511 "parsing/parser.mly" +# 3552 "parsing/parser.mly" ( _1 ) -# 44532 "parsing/parser.ml" +# 45053 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44558,9 +45079,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) = -# 2933 "parsing/parser.mly" +# 2940 "parsing/parser.mly" ( _2, _1 ) -# 44564 "parsing/parser.ml" +# 45085 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44576,9 +45097,9 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = -# 2926 "parsing/parser.mly" +# 2933 "parsing/parser.mly" ( [] ) -# 44582 "parsing/parser.ml" +# 45103 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44601,9 +45122,9 @@ module Tables = struct let _startpos = _startpos_p_ in let _endpos = _endpos_p_ in let _v : ((Parsetree.core_type * (Asttypes.variance * Asttypes.injectivity)) list) = -# 2928 "parsing/parser.mly" +# 2935 "parsing/parser.mly" ( [p] ) -# 44607 "parsing/parser.ml" +# 45128 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44643,18 +45164,18 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 44647 "parsing/parser.ml" +# 45168 "parsing/parser.ml" in -# 947 "parsing/parser.mly" +# 948 "parsing/parser.mly" ( xs ) -# 44652 "parsing/parser.ml" +# 45173 "parsing/parser.ml" in -# 2930 "parsing/parser.mly" +# 2937 "parsing/parser.mly" ( ps ) -# 44658 "parsing/parser.ml" +# 45179 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44685,24 +45206,24 @@ module Tables = struct let _endpos = _endpos_tyvar_ in let _v : (Parsetree.core_type) = let _1 = let _1 = -# 2938 "parsing/parser.mly" +# 2945 "parsing/parser.mly" ( Ptyp_var tyvar ) -# 44691 "parsing/parser.ml" +# 45212 "parsing/parser.ml" in let _endpos__1_ = _endpos_tyvar_ in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 44700 "parsing/parser.ml" +# 45221 "parsing/parser.ml" in -# 2941 "parsing/parser.mly" +# 2948 "parsing/parser.mly" ( _1 ) -# 44706 "parsing/parser.ml" +# 45227 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44726,23 +45247,23 @@ module Tables = struct let _endpos = _endpos__1_ in let _v : (Parsetree.core_type) = let _1 = let _1 = -# 2940 "parsing/parser.mly" +# 2947 "parsing/parser.mly" ( Ptyp_any ) -# 44732 "parsing/parser.ml" +# 45253 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 850 "parsing/parser.mly" +# 851 "parsing/parser.mly" ( mktyp ~loc:_sloc _1 ) -# 44740 "parsing/parser.ml" +# 45261 "parsing/parser.ml" in -# 2941 "parsing/parser.mly" +# 2948 "parsing/parser.mly" ( _1 ) -# 44746 "parsing/parser.ml" +# 45267 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44758,9 +45279,9 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : (Asttypes.variance * Asttypes.injectivity) = -# 2945 "parsing/parser.mly" +# 2952 "parsing/parser.mly" ( NoVariance, NoInjectivity ) -# 44764 "parsing/parser.ml" +# 45285 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44783,9 +45304,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.variance * Asttypes.injectivity) = -# 2946 "parsing/parser.mly" +# 2953 "parsing/parser.mly" ( Covariant, NoInjectivity ) -# 44789 "parsing/parser.ml" +# 45310 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44808,9 +45329,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.variance * Asttypes.injectivity) = -# 2947 "parsing/parser.mly" +# 2954 "parsing/parser.mly" ( Contravariant, NoInjectivity ) -# 44814 "parsing/parser.ml" +# 45335 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44833,9 +45354,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.variance * Asttypes.injectivity) = -# 2948 "parsing/parser.mly" +# 2955 "parsing/parser.mly" ( NoVariance, Injective ) -# 44839 "parsing/parser.ml" +# 45360 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44865,9 +45386,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.variance * Asttypes.injectivity) = -# 2949 "parsing/parser.mly" +# 2956 "parsing/parser.mly" ( Covariant, Injective ) -# 44871 "parsing/parser.ml" +# 45392 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44897,9 +45418,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.variance * Asttypes.injectivity) = -# 2949 "parsing/parser.mly" +# 2956 "parsing/parser.mly" ( Covariant, Injective ) -# 44903 "parsing/parser.ml" +# 45424 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44929,9 +45450,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.variance * Asttypes.injectivity) = -# 2950 "parsing/parser.mly" +# 2957 "parsing/parser.mly" ( Contravariant, Injective ) -# 44935 "parsing/parser.ml" +# 45456 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44961,9 +45482,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.variance * Asttypes.injectivity) = -# 2950 "parsing/parser.mly" +# 2957 "parsing/parser.mly" ( Contravariant, Injective ) -# 44967 "parsing/parser.ml" +# 45488 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -44982,20 +45503,20 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 625 "parsing/parser.mly" +# 626 "parsing/parser.mly" (string) -# 44988 "parsing/parser.ml" +# 45509 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.variance * Asttypes.injectivity) = let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2952 "parsing/parser.mly" +# 2959 "parsing/parser.mly" ( if _1 = "+!" then Covariant, Injective else if _1 = "-!" then Contravariant, Injective else expecting _loc__1_ "type_variance" ) -# 44999 "parsing/parser.ml" +# 45520 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45014,20 +45535,20 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 671 "parsing/parser.mly" +# 672 "parsing/parser.mly" (string) -# 45020 "parsing/parser.ml" +# 45541 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.variance * Asttypes.injectivity) = let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 2956 "parsing/parser.mly" +# 2963 "parsing/parser.mly" ( if _1 = "!+" then Covariant, Injective else if _1 = "!-" then Contravariant, Injective else expecting _loc__1_ "type_variance" ) -# 45031 "parsing/parser.ml" +# 45552 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45057,47 +45578,47 @@ module Tables = struct let _startpos = _startpos_xss_ in let _endpos = _endpos__2_ in let _v : ( -# 783 "parsing/parser.mly" +# 784 "parsing/parser.mly" (Parsetree.toplevel_phrase list) -# 45063 "parsing/parser.ml" +# 45584 "parsing/parser.ml" ) = let _1 = let _1 = let ys = # 260 "<standard.mly>" ( List.flatten xss ) -# 45069 "parsing/parser.ml" +# 45590 "parsing/parser.ml" in let xs = let _1 = -# 883 "parsing/parser.mly" +# 884 "parsing/parser.mly" ( [] ) -# 45075 "parsing/parser.ml" +# 45596 "parsing/parser.ml" in -# 1113 "parsing/parser.mly" +# 1114 "parsing/parser.mly" ( _1 ) -# 45080 "parsing/parser.ml" +# 45601 "parsing/parser.ml" in # 267 "<standard.mly>" ( xs @ ys ) -# 45086 "parsing/parser.ml" +# 45607 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_xss_) in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 809 "parsing/parser.mly" +# 810 "parsing/parser.mly" ( extra_def _startpos _endpos _1 ) -# 45095 "parsing/parser.ml" +# 45616 "parsing/parser.ml" in -# 1106 "parsing/parser.mly" +# 1107 "parsing/parser.mly" ( _1 ) -# 45101 "parsing/parser.ml" +# 45622 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45141,15 +45662,15 @@ module Tables = struct let _startpos = _startpos_e_ in let _endpos = _endpos__2_ in let _v : ( -# 783 "parsing/parser.mly" +# 784 "parsing/parser.mly" (Parsetree.toplevel_phrase list) -# 45147 "parsing/parser.ml" +# 45668 "parsing/parser.ml" ) = let _1 = let _1 = let ys = # 260 "<standard.mly>" ( List.flatten xss ) -# 45153 "parsing/parser.ml" +# 45674 "parsing/parser.ml" in let xs = let _1 = @@ -45157,61 +45678,61 @@ module Tables = struct let _1 = let _1 = let attrs = -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 45163 "parsing/parser.ml" +# 45684 "parsing/parser.ml" in -# 1304 "parsing/parser.mly" +# 1305 "parsing/parser.mly" ( mkstrexp e attrs ) -# 45168 "parsing/parser.ml" +# 45689 "parsing/parser.ml" in -# 827 "parsing/parser.mly" +# 828 "parsing/parser.mly" ( Ptop_def [_1] ) -# 45174 "parsing/parser.ml" +# 45695 "parsing/parser.ml" in let _startpos__1_ = _startpos_e_ in let _startpos = _startpos__1_ in -# 825 "parsing/parser.mly" +# 826 "parsing/parser.mly" ( text_def _startpos @ [_1] ) -# 45182 "parsing/parser.ml" +# 45703 "parsing/parser.ml" in -# 885 "parsing/parser.mly" +# 886 "parsing/parser.mly" ( x ) -# 45188 "parsing/parser.ml" +# 45709 "parsing/parser.ml" in -# 1113 "parsing/parser.mly" +# 1114 "parsing/parser.mly" ( _1 ) -# 45194 "parsing/parser.ml" +# 45715 "parsing/parser.ml" in # 267 "<standard.mly>" ( xs @ ys ) -# 45200 "parsing/parser.ml" +# 45721 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos_xss_, _startpos_e_) in let _endpos = _endpos__1_ in let _startpos = _startpos__1_ in -# 809 "parsing/parser.mly" +# 810 "parsing/parser.mly" ( extra_def _startpos _endpos _1 ) -# 45209 "parsing/parser.ml" +# 45730 "parsing/parser.ml" in -# 1106 "parsing/parser.mly" +# 1107 "parsing/parser.mly" ( _1 ) -# 45215 "parsing/parser.ml" +# 45736 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45248,9 +45769,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__3_ in let _v : (Asttypes.label) = -# 3430 "parsing/parser.mly" +# 3471 "parsing/parser.mly" ( _2 ) -# 45254 "parsing/parser.ml" +# 45775 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45289,9 +45810,9 @@ module Tables = struct let _v : (Asttypes.label) = let _loc__3_ = (_startpos__3_, _endpos__3_) in let _loc__1_ = (_startpos__1_, _endpos__1_) in -# 3431 "parsing/parser.mly" +# 3472 "parsing/parser.mly" ( unclosed "(" _loc__1_ ")" _loc__3_ ) -# 45295 "parsing/parser.ml" +# 45816 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45322,9 +45843,9 @@ module Tables = struct let _endpos = _endpos__2_ in let _v : (Asttypes.label) = let _loc__2_ = (_startpos__2_, _endpos__2_) in -# 3432 "parsing/parser.mly" +# 3473 "parsing/parser.mly" ( expecting _loc__2_ "operator" ) -# 45328 "parsing/parser.ml" +# 45849 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45362,9 +45883,9 @@ module Tables = struct let _endpos = _endpos__3_ in let _v : (Asttypes.label) = let _loc__3_ = (_startpos__3_, _endpos__3_) in -# 3433 "parsing/parser.mly" +# 3474 "parsing/parser.mly" ( expecting _loc__3_ "module-expr" ) -# 45368 "parsing/parser.ml" +# 45889 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45383,17 +45904,17 @@ module Tables = struct MenhirLib.EngineTypes.next = _menhir_stack; } = _menhir_stack in let _1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 45389 "parsing/parser.ml" +# 45910 "parsing/parser.ml" ) = Obj.magic _1 in let _endpos__0_ = _menhir_stack.MenhirLib.EngineTypes.endp in let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = -# 3436 "parsing/parser.mly" +# 3477 "parsing/parser.mly" ( _1 ) -# 45397 "parsing/parser.ml" +# 45918 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45416,9 +45937,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.label) = -# 3437 "parsing/parser.mly" +# 3478 "parsing/parser.mly" ( _1 ) -# 45422 "parsing/parser.ml" +# 45943 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45441,9 +45962,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Longident.t) = -# 3505 "parsing/parser.mly" +# 3546 "parsing/parser.mly" ( _1 ) -# 45447 "parsing/parser.ml" +# 45968 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45488,9 +46009,9 @@ module Tables = struct let ty : (Parsetree.core_type) = Obj.magic ty in let _5 : unit = Obj.magic _5 in let _1_inlined1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 45494 "parsing/parser.ml" +# 46015 "parsing/parser.ml" ) = Obj.magic _1_inlined1 in let mutable_ : (Asttypes.mutable_flag) = Obj.magic mutable_ in let _1 : (Parsetree.attributes) = Obj.magic _1 in @@ -45502,33 +46023,33 @@ module Tables = struct Parsetree.attributes) = let label = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 45508 "parsing/parser.ml" +# 46029 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 45516 "parsing/parser.ml" +# 46037 "parsing/parser.ml" in let attrs = -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 45522 "parsing/parser.ml" +# 46043 "parsing/parser.ml" in let _1 = -# 3641 "parsing/parser.mly" +# 3682 "parsing/parser.mly" ( Fresh ) -# 45527 "parsing/parser.ml" +# 46048 "parsing/parser.ml" in -# 1855 "parsing/parser.mly" +# 1860 "parsing/parser.mly" ( (label, mutable_, Cfk_virtual ty), attrs ) -# 45532 "parsing/parser.ml" +# 46053 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45573,9 +46094,9 @@ module Tables = struct let _6 : (Parsetree.expression) = Obj.magic _6 in let _5 : unit = Obj.magic _5 in let _1_inlined1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 45579 "parsing/parser.ml" +# 46100 "parsing/parser.ml" ) = Obj.magic _1_inlined1 in let _3 : (Asttypes.mutable_flag) = Obj.magic _3 in let _1 : (Parsetree.attributes) = Obj.magic _1 in @@ -45587,33 +46108,33 @@ module Tables = struct Parsetree.attributes) = let _4 = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 45593 "parsing/parser.ml" +# 46114 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 45601 "parsing/parser.ml" +# 46122 "parsing/parser.ml" in let _2 = -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 45607 "parsing/parser.ml" +# 46128 "parsing/parser.ml" in let _1 = -# 3644 "parsing/parser.mly" +# 3685 "parsing/parser.mly" ( Fresh ) -# 45612 "parsing/parser.ml" +# 46133 "parsing/parser.ml" in -# 1857 "parsing/parser.mly" +# 1862 "parsing/parser.mly" ( (_4, _3, Cfk_concrete (_1, _6)), _2 ) -# 45617 "parsing/parser.ml" +# 46138 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45664,9 +46185,9 @@ module Tables = struct let _6 : (Parsetree.expression) = Obj.magic _6 in let _5 : unit = Obj.magic _5 in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 45670 "parsing/parser.ml" +# 46191 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let _3 : (Asttypes.mutable_flag) = Obj.magic _3 in let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in @@ -45679,36 +46200,36 @@ module Tables = struct Parsetree.attributes) = let _4 = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 45685 "parsing/parser.ml" +# 46206 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 45693 "parsing/parser.ml" +# 46214 "parsing/parser.ml" in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 45701 "parsing/parser.ml" +# 46222 "parsing/parser.ml" in let _1 = -# 3645 "parsing/parser.mly" +# 3686 "parsing/parser.mly" ( Override ) -# 45707 "parsing/parser.ml" +# 46228 "parsing/parser.ml" in -# 1857 "parsing/parser.mly" +# 1862 "parsing/parser.mly" ( (_4, _3, Cfk_concrete (_1, _6)), _2 ) -# 45712 "parsing/parser.ml" +# 46233 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45760,9 +46281,9 @@ module Tables = struct let _6 : unit = Obj.magic _6 in let _5 : (Parsetree.core_type option * Parsetree.core_type option) = Obj.magic _5 in let _1_inlined1 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 45766 "parsing/parser.ml" +# 46287 "parsing/parser.ml" ) = Obj.magic _1_inlined1 in let _3 : (Asttypes.mutable_flag) = Obj.magic _3 in let _1 : (Parsetree.attributes) = Obj.magic _1 in @@ -45774,30 +46295,30 @@ module Tables = struct Parsetree.attributes) = let _4 = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined1_, _startpos__1_inlined1_, _1_inlined1) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 45780 "parsing/parser.ml" +# 46301 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 45788 "parsing/parser.ml" +# 46309 "parsing/parser.ml" in let _startpos__4_ = _startpos__1_inlined1_ in let _2 = -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 45795 "parsing/parser.ml" +# 46316 "parsing/parser.ml" in let (_endpos__2_, _startpos__2_) = (_endpos__1_, _startpos__1_) in let _1 = -# 3644 "parsing/parser.mly" +# 3685 "parsing/parser.mly" ( Fresh ) -# 45801 "parsing/parser.ml" +# 46322 "parsing/parser.ml" in let (_endpos__1_, _startpos__1_) = (_endpos__0_, _endpos__0_) in let _endpos = _endpos__7_ in @@ -45813,11 +46334,11 @@ module Tables = struct _startpos__4_ in let _sloc = (_symbolstartpos, _endpos) in -# 1860 "parsing/parser.mly" +# 1865 "parsing/parser.mly" ( let e = mkexp_constraint ~loc:_sloc _7 _5 in (_4, _3, Cfk_concrete (_1, e)), _2 ) -# 45821 "parsing/parser.ml" +# 46342 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -45875,9 +46396,9 @@ module Tables = struct let _6 : unit = Obj.magic _6 in let _5 : (Parsetree.core_type option * Parsetree.core_type option) = Obj.magic _5 in let _1_inlined2 : ( -# 647 "parsing/parser.mly" +# 648 "parsing/parser.mly" (string) -# 45881 "parsing/parser.ml" +# 46402 "parsing/parser.ml" ) = Obj.magic _1_inlined2 in let _3 : (Asttypes.mutable_flag) = Obj.magic _3 in let _1_inlined1 : (Parsetree.attributes) = Obj.magic _1_inlined1 in @@ -45890,33 +46411,33 @@ module Tables = struct Parsetree.attributes) = let _4 = let (_endpos__1_, _startpos__1_, _1) = (_endpos__1_inlined2_, _startpos__1_inlined2_, _1_inlined2) in let _1 = -# 3404 "parsing/parser.mly" +# 3445 "parsing/parser.mly" ( _1 ) -# 45896 "parsing/parser.ml" +# 46417 "parsing/parser.ml" in let _endpos = _endpos__1_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 45904 "parsing/parser.ml" +# 46425 "parsing/parser.ml" in let _startpos__4_ = _startpos__1_inlined2_ in let _2 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 45913 "parsing/parser.ml" +# 46434 "parsing/parser.ml" in let (_endpos__2_, _startpos__2_) = (_endpos__1_inlined1_, _startpos__1_inlined1_) in let _1 = -# 3645 "parsing/parser.mly" +# 3686 "parsing/parser.mly" ( Override ) -# 45920 "parsing/parser.ml" +# 46441 "parsing/parser.ml" in let _endpos = _endpos__7_ in let _symbolstartpos = if _startpos__1_ != _endpos__1_ then @@ -45931,11 +46452,11 @@ module Tables = struct _startpos__4_ in let _sloc = (_symbolstartpos, _endpos) in -# 1860 "parsing/parser.mly" +# 1865 "parsing/parser.mly" ( let e = mkexp_constraint ~loc:_sloc _7 _5 in (_4, _3, Cfk_concrete (_1, e)), _2 ) -# 45939 "parsing/parser.ml" +# 46460 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46002,9 +46523,9 @@ module Tables = struct let _v : (Parsetree.value_description * string Asttypes.loc option) = let attrs2 = let _1 = _1_inlined3 in -# 3738 "parsing/parser.mly" +# 3779 "parsing/parser.mly" ( _1 ) -# 46008 "parsing/parser.ml" +# 46529 "parsing/parser.ml" in let _endpos_attrs2_ = _endpos__1_inlined3_ in @@ -46014,30 +46535,30 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 46020 "parsing/parser.ml" +# 46541 "parsing/parser.ml" in let attrs1 = let _1 = _1_inlined1 in -# 3742 "parsing/parser.mly" +# 3783 "parsing/parser.mly" ( _1 ) -# 46028 "parsing/parser.ml" +# 46549 "parsing/parser.ml" in let _endpos = _endpos_attrs2_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 2787 "parsing/parser.mly" +# 2794 "parsing/parser.mly" ( let attrs = attrs1 @ attrs2 in let loc = make_loc _sloc in let docs = symbol_docs _sloc in Val.mk id ty ~attrs ~loc ~docs, ext ) -# 46041 "parsing/parser.ml" +# 46562 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46053,9 +46574,9 @@ module Tables = struct let _startpos = _menhir_stack.MenhirLib.EngineTypes.endp in let _endpos = _startpos in let _v : (Asttypes.virtual_flag) = -# 3605 "parsing/parser.mly" +# 3646 "parsing/parser.mly" ( Concrete ) -# 46059 "parsing/parser.ml" +# 46580 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46078,9 +46599,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.virtual_flag) = -# 3606 "parsing/parser.mly" +# 3647 "parsing/parser.mly" ( Virtual ) -# 46084 "parsing/parser.ml" +# 46605 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46103,9 +46624,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.mutable_flag) = -# 3629 "parsing/parser.mly" +# 3670 "parsing/parser.mly" ( Immutable ) -# 46109 "parsing/parser.ml" +# 46630 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46135,9 +46656,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.mutable_flag) = -# 3630 "parsing/parser.mly" +# 3671 "parsing/parser.mly" ( Mutable ) -# 46141 "parsing/parser.ml" +# 46662 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46167,9 +46688,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.mutable_flag) = -# 3631 "parsing/parser.mly" +# 3672 "parsing/parser.mly" ( Mutable ) -# 46173 "parsing/parser.ml" +# 46694 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46192,9 +46713,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.private_flag) = -# 3636 "parsing/parser.mly" +# 3677 "parsing/parser.mly" ( Public ) -# 46198 "parsing/parser.ml" +# 46719 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46224,9 +46745,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.private_flag) = -# 3637 "parsing/parser.mly" +# 3678 "parsing/parser.mly" ( Private ) -# 46230 "parsing/parser.ml" +# 46751 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46256,9 +46777,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.private_flag) = -# 3638 "parsing/parser.mly" +# 3679 "parsing/parser.mly" ( Private ) -# 46262 "parsing/parser.ml" +# 46783 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46320,27 +46841,27 @@ module Tables = struct let xs = # 253 "<standard.mly>" ( List.rev xs ) -# 46324 "parsing/parser.ml" +# 46845 "parsing/parser.ml" in -# 897 "parsing/parser.mly" +# 898 "parsing/parser.mly" ( xs ) -# 46329 "parsing/parser.ml" +# 46850 "parsing/parser.ml" in -# 2887 "parsing/parser.mly" +# 2894 "parsing/parser.mly" ( _1 ) -# 46335 "parsing/parser.ml" +# 46856 "parsing/parser.ml" in let _endpos__6_ = _endpos_xs_ in let _5 = let _1 = _1_inlined2 in -# 3200 "parsing/parser.mly" +# 3241 "parsing/parser.mly" ( _1 ) -# 46344 "parsing/parser.ml" +# 46865 "parsing/parser.ml" in let _3 = @@ -46349,16 +46870,16 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 46355 "parsing/parser.ml" +# 46876 "parsing/parser.ml" in let _endpos = _endpos__6_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3123 "parsing/parser.mly" +# 3164 "parsing/parser.mly" ( let lident = loc_last _3 in Pwith_type (_3, @@ -46368,7 +46889,7 @@ module Tables = struct ~manifest:_5 ~priv:_4 ~loc:(make_loc _sloc))) ) -# 46372 "parsing/parser.ml" +# 46893 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46421,9 +46942,9 @@ module Tables = struct let _v : (Parsetree.with_constraint) = let _5 = let _1 = _1_inlined2 in -# 3200 "parsing/parser.mly" +# 3241 "parsing/parser.mly" ( _1 ) -# 46427 "parsing/parser.ml" +# 46948 "parsing/parser.ml" in let _endpos__5_ = _endpos__1_inlined2_ in @@ -46433,16 +46954,16 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 46439 "parsing/parser.ml" +# 46960 "parsing/parser.ml" in let _endpos = _endpos__5_ in let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 3136 "parsing/parser.mly" +# 3177 "parsing/parser.mly" ( let lident = loc_last _3 in Pwith_typesubst (_3, @@ -46450,7 +46971,7 @@ module Tables = struct ~params:_2 ~manifest:_5 ~loc:(make_loc _sloc))) ) -# 46454 "parsing/parser.ml" +# 46975 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46499,9 +47020,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 46505 "parsing/parser.ml" +# 47026 "parsing/parser.ml" in let _2 = @@ -46510,15 +47031,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 46516 "parsing/parser.ml" +# 47037 "parsing/parser.ml" in -# 3144 "parsing/parser.mly" +# 3185 "parsing/parser.mly" ( Pwith_module (_2, _4) ) -# 46522 "parsing/parser.ml" +# 47043 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46567,9 +47088,9 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 46573 "parsing/parser.ml" +# 47094 "parsing/parser.ml" in let _2 = @@ -46578,15 +47099,15 @@ module Tables = struct let _symbolstartpos = _startpos__1_ in let _sloc = (_symbolstartpos, _endpos) in -# 813 "parsing/parser.mly" +# 814 "parsing/parser.mly" ( mkrhs _1 _sloc ) -# 46584 "parsing/parser.ml" +# 47105 "parsing/parser.ml" in -# 3146 "parsing/parser.mly" +# 3187 "parsing/parser.mly" ( Pwith_modsubst (_2, _4) ) -# 46590 "parsing/parser.ml" +# 47111 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46609,9 +47130,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__1_ in let _v : (Asttypes.private_flag) = -# 3149 "parsing/parser.mly" +# 3190 "parsing/parser.mly" ( Public ) -# 46615 "parsing/parser.ml" +# 47136 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46641,9 +47162,9 @@ module Tables = struct let _startpos = _startpos__1_ in let _endpos = _endpos__2_ in let _v : (Asttypes.private_flag) = -# 3150 "parsing/parser.mly" +# 3191 "parsing/parser.mly" ( Private ) -# 46647 "parsing/parser.ml" +# 47168 "parsing/parser.ml" in { MenhirLib.EngineTypes.state = _menhir_s; @@ -46671,222 +47192,222 @@ end let use_file = fun lexer lexbuf -> - (Obj.magic (MenhirInterpreter.entry 1809 lexer lexbuf) : ( -# 783 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.entry 1835 lexer lexbuf) : ( +# 784 "parsing/parser.mly" (Parsetree.toplevel_phrase list) -# 46678 "parsing/parser.ml" +# 47199 "parsing/parser.ml" )) and toplevel_phrase = fun lexer lexbuf -> - (Obj.magic (MenhirInterpreter.entry 1789 lexer lexbuf) : ( -# 781 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.entry 1815 lexer lexbuf) : ( +# 782 "parsing/parser.mly" (Parsetree.toplevel_phrase) -# 46686 "parsing/parser.ml" +# 47207 "parsing/parser.ml" )) and parse_val_longident = fun lexer lexbuf -> - (Obj.magic (MenhirInterpreter.entry 1783 lexer lexbuf) : ( -# 793 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.entry 1809 lexer lexbuf) : ( +# 794 "parsing/parser.mly" (Longident.t) -# 46694 "parsing/parser.ml" +# 47215 "parsing/parser.ml" )) and parse_pattern = fun lexer lexbuf -> - (Obj.magic (MenhirInterpreter.entry 1779 lexer lexbuf) : ( -# 789 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.entry 1805 lexer lexbuf) : ( +# 790 "parsing/parser.mly" (Parsetree.pattern) -# 46702 "parsing/parser.ml" +# 47223 "parsing/parser.ml" )) and parse_mty_longident = fun lexer lexbuf -> - (Obj.magic (MenhirInterpreter.entry 1775 lexer lexbuf) : ( -# 795 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.entry 1801 lexer lexbuf) : ( +# 796 "parsing/parser.mly" (Longident.t) -# 46710 "parsing/parser.ml" +# 47231 "parsing/parser.ml" )) and parse_mod_longident = fun lexer lexbuf -> - (Obj.magic (MenhirInterpreter.entry 1771 lexer lexbuf) : ( -# 799 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.entry 1797 lexer lexbuf) : ( +# 800 "parsing/parser.mly" (Longident.t) -# 46718 "parsing/parser.ml" +# 47239 "parsing/parser.ml" )) and parse_mod_ext_longident = fun lexer lexbuf -> - (Obj.magic (MenhirInterpreter.entry 1767 lexer lexbuf) : ( -# 797 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.entry 1793 lexer lexbuf) : ( +# 798 "parsing/parser.mly" (Longident.t) -# 46726 "parsing/parser.ml" +# 47247 "parsing/parser.ml" )) and parse_expression = fun lexer lexbuf -> - (Obj.magic (MenhirInterpreter.entry 1763 lexer lexbuf) : ( -# 787 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.entry 1789 lexer lexbuf) : ( +# 788 "parsing/parser.mly" (Parsetree.expression) -# 46734 "parsing/parser.ml" +# 47255 "parsing/parser.ml" )) and parse_core_type = fun lexer lexbuf -> - (Obj.magic (MenhirInterpreter.entry 1759 lexer lexbuf) : ( -# 785 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.entry 1785 lexer lexbuf) : ( +# 786 "parsing/parser.mly" (Parsetree.core_type) -# 46742 "parsing/parser.ml" +# 47263 "parsing/parser.ml" )) and parse_constr_longident = fun lexer lexbuf -> - (Obj.magic (MenhirInterpreter.entry 1755 lexer lexbuf) : ( -# 791 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.entry 1781 lexer lexbuf) : ( +# 792 "parsing/parser.mly" (Longident.t) -# 46750 "parsing/parser.ml" +# 47271 "parsing/parser.ml" )) and parse_any_longident = fun lexer lexbuf -> - (Obj.magic (MenhirInterpreter.entry 1737 lexer lexbuf) : ( -# 801 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.entry 1763 lexer lexbuf) : ( +# 802 "parsing/parser.mly" (Longident.t) -# 46758 "parsing/parser.ml" +# 47279 "parsing/parser.ml" )) and interface = fun lexer lexbuf -> - (Obj.magic (MenhirInterpreter.entry 1733 lexer lexbuf) : ( -# 779 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.entry 1759 lexer lexbuf) : ( +# 780 "parsing/parser.mly" (Parsetree.signature) -# 46766 "parsing/parser.ml" +# 47287 "parsing/parser.ml" )) and implementation = fun lexer lexbuf -> (Obj.magic (MenhirInterpreter.entry 0 lexer lexbuf) : ( -# 777 "parsing/parser.mly" +# 778 "parsing/parser.mly" (Parsetree.structure) -# 46774 "parsing/parser.ml" +# 47295 "parsing/parser.ml" )) module Incremental = struct let use_file = fun initial_position -> - (Obj.magic (MenhirInterpreter.start 1809 initial_position) : ( -# 783 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.start 1835 initial_position) : ( +# 784 "parsing/parser.mly" (Parsetree.toplevel_phrase list) -# 46784 "parsing/parser.ml" +# 47305 "parsing/parser.ml" ) MenhirInterpreter.checkpoint) and toplevel_phrase = fun initial_position -> - (Obj.magic (MenhirInterpreter.start 1789 initial_position) : ( -# 781 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.start 1815 initial_position) : ( +# 782 "parsing/parser.mly" (Parsetree.toplevel_phrase) -# 46792 "parsing/parser.ml" +# 47313 "parsing/parser.ml" ) MenhirInterpreter.checkpoint) and parse_val_longident = fun initial_position -> - (Obj.magic (MenhirInterpreter.start 1783 initial_position) : ( -# 793 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.start 1809 initial_position) : ( +# 794 "parsing/parser.mly" (Longident.t) -# 46800 "parsing/parser.ml" +# 47321 "parsing/parser.ml" ) MenhirInterpreter.checkpoint) and parse_pattern = fun initial_position -> - (Obj.magic (MenhirInterpreter.start 1779 initial_position) : ( -# 789 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.start 1805 initial_position) : ( +# 790 "parsing/parser.mly" (Parsetree.pattern) -# 46808 "parsing/parser.ml" +# 47329 "parsing/parser.ml" ) MenhirInterpreter.checkpoint) and parse_mty_longident = fun initial_position -> - (Obj.magic (MenhirInterpreter.start 1775 initial_position) : ( -# 795 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.start 1801 initial_position) : ( +# 796 "parsing/parser.mly" (Longident.t) -# 46816 "parsing/parser.ml" +# 47337 "parsing/parser.ml" ) MenhirInterpreter.checkpoint) and parse_mod_longident = fun initial_position -> - (Obj.magic (MenhirInterpreter.start 1771 initial_position) : ( -# 799 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.start 1797 initial_position) : ( +# 800 "parsing/parser.mly" (Longident.t) -# 46824 "parsing/parser.ml" +# 47345 "parsing/parser.ml" ) MenhirInterpreter.checkpoint) and parse_mod_ext_longident = fun initial_position -> - (Obj.magic (MenhirInterpreter.start 1767 initial_position) : ( -# 797 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.start 1793 initial_position) : ( +# 798 "parsing/parser.mly" (Longident.t) -# 46832 "parsing/parser.ml" +# 47353 "parsing/parser.ml" ) MenhirInterpreter.checkpoint) and parse_expression = fun initial_position -> - (Obj.magic (MenhirInterpreter.start 1763 initial_position) : ( -# 787 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.start 1789 initial_position) : ( +# 788 "parsing/parser.mly" (Parsetree.expression) -# 46840 "parsing/parser.ml" +# 47361 "parsing/parser.ml" ) MenhirInterpreter.checkpoint) and parse_core_type = fun initial_position -> - (Obj.magic (MenhirInterpreter.start 1759 initial_position) : ( -# 785 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.start 1785 initial_position) : ( +# 786 "parsing/parser.mly" (Parsetree.core_type) -# 46848 "parsing/parser.ml" +# 47369 "parsing/parser.ml" ) MenhirInterpreter.checkpoint) and parse_constr_longident = fun initial_position -> - (Obj.magic (MenhirInterpreter.start 1755 initial_position) : ( -# 791 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.start 1781 initial_position) : ( +# 792 "parsing/parser.mly" (Longident.t) -# 46856 "parsing/parser.ml" +# 47377 "parsing/parser.ml" ) MenhirInterpreter.checkpoint) and parse_any_longident = fun initial_position -> - (Obj.magic (MenhirInterpreter.start 1737 initial_position) : ( -# 801 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.start 1763 initial_position) : ( +# 802 "parsing/parser.mly" (Longident.t) -# 46864 "parsing/parser.ml" +# 47385 "parsing/parser.ml" ) MenhirInterpreter.checkpoint) and interface = fun initial_position -> - (Obj.magic (MenhirInterpreter.start 1733 initial_position) : ( -# 779 "parsing/parser.mly" + (Obj.magic (MenhirInterpreter.start 1759 initial_position) : ( +# 780 "parsing/parser.mly" (Parsetree.signature) -# 46872 "parsing/parser.ml" +# 47393 "parsing/parser.ml" ) MenhirInterpreter.checkpoint) and implementation = fun initial_position -> (Obj.magic (MenhirInterpreter.start 0 initial_position) : ( -# 777 "parsing/parser.mly" +# 778 "parsing/parser.mly" (Parsetree.structure) -# 46880 "parsing/parser.ml" +# 47401 "parsing/parser.ml" ) MenhirInterpreter.checkpoint) end -# 3772 "parsing/parser.mly" +# 3813 "parsing/parser.mly" -# 46888 "parsing/parser.ml" +# 47409 "parsing/parser.ml" # 269 "<standard.mly>" -# 46893 "parsing/parser.ml" +# 47414 "parsing/parser.ml" diff --git a/boot/menhir/parser.mli b/boot/menhir/parser.mli index dd3f68ee8e..4c4f32ceee 100644 --- a/boot/menhir/parser.mli +++ b/boot/menhir/parser.mli @@ -97,6 +97,7 @@ type token = | EOF | END | ELSE + | EFFECT | DOWNTO | DOTOP of (string) | DOTDOT diff --git a/boot/ocamlc b/boot/ocamlc Binary files differindex 6bcfb63466..c856286518 100755 --- a/boot/ocamlc +++ b/boot/ocamlc diff --git a/boot/ocamllex b/boot/ocamllex Binary files differindex e353edbc56..c8f74b4dfe 100755 --- a/boot/ocamllex +++ b/boot/ocamllex diff --git a/bytecomp/bytegen.ml b/bytecomp/bytegen.ml index 4931456588..006288a0d0 100644 --- a/bytecomp/bytegen.ml +++ b/bytecomp/bytegen.ml @@ -109,6 +109,7 @@ let rec is_tailcall = function from the tail call optimization? *) let preserve_tailcall_for_prim = function + Prunstack | Pperform | Presume | Preperform | Ppoll | Pidentity | Popaque | Pdirapply | Prevapply | Psequor | Psequand -> true | Pbytes_to_string | Pbytes_of_string | Pignore | Pgetglobal _ | Psetglobal _ @@ -130,6 +131,7 @@ let preserve_tailcall_for_prim = function | Pbytes_load_32 _ | Pbytes_load_64 _ | Pbytes_set_16 _ | Pbytes_set_32 _ | Pbytes_set_64 _ | Pbigstring_load_16 _ | Pbigstring_load_32 _ | Pbigstring_load_64 _ | Pbigstring_set_16 _ | Pbigstring_set_32 _ + | Patomic_exchange | Patomic_cas | Patomic_fetch_add | Patomic_load _ | Pnop | Pbigstring_set_64 _ | Pctconst _ | Pbswap16 | Pbbswap _ | Pint_as_pointer -> false @@ -369,6 +371,8 @@ let compunit_name = ref "" let max_stack_used = ref 0 +let check_stack sz = + if sz > !max_stack_used then max_stack_used := sz (* Sequence of string tests *) @@ -383,7 +387,8 @@ let comp_bint_primitive bi suff args = | Pint64 -> "caml_int64_" in Kccall(pref ^ suff, List.length args) -let comp_primitive p args = +let comp_primitive p sz args = + check_stack sz; match p with Pgetglobal id -> Kgetglobal id | Psetglobal id -> Ksetglobal id @@ -391,13 +396,18 @@ let comp_primitive p args = | Pcompare_ints -> Kccall("caml_int_compare", 2) | Pcompare_floats -> Kccall("caml_float_compare", 2) | Pcompare_bints bi -> comp_bint_primitive bi "compare" args - | Pfield n -> Kgetfield n + | Pmakeblock(tag, _mut, _) -> Kmakeblock(List.length args, tag) + | Pfield(n, _ptr, Immutable) -> Kgetfield n + | Pfield(n, _ptr, Mutable) -> Kgetmutablefield n | Pfield_computed -> Kgetvectitem | Psetfield(n, _ptr, _init) -> Ksetfield n | Psetfield_computed(_ptr, _init) -> Ksetvectitem | Psetfloatfield (n, _init) -> Ksetfloatfield n | Pduprecord _ -> Kccall("caml_obj_dup", 1) | Pccall p -> Kccall(p.prim_name, p.prim_arity) + | Pperform -> + check_stack (sz + 4); + Kperform | Pnegint -> Knegint | Paddint -> Kaddint | Psubint -> Ksubint @@ -503,6 +513,10 @@ let comp_primitive p args = | Pint_as_pointer -> Kccall("caml_int_as_pointer", 1) | Pbytes_to_string -> Kccall("caml_string_of_bytes", 1) | Pbytes_of_string -> Kccall("caml_bytes_of_string", 1) + | Patomic_load _ -> Kccall("caml_atomic_load", 1) + | Patomic_exchange -> Kccall("caml_atomic_exchange", 2); + | Patomic_cas -> Kccall("caml_atomic_cas", 3); + | Patomic_fetch_add -> Kccall("caml_atomic_fetch_add", 2); | _ -> fatal_error "Bytegen.comp_primitive" let is_immed n = immed_min <= n && n <= immed_max @@ -522,7 +536,7 @@ module Storer = Result = list of instructions that evaluate exp, then perform cont. *) let rec comp_expr env exp sz cont = - if sz > !max_stack_used then max_stack_used := sz; + check_stack sz; match exp with Lvar id -> begin try @@ -670,7 +684,8 @@ let rec comp_expr env exp sz cont = in comp_init env sz decl_size end - | Lprim((Pidentity | Popaque), [arg], _) -> + | Lprim((Pidentity | Pnop | Ppoll | Popaque | + Pbytes_to_string | Pbytes_of_string), [arg], _) -> comp_expr env arg sz cont | Lprim(Pignore, [arg], _) -> comp_expr env arg sz (add_const_unit cont) @@ -748,6 +763,25 @@ let rec comp_expr env exp sz cont = (Kmakeblock(List.length args, 0) :: Kccall("caml_make_array", 1) :: cont) end + | Lprim((Presume|Prunstack), args, _) -> + let nargs = List.length args - 1 in + assert (nargs = 2); + (* Resume itself only pushes 3 words, but perform adds another *) + check_stack (sz + 4); + if is_tailcall cont then + comp_args env args sz + (Kresumeterm(sz + nargs) :: discard_dead_code cont) + else + comp_args env args sz (Kresume :: cont) + | Lprim(Preperform, args, _) -> + let nargs = List.length args - 1 in + assert (nargs = 2); + check_stack (sz + 3); + if is_tailcall cont then + comp_args env args sz + (Kreperformterm(sz + nargs) :: discard_dead_code cont) + else + fatal_error "Reperform used in non-tail position" | Lprim (Pduparray (kind, mutability), [Lprim (Pmakearray (kind',_),args,_)], loc) -> assert (kind = kind'); @@ -763,8 +797,9 @@ let rec comp_expr env exp sz cont = | Lprim (Pintcomp c, [arg ; (Lconst _ as k)], _) -> let p = Pintcomp (swap_integer_comparison c) and args = [k ; arg] in - comp_args env args sz (comp_primitive p args :: cont) - | Lprim (Pfloatcomp cmp, args, _) -> + let nargs = List.length args - 1 in + comp_args env args sz (comp_primitive p (sz + nargs - 1) args :: cont) + | Lprim (Pfloatcomp cmp, args, _) -> let cont = match cmp with | CFeq -> Kccall("caml_eq_float", 2) :: cont @@ -786,7 +821,8 @@ let rec comp_expr env exp sz cont = let cont = add_pseudo_event loc !compunit_name cont in comp_args env args sz (Kgetfloatfield n :: cont) | Lprim(p, args, _) -> - comp_args env args sz (comp_primitive p args :: cont) + let nargs = List.length args - 1 in + comp_args env args sz (comp_primitive p (sz + nargs - 1) args :: cont) | Lstaticcatch (body, (i, vars) , handler) -> let vars = List.map fst vars in let nvars = List.length vars in diff --git a/bytecomp/emitcode.ml b/bytecomp/emitcode.ml index 1b744f3fe9..984ddf2207 100644 --- a/bytecomp/emitcode.ml +++ b/bytecomp/emitcode.ml @@ -251,6 +251,8 @@ let emit_instr = function else (out opMAKEBLOCK; out_int n; out_int t) | Kgetfield n -> if n < 4 then out(opGETFIELD0 + n) else (out opGETFIELD; out_int n) + | Kgetmutablefield n -> + if n < 4 then out(opGETMUTABLEFIELD0 + n) else (out opGETMUTABLEFIELD; out_int n) | Ksetfield n -> if n < 4 then out(opSETFIELD0 + n) else (out opSETFIELD; out_int n) | Kmakefloatblock(n) -> @@ -300,6 +302,10 @@ let emit_instr = function | Kgetpubmet tag -> out opGETPUBMET; out_int tag; out_int 0 | Kgetdynmet -> out opGETDYNMET | Kevent ev -> record_event ev + | Kperform -> out opPERFORM + | Kresume -> out opRESUME + | Kresumeterm n -> out opRESUMETERM; out_int n + | Kreperformterm n -> out opREPERFORMTERM; out_int n | Kstop -> out opSTOP (* Emission of a list of instructions. Include some peephole optimization. *) diff --git a/bytecomp/instruct.ml b/bytecomp/instruct.ml index c684bedf99..6962fdffb4 100644 --- a/bytecomp/instruct.ml +++ b/bytecomp/instruct.ml @@ -72,6 +72,7 @@ type instruction = | Kmakeblock of int * int (* size, tag *) | Kmakefloatblock of int | Kgetfield of int + | Kgetmutablefield of int | Ksetfield of int | Kgetfloatfield of int | Ksetfloatfield of int @@ -104,6 +105,10 @@ type instruction = | Kgetpubmet of int | Kgetdynmet | Kevent of debug_event + | Kperform + | Kresume + | Kresumeterm of int + | Kreperformterm of int | Kstop let immed_min = -0x40000000 diff --git a/bytecomp/instruct.mli b/bytecomp/instruct.mli index e1cae776b0..9ed5f22f3e 100644 --- a/bytecomp/instruct.mli +++ b/bytecomp/instruct.mli @@ -92,6 +92,7 @@ type instruction = | Kmakeblock of int * int (* size, tag *) | Kmakefloatblock of int | Kgetfield of int + | Kgetmutablefield of int | Ksetfield of int | Kgetfloatfield of int | Ksetfloatfield of int @@ -124,6 +125,10 @@ type instruction = | Kgetpubmet of int | Kgetdynmet | Kevent of debug_event + | Kperform + | Kresume + | Kresumeterm of int + | Kreperformterm of int | Kstop val immed_min: int diff --git a/bytecomp/printinstr.ml b/bytecomp/printinstr.ml index 6b3754cbfc..384e623141 100644 --- a/bytecomp/printinstr.ml +++ b/bytecomp/printinstr.ml @@ -49,6 +49,7 @@ let instruction ppf = function | Kmakefloatblock(n) -> fprintf ppf "\tmakefloatblock %i" n | Kgetfield n -> fprintf ppf "\tgetfield %i" n + | Kgetmutablefield n -> fprintf ppf "\tgetmutablefield %i" n | Ksetfield n -> fprintf ppf "\tsetfield %i" n | Kgetfloatfield n -> fprintf ppf "\tgetfloatfield %i" n | Ksetfloatfield n -> fprintf ppf "\tsetfloatfield %i" n @@ -100,6 +101,10 @@ let instruction ppf = function | Kgetmethod -> fprintf ppf "\tgetmethod" | Kgetpubmet n -> fprintf ppf "\tgetpubmet %i" n | Kgetdynmet -> fprintf ppf "\tgetdynmet" + | Kperform -> fprintf ppf "\tperform" + | Kresume -> fprintf ppf "\tresume" + | Kresumeterm n -> fprintf ppf "\tresumeterm %i" n + | Kreperformterm n -> fprintf ppf "\treperformterm %i" n | Kstop -> fprintf ppf "\tstop" | Kevent ev -> fprintf ppf "\tevent \"%s\" %i-%i" ev.ev_loc.Location.loc_start.Lexing.pos_fname diff --git a/bytecomp/symtable.ml b/bytecomp/symtable.ml index 189604371a..5a56699c62 100644 --- a/bytecomp/symtable.ml +++ b/bytecomp/symtable.ml @@ -265,7 +265,7 @@ let update_global_table () = if ng > Array.length(Meta.global_data()) then Meta.realloc_global_data ng; let glob = Meta.global_data() in List.iter - (fun (slot, cst) -> glob.(slot) <- transl_const cst) + (fun (slot, cst) -> glob.(slot) <- Gc.promote_to (transl_const cst) ()) !literal_table; literal_table := [] @@ -331,7 +331,7 @@ let get_global_position id = slot_for_getglobal id let get_global_value id = (Meta.global_data()).(slot_for_getglobal id) let assign_global_value id v = - (Meta.global_data()).(slot_for_getglobal id) <- v + (Meta.global_data()).(slot_for_getglobal id) <- Gc.promote_to v () (* Check that all globals referenced in the given patch list have been initialized already *) diff --git a/compilerlibs/Makefile.compilerlibs b/compilerlibs/Makefile.compilerlibs index 8cdbf3b22b..94a191aec5 100644 --- a/compilerlibs/Makefile.compilerlibs +++ b/compilerlibs/Makefile.compilerlibs @@ -139,6 +139,7 @@ ASMCOMP=\ asmcomp/comballoc.cmo \ asmcomp/CSEgen.cmo asmcomp/CSE.cmo \ asmcomp/liveness.cmo \ + asmcomp/polling.cmo \ asmcomp/spill.cmo asmcomp/split.cmo \ asmcomp/interf.cmo asmcomp/coloring.cmo \ asmcomp/linscan.cmo \ diff --git a/config/auto-aux/cpp.c b/config/auto-aux/cpp.c new file mode 100644 index 0000000000..4cfbb4442e --- /dev/null +++ b/config/auto-aux/cpp.c @@ -0,0 +1,6 @@ +/* This file should preprocess to the string "ok", modulo whitespace */ +#if 0 +bad stuff +#else +ok +#endif @@ -56,7 +56,7 @@ if test -e '.git' ; then : fi fi # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for OCaml 4.12.0+dev0-2020-04-22. +# Generated by GNU Autoconf 2.69 for OCaml 4.12.0+multicore+dev0-2020-04-22. # # Report bugs to <caml-list@inria.fr>. # @@ -646,8 +646,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='OCaml' PACKAGE_TARNAME='ocaml' -PACKAGE_VERSION='4.12.0+dev0-2020-04-22' -PACKAGE_STRING='OCaml 4.12.0+dev0-2020-04-22' +PACKAGE_VERSION='4.12.0+multicore+dev0-2020-04-22' +PACKAGE_STRING='OCaml 4.12.0+multicore+dev0-2020-04-22' PACKAGE_BUGREPORT='caml-list@inria.fr' PACKAGE_URL='http://www.ocaml.org' @@ -825,6 +825,7 @@ outputobj outputexe unixlib unix_or_win32 +collect_stats systhread_support system model @@ -902,6 +903,7 @@ enable_call_counts enable_cfi enable_installing_source_artifacts enable_installing_bytecode_programs +enable_stats enable_native_compiler enable_flambda enable_flambda_invariants @@ -1480,7 +1482,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures OCaml 4.12.0+dev0-2020-04-22 to adapt to many kinds of systems. +\`configure' configures OCaml 4.12.0+multicore+dev0-2020-04-22 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1546,7 +1548,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of OCaml 4.12.0+dev0-2020-04-22:";; + short | recursive ) echo "Configuration of OCaml 4.12.0+multicore+dev0-2020-04-22:";; esac cat <<\_ACEOF @@ -1577,6 +1579,7 @@ Optional Features: install *.cmt* and *.mli files --enable-installing-bytecode-programs also install the bytecode versions of programs + --enable-stats enable multicore stats --disable-native-compiler do not build the native compiler --enable-flambda enable flambda optimizations @@ -1707,7 +1710,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -OCaml configure 4.12.0+dev0-2020-04-22 +OCaml configure 4.12.0+multicore+dev0-2020-04-22 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2370,7 +2373,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by OCaml $as_me 4.12.0+dev0-2020-04-22, which was +It was created by OCaml $as_me 4.12.0+multicore+dev0-2020-04-22, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2719,8 +2722,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: Configuring OCaml version 4.12.0+dev0-2020-04-22" >&5 -$as_echo "$as_me: Configuring OCaml version 4.12.0+dev0-2020-04-22" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: Configuring OCaml version 4.12.0+multicore+dev0-2020-04-22" >&5 +$as_echo "$as_me: Configuring OCaml version 4.12.0+multicore+dev0-2020-04-22" >&6;} # Configuration variables @@ -2796,7 +2799,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. -VERSION=4.12.0+dev0-2020-04-22 +VERSION=4.12.0+multicore+dev0-2020-04-22 # Note: This is present for the flexdll bootstrap where it exposed as the old @@ -2851,6 +2854,7 @@ VERSION=4.12.0+dev0-2020-04-22 + # TODO: rename this variable @@ -3067,11 +3071,12 @@ fi +# Disable instrumented-runtime with multicore # Check whether --enable-instrumented-runtime was given. if test "${enable_instrumented_runtime+set}" = set; then : enableval=$enable_instrumented_runtime; else - enable_instrumented_runtime=auto + enable_instrumented_runtime=no fi @@ -3180,6 +3185,12 @@ if test "${enable_installing_bytecode_programs+set}" = set; then : fi +# Check whether --enable-stats was given. +if test "${enable_stats+set}" = set; then : + enableval=$enable_stats; +fi + + # Check whether --enable-native-compiler was given. if test "${enable_native_compiler+set}" = set; then : enableval=$enable_native_compiler; @@ -12484,7 +12495,9 @@ case $ocaml_cv_cc_vendor in #( CPP="$CC -E -qnoppline" ;; #( # suppress incompatible XLC line directives msvc-*) : - CPP="$CC -nologo -EP" ;; #( + CPP="$CC -nologo -EP"; +# TODO: why can we not use $CPP in multicore, fix this? + CPP="$CC -E -P" ;; #( *) : ;; esac @@ -12605,8 +12618,8 @@ case $ocaml_cv_cc_vendor in #( cc_warnings='-Wall -Wdeclaration-after-statement' ;; esac -case $enable_warn_error,4.12.0+dev0-2020-04-22 in #( - yes,*|,*+dev*) : +case $enable_warn_error,4.12.0+multicore+dev0-2020-04-22 in #( + yes,*|,*+dev*|,*+multicore*) : cc_warnings="$cc_warnings $warn_error_flag" ;; #( *) : ;; @@ -13016,6 +13029,14 @@ fi +ac_fn_c_check_header_mongrel "$LINENO" "stdatomic.h" "ac_cv_header_stdatomic_h" "$ac_includes_default" +if test "x$ac_cv_header_stdatomic_h" = xyes; then : + $as_echo "#define HAS_STDATOMIC_H 1" >>confdefs.h + +fi + + + # Checks for types ## off_t @@ -16582,6 +16603,16 @@ else naked_pointers=true fi +## Collect multicore stats + +if test x"$enable_stats" = "xyes" ; then : + $as_echo "#define COLLECT_STATS 1" >>confdefs.h + + collect_stats=true +else + collect_stats=false +fi + ## Check for mmap support for huge pages and contiguous heap { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether mmap supports huge pages" >&5 @@ -16814,7 +16845,7 @@ else ocamldoc=ocamldoc fi -case $enable_ocamltest,4.12.0+dev0-2020-04-22 in #( +case $enable_ocamltest,4.12.0+multicore+dev0-2020-04-22 in #( yes,*|,*+dev*) : ocamltest='ocamltest' ;; #( *) : @@ -16931,7 +16962,7 @@ case $host in #( nativecclibs="advapi32.lib ws2_32.lib version.lib" ;; #( *) : bytecclibs="$cclibs $DLLIBS $pthread_link $instrumented_runtime_ldlibs" - nativecclibs="$cclibs $DLLIBS" ;; + nativecclibs="$cclibs $DLLIBS $pthread_link" ;; esac if test x"$libdir" = x'${exec_prefix}/lib'; then : @@ -17531,7 +17562,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by OCaml $as_me 4.12.0+dev0-2020-04-22, which was +This file was extended by OCaml $as_me 4.12.0+multicore+dev0-2020-04-22, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -17598,7 +17629,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -OCaml config.status 4.12.0+dev0-2020-04-22 +OCaml config.status 4.12.0+multicore+dev0-2020-04-22 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index cce3129fd5..b2dfbf93a2 100644 --- a/configure.ac +++ b/configure.ac @@ -88,6 +88,7 @@ AC_SUBST([arch64]) AC_SUBST([model]) AC_SUBST([system]) AC_SUBST([systhread_support]) +AC_SUBST([collect_stats]) AC_SUBST([unix_or_win32]) AC_SUBST([unixlib]) AC_SUBST([outputexe]) @@ -222,11 +223,12 @@ AC_ARG_ENABLE([dependency-generation], AC_ARG_VAR([DLLIBS], [which libraries to use (in addition to -ldl) to load dynamic libs]) +# Disable instrumented-runtime with multicore AC_ARG_ENABLE([instrumented-runtime], [AS_HELP_STRING([--enable-instrumented-runtime], [build the instrumented runtime @<:@default=auto@:>@])], [], - [enable_instrumented_runtime=auto]) + [enable_instrumented_runtime=no]) AC_ARG_ENABLE([vmthreads], [], [AC_MSG_ERROR([The vmthreads library is no longer available. \ @@ -302,6 +304,10 @@ AC_ARG_ENABLE([installing-bytecode-programs], [AS_HELP_STRING([--enable-installing-bytecode-programs], [also install the bytecode versions of programs])]) +AC_ARG_ENABLE([stats], + [AS_HELP_STRING([--enable-stats], + [enable multicore stats])]) + AC_ARG_ENABLE([native-compiler], [AS_HELP_STRING([--disable-native-compiler], [do not build the native compiler])]) @@ -478,7 +484,9 @@ AS_CASE([$ocaml_cv_cc_vendor], [xlc-*], [CPP="$CC -E -qnoppline"], # suppress incompatible XLC line directives [msvc-*], - [CPP="$CC -nologo -EP"]) + [CPP="$CC -nologo -EP"]; +# TODO: why can we not use $CPP in multicore, fix this? + [CPP="$CC -E -P"]) # Libraries to build depending on the host @@ -558,7 +566,7 @@ AS_CASE([$ocaml_cv_cc_vendor], cc_warnings='-Wall -Wdeclaration-after-statement']) AS_CASE([$enable_warn_error,AC_PACKAGE_VERSION], - [yes,*|,*+dev*], + [yes,*|,*+dev*|,*+multicore*], [cc_warnings="$cc_warnings $warn_error_flag"]) # We select high optimization levels, provided we can turn off: @@ -746,6 +754,8 @@ AC_CHECK_HEADER([dirent.h], [AC_DEFINE([HAS_DIRENT])], [], AC_CHECK_HEADER([sys/select.h], [AC_DEFINE([HAS_SYS_SELECT_H])], [], [#include <sys/types.h>]) +AC_CHECK_HEADER([stdatomic.h], [AC_DEFINE([HAS_STDATOMIC_H])]) + # Checks for types ## off_t @@ -1676,6 +1686,13 @@ AS_IF([test x"$enable_naked_pointers" = "xno" ], AC_DEFINE([NO_NAKED_POINTERS])], [naked_pointers=true]) +## Collect multicore stats + +AS_IF([test x"$enable_stats" = "xyes" ], + [AC_DEFINE([COLLECT_STATS]) + collect_stats=true], + [collect_stats=false]) + ## Check for mmap support for huge pages and contiguous heap OCAML_MMAP_SUPPORTS_HUGE_PAGES @@ -1855,7 +1872,7 @@ AS_CASE([$host], [bytecclibs="advapi32.lib ws2_32.lib version.lib" nativecclibs="advapi32.lib ws2_32.lib version.lib"], [bytecclibs="$cclibs $DLLIBS $pthread_link $instrumented_runtime_ldlibs" - nativecclibs="$cclibs $DLLIBS"]) + nativecclibs="$cclibs $DLLIBS $pthread_link"]) AS_IF([test x"$libdir" = x'${exec_prefix}/lib'], [libdir="$libdir"/ocaml]) diff --git a/flexdll b/flexdll deleted file mode 160000 -Subproject b6b231493387a7628103dc744b3bcd3d413c80d diff --git a/lambda/lambda.ml b/lambda/lambda.ml index 3cc7bd1131..926b6a0f7d 100644 --- a/lambda/lambda.ml +++ b/lambda/lambda.ml @@ -51,14 +51,18 @@ type primitive = | Psetglobal of Ident.t (* Operations on heap blocks *) | Pmakeblock of int * mutable_flag * block_shape - | Pfield of int + | Pfield of int * immediate_or_pointer * mutable_flag | Pfield_computed | Psetfield of int * immediate_or_pointer * initialization_or_assignment | Psetfield_computed of immediate_or_pointer * initialization_or_assignment | Pfloatfield of int | Psetfloatfield of int * initialization_or_assignment | Pduprecord of Types.record_representation * int - (* Force lazy values *) + (* Context switches *) + | Prunstack + | Pperform + | Presume + | Preperform (* External call *) | Pccall of Primitive.description (* Exceptions *) @@ -141,8 +145,17 @@ type primitive = | Pbbswap of boxed_integer (* Integer to external pointer *) | Pint_as_pointer + (* Atomic operations *) + | Patomic_load of {immediate_or_pointer : immediate_or_pointer} + | Patomic_exchange + | Patomic_cas + | Patomic_fetch_add (* Inhibition of optimisation *) | Popaque + (* Polling for interrupts *) + | Ppoll + (* nop instruction for debugging *) + | Pnop and integer_comparison = Ceq | Cne | Clt | Cgt | Cle | Cge @@ -641,7 +654,8 @@ let rec transl_address loc = function then Lprim(Pgetglobal id, [], loc) else Lvar id | Env.Adot(addr, pos) -> - Lprim(Pfield pos, [transl_address loc addr], loc) + Lprim(Pfield(pos, Pointer, Immutable), + [transl_address loc addr], loc) let transl_path find loc env path = match find path env with diff --git a/lambda/lambda.mli b/lambda/lambda.mli index 66077aa8ba..b3b71f5aa3 100644 --- a/lambda/lambda.mli +++ b/lambda/lambda.mli @@ -57,13 +57,18 @@ type primitive = | Psetglobal of Ident.t (* Operations on heap blocks *) | Pmakeblock of int * mutable_flag * block_shape - | Pfield of int + | Pfield of int * immediate_or_pointer * mutable_flag | Pfield_computed | Psetfield of int * immediate_or_pointer * initialization_or_assignment | Psetfield_computed of immediate_or_pointer * initialization_or_assignment | Pfloatfield of int | Psetfloatfield of int * initialization_or_assignment | Pduprecord of Types.record_representation * int + (* Context switches *) + | Prunstack + | Pperform + | Presume + | Preperform (* External call *) | Pccall of Primitive.description (* Exceptions *) @@ -150,8 +155,17 @@ type primitive = | Pbbswap of boxed_integer (* Integer to external pointer *) | Pint_as_pointer + (* Atomic operations *) + | Patomic_load of {immediate_or_pointer : immediate_or_pointer} + | Patomic_exchange + | Patomic_cas + | Patomic_fetch_add (* Inhibition of optimisation *) | Popaque + (* Polling for interrupts *) + | Ppoll + (* nop instruction for debugging *) + | Pnop and integer_comparison = Ceq | Cne | Clt | Cgt | Cle | Cge diff --git a/lambda/matching.ml b/lambda/matching.ml index 45803f6ca9..e73c0f1d5d 100644 --- a/lambda/matching.ml +++ b/lambda/matching.ml @@ -1679,7 +1679,7 @@ let get_expr_args_constr ~scopes head (arg, _mut) rem = if pos > last_pos then argl else - (Lprim (Pfield pos, [ arg ], loc), binding_kind) :: make_args (pos + 1) + (Lprim (Pfield (pos, Pointer, Immutable), [ arg ], loc), binding_kind) :: make_args (pos + 1) in make_args first_pos in @@ -1707,7 +1707,7 @@ let get_expr_args_variant_constant = drop_expr_arg let get_expr_args_variant_nonconst ~scopes head (arg, _mut) rem = let loc = head_loc ~scopes head in - (Lprim (Pfield 1, [ arg ], loc), Alias) :: rem + (Lprim (Pfield (1, Pointer, Immutable), [ arg ], loc), Alias) :: rem let divide_variant ~scopes row ctx { cases = cl; args; default = def } = let row = Btype.row_repr row in @@ -1798,7 +1798,7 @@ let code_force_lazy = get_mod_field "CamlinternalLazy" "force" (* inline_lazy_force inlines the beginning of the code of Lazy.force. When the value argument is tagged as: - forward, take field 0 - - lazy, call the primitive that forces (without testing again the tag) + - lazy || forcing, call the primitive that forces - anything else, return it Using Lswitch below relies on the fact that the GC does not shortcut @@ -1809,8 +1809,11 @@ let inline_lazy_force_cond arg loc = let idarg = Ident.create_local "lzarg" in let varg = Lvar idarg in let tag = Ident.create_local "tag" in - let tag_var = Lvar tag in let force_fun = Lazy.force code_force_lazy_block in + let test_tag t = + Lprim(Pintcomp Ceq, [Lvar tag; Lconst(Const_base(Const_int t))], loc) + in + Llet ( Strict, Pgenval, @@ -1822,18 +1825,16 @@ let inline_lazy_force_cond arg loc = tag, Lprim (Pccall prim_obj_tag, [ varg ], loc), Lifthenelse - (* if (tag == Obj.forward_tag) then varg.(0) else ... *) - ( Lprim - ( Pintcomp Ceq, - [ tag_var; Lconst (Const_base (Const_int Obj.forward_tag)) ], - loc ), - Lprim (Pfield 0, [ varg ], loc), + ( (* if (tag == Obj.forward_tag) then varg.(0) else ... *) + test_tag Obj.forward_tag, + Lprim (Pfield (0, Pointer, Mutable), [ varg ], loc), Lifthenelse - (* if (tag == Obj.lazy_tag) then Lazy.force varg else ... *) - ( Lprim - ( Pintcomp Ceq, - [ tag_var; Lconst (Const_base (Const_int Obj.lazy_tag)) ], - loc ), + ( + (* ... if tag == Obj.lazy_tag || tag == Obj.forcing_tag then + Lazy.force varg + else ... *) + Lprim (Psequor, + [test_tag Obj.lazy_tag; test_tag Obj.forcing_tag], loc), Lapply { ap_tailcall = Default_tailcall; ap_loc = loc; @@ -1864,8 +1865,20 @@ let inline_lazy_force_switch arg loc = sw_numblocks = 256; (* PR#6033 - tag ranges from 0 to 255 *) sw_blocks = - [ (Obj.forward_tag, Lprim (Pfield 0, [ varg ], loc)); - ( Obj.lazy_tag, + [ (Obj.forward_tag, Lprim (Pfield(0, Pointer, Mutable), + [ varg ], loc)); + + (Obj.lazy_tag, + Lapply + { ap_tailcall = Default_tailcall; + ap_loc = loc; + ap_func = force_fun; + ap_args = [varg]; + ap_inlined = Default_inline; + ap_specialised = Default_specialise + } ); + + (Obj.forcing_tag, Lapply { ap_tailcall = Default_tailcall; ap_loc = loc; @@ -1926,7 +1939,7 @@ let get_expr_args_tuple ~scopes head (arg, _mut) rem = if pos >= arity then rem else - (Lprim (Pfield pos, [ arg ], loc), Alias) :: make_args (pos + 1) + (Lprim (Pfield (pos, Pointer, Immutable), [ arg ], loc), Alias) :: make_args (pos + 1) in make_args 0 @@ -1966,14 +1979,16 @@ let get_expr_args_record ~scopes head (arg, _mut) rem = rem else let lbl = all_labels.(pos) in + let ptr = Typeopt.maybe_pointer_type head.pat_env lbl.lbl_arg in let access = match lbl.lbl_repres with | Record_regular | Record_inlined _ -> - Lprim (Pfield lbl.lbl_pos, [ arg ], loc) + Lprim (Pfield (lbl.lbl_pos, ptr, lbl.lbl_mut), [ arg ], loc) | Record_unboxed _ -> arg | Record_float -> Lprim (Pfloatfield lbl.lbl_pos, [ arg ], loc) - | Record_extension _ -> Lprim (Pfield (lbl.lbl_pos + 1), [ arg ], loc) + | Record_extension _ -> + Lprim (Pfield (lbl.lbl_pos + 1, ptr, lbl.lbl_mut), [ arg ], loc) in let str = match lbl.lbl_mut with @@ -2708,7 +2723,8 @@ let combine_constructor loc arg pat_env cstr partial ctx def (Lprim (Pintcomp Ceq, [ Lvar tag; ext ], loc), act, rem)) nonconsts default in - Llet (Alias, Pgenval, tag, Lprim (Pfield 0, [ arg ], loc), tests) + Llet (Alias, Pgenval, tag, + Lprim (Pfield (0, Pointer, Immutable), [ arg ], loc), tests) in List.fold_right (fun (path, act) rem -> @@ -2798,7 +2814,7 @@ let call_switcher_variant_constr loc fail arg int_lambda_list = ( Alias, Pgenval, v, - Lprim (Pfield 0, [ arg ], loc), + Lprim (Pfield (0, Pointer, Immutable), [ arg ], loc), call_switcher loc fail (Lvar v) min_int max_int int_lambda_list ) let combine_variant loc row arg partial ctx def (tag_lambda_list, total1, _pats) @@ -3328,9 +3344,12 @@ let check_partial pat_act_list = type failer_kind = | Raise_match_failure | Reraise_noloc of lambda + | Reperform_noloc of lambda list let failure_handler ~scopes loc ~failer () = match failer with + | Reperform_noloc reperform_lst -> + Lprim (Preperform, reperform_lst, Loc_unknown) | Reraise_noloc exn_lam -> Lprim (Praise Raise_reraise, [ exn_lam ], Scoped_location.Loc_unknown) | Raise_match_failure -> @@ -3412,6 +3431,11 @@ let for_trywith ~scopes loc param pat_act_list = compile_matching ~scopes loc ~failer:(Reraise_noloc param) None param pat_act_list Partial +let for_handler ~scopes loc param cont cont_tail pat_act_list = + compile_matching ~scopes loc + ~failer:(Reperform_noloc [param; cont; cont_tail]) + None param pat_act_list Partial + let simple_for_let ~scopes loc param pat body = compile_matching ~scopes loc ~failer:Raise_match_failure None param [ (pat, body) ] Partial diff --git a/lambda/matching.mli b/lambda/matching.mli index 3178fe2fa9..7c1264b9b2 100644 --- a/lambda/matching.mli +++ b/lambda/matching.mli @@ -28,6 +28,10 @@ val for_trywith: scopes:scopes -> Location.t -> lambda -> (pattern * lambda) list -> lambda +val for_handler: + scopes:scopes -> Location.t -> + lambda -> lambda -> lambda -> (pattern * lambda) list -> + lambda val for_let: scopes:scopes -> Location.t -> lambda -> pattern -> lambda -> diff --git a/lambda/printlambda.ml b/lambda/printlambda.ml index 7394c1ffa8..ec8432db19 100644 --- a/lambda/printlambda.ml +++ b/lambda/printlambda.ml @@ -159,7 +159,14 @@ let primitive ppf = function fprintf ppf "makeblock %i%a" tag block_shape shape | Pmakeblock(tag, Mutable, shape) -> fprintf ppf "makemutable %i%a" tag block_shape shape - | Pfield n -> fprintf ppf "field %i" n + | Pfield(n, ptr, mut) -> + let instr = + match ptr, mut with + | Immediate, _ -> "field_int " + | Pointer, Mutable -> "field_mut " + | Pointer, Immutable -> "field_imm " + in + fprintf ppf "%s%i" instr n | Pfield_computed -> fprintf ppf "field_computed" | Psetfield(n, ptr, init) -> let instr = @@ -197,6 +204,10 @@ let primitive ppf = function in fprintf ppf "setfloatfield%s %i" init n | Pduprecord (rep, size) -> fprintf ppf "duprecord %a %i" record_rep rep size + | Prunstack -> fprintf ppf "runstack" + | Pperform -> fprintf ppf "perform" + | Presume -> fprintf ppf "resume" + | Preperform -> fprintf ppf "reperform" | Pccall p -> fprintf ppf "%s" p.prim_name | Praise k -> fprintf ppf "%s" (Lambda.raise_kind k) | Psequand -> fprintf ppf "&&" @@ -269,14 +280,14 @@ let primitive ppf = function | Paddbint bi -> print_boxed_integer "add" ppf bi | Psubbint bi -> print_boxed_integer "sub" ppf bi | Pmulbint bi -> print_boxed_integer "mul" ppf bi - | Pdivbint { size = bi; is_safe = Safe } -> - print_boxed_integer "div" ppf bi - | Pdivbint { size = bi; is_safe = Unsafe } -> - print_boxed_integer "div_unsafe" ppf bi - | Pmodbint { size = bi; is_safe = Safe } -> - print_boxed_integer "mod" ppf bi - | Pmodbint { size = bi; is_safe = Unsafe } -> - print_boxed_integer "mod_unsafe" ppf bi + | Pdivbint { size; is_safe = Safe } -> + print_boxed_integer "div" ppf size + | Pdivbint { size; is_safe = Unsafe } -> + print_boxed_integer "div_unsafe" ppf size + | Pmodbint { size; is_safe = Safe } -> + print_boxed_integer "mod" ppf size + | Pmodbint { size; is_safe = Unsafe } -> + print_boxed_integer "mod_unsafe" ppf size | Pandbint bi -> print_boxed_integer "and" ppf bi | Porbint bi -> print_boxed_integer "or" ppf bi | Pxorbint bi -> print_boxed_integer "xor" ppf bi @@ -342,7 +353,16 @@ let primitive ppf = function | Pbswap16 -> fprintf ppf "bswap16" | Pbbswap(bi) -> print_boxed_integer "bswap" ppf bi | Pint_as_pointer -> fprintf ppf "int_as_pointer" + | Patomic_load {immediate_or_pointer} -> + (match immediate_or_pointer with + | Immediate -> fprintf ppf "atomic_load_imm" + | Pointer -> fprintf ppf "atomic_load_ptr") + | Patomic_exchange -> fprintf ppf "atomic_exchange" + | Patomic_cas -> fprintf ppf "atomic_cas" + | Patomic_fetch_add -> fprintf ppf "atomic_fetch_add" | Popaque -> fprintf ppf "opaque" + | Ppoll -> fprintf ppf "poll" + | Pnop -> fprintf ppf "nop" let name_of_primitive = function | Pidentity -> "Pidentity" @@ -448,7 +468,20 @@ let name_of_primitive = function | Pbswap16 -> "Pbswap16" | Pbbswap _ -> "Pbbswap" | Pint_as_pointer -> "Pint_as_pointer" + | Patomic_load {immediate_or_pointer} -> + (match immediate_or_pointer with + | Immediate -> "atomic_load_imm" + | Pointer -> "atomic_load_ptr") + | Patomic_exchange -> "Patomic_exchange" + | Patomic_cas -> "Patomic_cas" + | Patomic_fetch_add -> "Patomic_fetch_add" | Popaque -> "Popaque" + | Prunstack -> "Prunstack" + | Presume -> "Presume" + | Pperform -> "Pperform" + | Preperform -> "Preperform" + | Ppoll -> "Ppoll" + | Pnop -> "Pnop" let function_attribute ppf { inline; specialise; local; is_a_functor; stub } = if is_a_functor then diff --git a/lambda/simplif.ml b/lambda/simplif.ml index a7e4141bde..e6a1c4d240 100644 --- a/lambda/simplif.ml +++ b/lambda/simplif.ml @@ -40,7 +40,7 @@ let rec eliminate_ref id = function | Lletrec(idel, e2) -> Lletrec(List.map (fun (v, e) -> (v, eliminate_ref id e)) idel, eliminate_ref id e2) - | Lprim(Pfield 0, [Lvar v], _) when Ident.same v id -> + | Lprim(Pfield (0, _, _), [Lvar v], _) when Ident.same v id -> Lvar id | Lprim(Psetfield(0, _, _), [Lvar v; e], _) when Ident.same v id -> Lassign(id, eliminate_ref id e) diff --git a/lambda/translclass.ml b/lambda/translclass.ml index a465579811..fc3a7f4723 100644 --- a/lambda/translclass.ml +++ b/lambda/translclass.ml @@ -62,7 +62,8 @@ let mkappl (func, args) = let lsequence l1 l2 = if l2 = lambda_unit then l1 else Lsequence(l1, l2) -let lfield v i = Lprim(Pfield i, [Lvar v], Loc_unknown) +let lfield v i = Lprim(Pfield (i, Pointer, Mutable), + [Lvar v], Loc_unknown) let transl_label l = share (Const_immstring l) @@ -133,7 +134,7 @@ let rec build_object_init ~scopes cl_table obj params inh_init obj_init cl = let env = match envs with None -> [] | Some envs -> - [Lprim(Pfield (List.length inh_init + 1), + [Lprim(Pfield (List.length inh_init + 1, Pointer, Mutable), [Lvar envs], Loc_unknown)] in @@ -278,8 +279,10 @@ let rec build_class_init ~scopes cla cstr super inh_init cl_init msubst top cl = | (_, path_lam, obj_init)::inh_init -> (inh_init, Llet (Strict, Pgenval, obj_init, - mkappl(Lprim(Pfield 1, [path_lam], Loc_unknown), Lvar cla :: - if top then [Lprim(Pfield 3, [path_lam], Loc_unknown)] + mkappl(Lprim(Pfield (1, Pointer, Mutable), + [path_lam], Loc_unknown), Lvar cla :: + if top then [Lprim(Pfield (3, Pointer, Mutable), + [path_lam], Loc_unknown)] else []), bind_super cla super cl_init)) | _ -> @@ -551,7 +554,7 @@ let rec builtin_meths self env env2 body = | p when const_path p -> "const", [p] | Lprim(Parrayrefu _, [Lvar s; Lvar n], _) when List.mem s self -> "var", [Lvar n] - | Lprim(Pfield n, [Lvar e], _) when Ident.same e env -> + | Lprim(Pfield(n, _, _), [Lvar e], _) when Ident.same e env -> "env", [Lvar env2; Lconst(const_int n)] | Lsend(Self, met, Lvar s, [], _) when List.mem s self -> "meth", [met] @@ -847,7 +850,8 @@ let transl_class ~scopes ids cl_id pub_meths cl vflag = Loc_unknown) and linh_envs = List.map - (fun (_, path_lam, _) -> Lprim(Pfield 3, [path_lam], Loc_unknown)) + (fun (_, path_lam, _) -> + Lprim(Pfield (3, Pointer, Mutable), [path_lam], Loc_unknown)) (List.rev inh_init) in let make_envs lam = @@ -867,7 +871,8 @@ let transl_class ~scopes ids cl_id pub_meths cl vflag = in let inh_keys = List.map - (fun (_, path_lam, _) -> Lprim(Pfield 1, [path_lam], Loc_unknown)) + (fun (_, path_lam, _) -> + Lprim(Pfield (1, Pointer, Mutable), [path_lam], Loc_unknown)) inh_paths in let lclass lam = diff --git a/lambda/translcore.ml b/lambda/translcore.ml index edf66f255f..da00a410d7 100644 --- a/lambda/translcore.ml +++ b/lambda/translcore.ml @@ -94,7 +94,7 @@ let rec push_defaults loc bindings cases partial = c_rhs={exp_desc = Texp_function { arg_label; param; cases; partial; } } as exp}] -> let cases = push_defaults exp.exp_loc bindings cases partial in - [{c_lhs=pat; c_guard=None; + [{c_lhs=pat; c_guard=None; c_cont=None; c_rhs={exp with exp_desc = Texp_function { arg_label; param; cases; partial; }}}] | [{c_lhs=pat; c_guard=None; @@ -102,7 +102,7 @@ let rec push_defaults loc bindings cases partial = exp_desc = Texp_let (Nonrecursive, binds, ({exp_desc = Texp_function _} as e2))}}] -> push_defaults loc (Bind_value binds :: bindings) - [{c_lhs=pat;c_guard=None;c_rhs=e2}] + [{c_lhs=pat; c_cont=None; c_guard=None; c_rhs=e2}] partial | [{c_lhs=pat; c_guard=None; c_rhs={exp_attributes=[{Parsetree.attr_name = {txt="#modulepat"};_}]; @@ -110,7 +110,7 @@ let rec push_defaults loc bindings cases partial = (Some id, name, pres, mexpr, ({exp_desc = Texp_function _} as e2))}}] -> push_defaults loc (Bind_module (id, name, pres, mexpr) :: bindings) - [{c_lhs=pat;c_guard=None;c_rhs=e2}] + [{c_lhs=pat;c_cont=None;c_guard=None;c_rhs=e2}] partial | [case] -> let exp = @@ -143,11 +143,11 @@ let rec push_defaults loc bindings cases partial = ({exp with exp_type = pat.pat_type; exp_env = env; exp_desc = Texp_ident (Path.Pident param, mknoloc (Longident.Lident name), desc)}, - cases, partial) } + cases, [], partial) } in push_defaults loc bindings [{c_lhs={pat with pat_desc = Tpat_var (param, mknoloc name)}; - c_guard=None; c_rhs=exp}] + c_cont=None; c_guard=None; c_rhs=exp}] Total | _ -> cases @@ -287,13 +287,35 @@ and transl_exp0 ~scopes e = event_after ~scopes e (transl_apply ~scopes ~tailcall ~inlined ~specialised (transl_exp ~scopes funct) oargs (of_location ~scopes e.exp_loc)) - | Texp_match(arg, pat_expr_list, partial) -> + | Texp_match(arg, pat_expr_list, [], partial) -> transl_match ~scopes e arg pat_expr_list partial - | Texp_try(body, pat_expr_list) -> + | Texp_match(arg, pat_expr_list, eff_pat_expr_list, partial) -> + (* need to separate the values from exceptions for tansl_handler *) + let split_case (val_cases, exn_cases as acc) + ({ c_lhs; c_rhs } as case) = + if c_rhs.exp_desc = Texp_unreachable then acc else + let val_pat, exn_pat = split_pattern c_lhs in + match val_pat, exn_pat with + | None, None -> assert false + | Some pv, None -> + { case with c_lhs = pv } :: val_cases, exn_cases + | None, Some pe -> + val_cases, { case with c_lhs = pe } :: exn_cases + | Some _pv, Some _pe -> + assert false (* FIXME: handle this case *) + in + let pat_expr_list, exn_pat_expr_list = + let x, y = List.fold_left split_case ([], []) pat_expr_list in + List.rev x, List.rev y + in + transl_handler ~scopes e arg (Some (pat_expr_list, partial)) exn_pat_expr_list eff_pat_expr_list + | Texp_try(body, pat_expr_list, []) -> let id = Typecore.name_cases "exn" pat_expr_list in Ltrywith(transl_exp ~scopes body, id, Matching.for_trywith ~scopes e.exp_loc (Lvar id) (transl_cases_try ~scopes pat_expr_list)) + | Texp_try(body, exn_pat_expr_list, eff_pat_expr_list) -> + transl_handler ~scopes e body None exn_pat_expr_list eff_pat_expr_list | Texp_tuple el -> let ll, shape = transl_list_with_shape ~scopes el in begin try @@ -350,14 +372,14 @@ and transl_exp0 ~scopes e = let targ = transl_exp ~scopes arg in begin match lbl.lbl_repres with Record_regular | Record_inlined _ -> - Lprim (Pfield lbl.lbl_pos, [targ], + Lprim (Pfield (lbl.lbl_pos, maybe_pointer e, lbl.lbl_mut), [targ], of_location ~scopes e.exp_loc) | Record_unboxed _ -> targ | Record_float -> Lprim (Pfloatfield lbl.lbl_pos, [targ], of_location ~scopes e.exp_loc) | Record_extension _ -> - Lprim (Pfield (lbl.lbl_pos + 1), [targ], + Lprim (Pfield (lbl.lbl_pos + 1, maybe_pointer e, lbl.lbl_mut), [targ], of_location ~scopes e.exp_loc) end | Texp_setfield(arg, _, lbl, newval) -> @@ -457,7 +479,8 @@ and transl_exp0 ~scopes e = Lapply{ ap_loc=loc; ap_func= - Lprim(Pfield 0, [transl_class_path loc e.exp_env cl], loc); + Lprim(Pfield (0, Pointer, Mutable), + [transl_class_path loc e.exp_env cl], loc); ap_args=[lambda_unit]; ap_tailcall=Default_tailcall; ap_inlined=Default_inline; @@ -591,7 +614,7 @@ and transl_exp0 ~scopes e = let body, _ = List.fold_left (fun (body, pos) id -> Llet(Alias, Pgenval, id, - Lprim(Pfield pos, [Lvar oid], + Lprim(Pfield (pos, Pointer, Mutable), [Lvar oid], of_location ~scopes od.open_loc), body), pos + 1 ) (transl_exp ~scopes e, 0) @@ -625,13 +648,20 @@ and transl_guard ~scopes guard rhs = event_before ~scopes cond (Lifthenelse(transl_exp ~scopes cond, expr, staticfail)) -and transl_case ~scopes {c_lhs; c_guard; c_rhs} = - c_lhs, transl_guard ~scopes c_guard c_rhs +and transl_cont cont c_cont body = + match cont, c_cont with + | Some id1, Some id2 -> Llet(Alias, Pgenval, id2, Lvar id1, body) + | None, None + | Some _, None -> body + | None, Some _ -> assert false + +and transl_case ~scopes ?cont {c_lhs; c_cont; c_guard; c_rhs} = + c_lhs, transl_cont cont c_cont (transl_guard ~scopes c_guard c_rhs) -and transl_cases ~scopes cases = +and transl_cases ~scopes ?cont cases = let cases = List.filter (fun c -> c.c_rhs.exp_desc <> Texp_unreachable) cases in - List.map (transl_case ~scopes) cases + List.map (transl_case ~scopes ?cont) cases and transl_case_try ~scopes {c_lhs; c_guard; c_rhs} = iter_exn_names Translprim.add_exception_ident c_lhs; @@ -898,13 +928,15 @@ and transl_record ~scopes loc env fields repres opt_init_expr = Array.mapi (fun i (_, definition) -> match definition with - | Kept typ -> + | Kept (typ, mut) -> let field_kind = value_kind env typ in let access = match repres with - Record_regular | Record_inlined _ -> Pfield i + Record_regular | Record_inlined _ -> + Pfield (i, maybe_pointer_type env typ, mut) | Record_unboxed _ -> assert false - | Record_extension _ -> Pfield (i + 1) + | Record_extension _ -> + Pfield (i + 1, maybe_pointer_type env typ, mut) | Record_float -> Pfloatfield i in Lprim(access, [Lvar init_id], of_location ~scopes loc), @@ -956,7 +988,7 @@ and transl_record ~scopes loc env fields repres opt_init_expr = let copy_id = Ident.create_local "newrecord" in let update_field cont (lbl, definition) = match definition with - | Kept _type -> cont + | Kept _ -> cont | Overridden (_lid, expr) -> let upd = match repres with @@ -1073,6 +1105,71 @@ and transl_match ~scopes e arg pat_expr_list partial = Lstaticcatch (body, (static_exception_id, val_ids), handler) ) classic static_handlers +and prim_alloc_stack = + Pccall (Primitive.simple ~name:"caml_alloc_stack" ~arity:3 ~alloc:true) + +and transl_handler ~scopes e body val_caselist exn_caselist eff_caselist = + let val_fun = + match val_caselist with + | None -> + let param = Ident.create_local "param" in + Lfunction {kind = Curried; params = [param, Pgenval]; + return = Pgenval; + attr = default_function_attribute; loc = Loc_unknown; + body = Lvar param } + | Some (val_caselist, partial) -> + let val_cases = transl_cases ~scopes val_caselist in + let param = Typecore.name_cases "param" val_caselist in + Lfunction { kind = Curried; params = [param, Pgenval]; + return = Pgenval; + attr = default_function_attribute; loc = Loc_unknown; + body = Matching.for_function ~scopes e.exp_loc None + (Lvar param) val_cases partial } + in + let exn_fun = + let exn_cases = transl_cases ~scopes exn_caselist in + let param = Typecore.name_cases "exn" exn_caselist in + Lfunction { kind = Curried; params = [param, Pgenval]; + return = Pgenval; + attr = default_function_attribute; loc = Loc_unknown; + body = Matching.for_trywith ~scopes e.exp_loc (Lvar param) exn_cases } + in + let eff_fun = + let param = Typecore.name_cases "eff" eff_caselist in + let cont = Ident.create_local "k" in + let cont_tail = Ident.create_local "ktail" in + let eff_cases = transl_cases ~scopes ~cont eff_caselist in + Lfunction { kind = Curried; + params = [(param, Pgenval); (cont, Pgenval); (cont_tail, Pgenval)]; + return = Pgenval; + attr = default_function_attribute; loc = Loc_unknown; + body = Matching.for_handler ~scopes e.exp_loc (Lvar param) + (Lvar cont) (Lvar cont_tail) eff_cases } + in + let is_pure = function + | Lconst _ -> true + | Lvar _ -> true + | Lfunction _ -> true + | _ -> false + in + let (body_fun, arg) = + match transl_exp ~scopes body with + | Lapply { ap_func = fn; ap_args = [arg]; _ } + when is_pure fn && is_pure arg -> (fn, arg) + | body -> + let param = Ident.create_local "param" in + (Lfunction { kind = Curried; params = [param, Pgenval]; + return = Pgenval; + attr = default_function_attribute; loc = Loc_unknown; + body }, + Lconst(Const_base(Const_int 0))) + in + let alloc_stack = + Lprim(prim_alloc_stack, [val_fun; exn_fun; eff_fun], Loc_unknown) + in + Lprim(Prunstack, [alloc_stack; body_fun; arg], + of_location ~scopes e.exp_loc) + and transl_letop ~scopes loc env let_ ands param case partial = let rec loop prev_lam = function | [] -> prev_lam diff --git a/lambda/translmod.ml b/lambda/translmod.ml index 9e7756374c..db04c00392 100644 --- a/lambda/translmod.ml +++ b/lambda/translmod.ml @@ -83,7 +83,7 @@ let rec apply_coercion loc strict restr arg = name_lambda strict arg (fun id -> let get_field pos = if pos < 0 then lambda_unit - else Lprim(Pfield pos,[Lvar id], loc) + else Lprim(Pfield (pos, Pointer, Mutable), [Lvar id], loc) in let lam = Lprim(Pmakeblock(0, Immutable, None), @@ -631,6 +631,15 @@ and transl_structure ~scopes loc fields cc rootpath final_env = function path ext.tyexn_constructor, body), size + | Tstr_effect ext -> + let id = ext.ext_id in + let path = field_path rootpath id in + let body, size = + transl_structure ~scopes loc (id :: fields) cc rootpath final_env rem + in + Llet(Strict, Pgenval, id, + transl_extension_constructor ~scopes item.str_env path ext, body), + size | Tstr_module ({mb_presence=Mp_present} as mb) -> let id = mb.mb_id in (* Translate module first *) @@ -714,8 +723,8 @@ and transl_structure ~scopes loc fields cc rootpath final_env = function rebind_idents (pos + 1) (id :: newfields) ids in Llet(Alias, Pgenval, id, - Lprim(Pfield pos, [Lvar mid], - of_location ~scopes incl.incl_loc), body), + Lprim(Pfield (pos, Pointer, Mutable), + [Lvar mid], of_location ~scopes incl.incl_loc), body), size in let body, size = rebind_idents 0 fields ids in @@ -743,7 +752,7 @@ and transl_structure ~scopes loc fields cc rootpath final_env = function rebind_idents (pos + 1) (id :: newfields) ids in Llet(Alias, Pgenval, id, - Lprim(Pfield pos, [Lvar mid], + Lprim(Pfield (pos, Pointer, Mutable), [Lvar mid], of_location ~scopes od.open_loc), body), size in @@ -838,6 +847,7 @@ let rec defined_idents = function | Tstr_typext tyext -> List.map (fun ext -> ext.ext_id) tyext.tyext_constructors @ defined_idents rem + | Tstr_effect ext -> ext.ext_id :: defined_idents rem | Tstr_exception ext -> ext.tyexn_constructor.ext_id :: defined_idents rem | Tstr_module {mb_id = Some id; mb_presence=Mp_present} -> id :: defined_idents rem @@ -867,6 +877,7 @@ let rec more_idents = function | Tstr_type _ -> more_idents rem | Tstr_typext _ -> more_idents rem | Tstr_exception _ -> more_idents rem + | Tstr_effect _ -> more_idents rem | Tstr_recmodule _ -> more_idents rem | Tstr_modtype _ -> more_idents rem | Tstr_open od -> @@ -904,6 +915,7 @@ and all_idents = function | Tstr_typext tyext -> List.map (fun ext -> ext.ext_id) tyext.tyext_constructors @ all_idents rem + | Tstr_effect ext -> ext.ext_id :: all_idents rem | Tstr_exception ext -> ext.tyexn_constructor.ext_id :: all_idents rem | Tstr_recmodule decls -> List.filter_map (fun mb -> mb.mb_id) decls @ all_idents rem @@ -962,7 +974,7 @@ let transl_store_subst = ref Ident.Map.empty let nat_toplevel_name id = try match Ident.Map.find id !transl_store_subst with - | Lprim(Pfield pos, [Lprim(Pgetglobal glob, [], _)], _) -> (glob,pos) + | Lprim(Pfield (pos, _, _), [Lprim(Pgetglobal glob, [], _)], _) -> (glob,pos) | _ -> raise Not_found with Not_found -> fatal_error("Translmod.nat_toplevel_name: " ^ Ident.unique_name id) @@ -1031,6 +1043,20 @@ let transl_store_structure ~scopes glob map prims aliases str = store_ident loc id), transl_store ~scopes rootpath (add_ident false id subst) cont rem) + | Tstr_effect ext -> + let id = ext.ext_id in + let path = field_path rootpath id in + let loc = of_location ~scopes ext.ext_loc in + let lam = transl_extension_constructor ~scopes + item.str_env + path + ext + in + Lsequence(Llet(Strict, Pgenval, id, + Lambda.subst no_env_update subst lam, + store_ident loc id), + transl_store ~scopes rootpath + (add_ident false id subst) cont rem) | Tstr_module {mb_id=None; mb_name; mb_presence=Mp_present; mb_expr=modl; mb_loc=loc; mb_attributes} -> @@ -1194,7 +1220,8 @@ let transl_store_structure ~scopes glob map prims aliases str = | [] -> transl_store ~scopes rootpath (add_idents true ids subst) cont rem | id :: idl -> - Llet(Alias, Pgenval, id, Lprim(Pfield pos, [Lvar mid], + Llet(Alias, Pgenval, id, + Lprim(Pfield (pos, Pointer, Mutable), [Lvar mid], of_location ~scopes loc), Lsequence(store_ident (of_location ~scopes loc) id, store_idents (pos + 1) idl)) @@ -1240,8 +1267,8 @@ let transl_store_structure ~scopes glob map prims aliases str = [] -> transl_store ~scopes rootpath (add_idents true ids subst) cont rem | id :: idl -> - Llet(Alias, Pgenval, id, Lprim(Pfield pos, [Lvar mid], - loc), + Llet(Alias, Pgenval, id, + Lprim(Pfield (pos, Pointer, Mutable), [Lvar mid], loc), Lsequence(store_ident loc id, store_idents (pos + 1) idl)) in @@ -1275,7 +1302,7 @@ let transl_store_structure ~scopes glob map prims aliases str = match cc with Tcoerce_none -> Ident.Map.add id - (Lprim(Pfield pos, + (Lprim(Pfield (pos, Pointer, Immutable), [Lprim(Pgetglobal glob, [], Loc_unknown)], Loc_unknown)) subst @@ -1411,7 +1438,7 @@ let toplevel_name id = let toploop_getvalue id = Lapply{ ap_loc=Loc_unknown; - ap_func=Lprim(Pfield toploop_getvalue_pos, + ap_func=Lprim(Pfield (toploop_getvalue_pos, Pointer, Mutable), [Lprim(Pgetglobal toploop_ident, [], Loc_unknown)], Loc_unknown); ap_args=[Lconst(Const_base( @@ -1424,7 +1451,7 @@ let toploop_getvalue id = let toploop_setvalue id lam = Lapply{ ap_loc=Loc_unknown; - ap_func=Lprim(Pfield toploop_setvalue_pos, + ap_func=Lprim(Pfield (toploop_setvalue_pos, Pointer, Mutable), [Lprim(Pgetglobal toploop_ident, [], Loc_unknown)], Loc_unknown); ap_args= @@ -1471,6 +1498,11 @@ let transl_toplevel_item ~scopes item = toploop_setvalue ext.tyexn_constructor.ext_id (transl_extension_constructor ~scopes item.str_env None ext.tyexn_constructor) + | Tstr_effect ext -> + set_toplevel_unique_name ext.ext_id; + toploop_setvalue ext.ext_id + (transl_extension_constructor ~scopes + item.str_env None ext) | Tstr_module {mb_id=None; mb_presence=Mp_present; mb_expr=modl} -> transl_module ~scopes Tcoerce_none None modl | Tstr_module {mb_id=Some id; mb_presence=Mp_present; mb_expr=modl} -> @@ -1509,7 +1541,7 @@ let transl_toplevel_item ~scopes item = lambda_unit | id :: ids -> Lsequence(toploop_setvalue id - (Lprim(Pfield pos, [Lvar mid], Loc_unknown)), + (Lprim(Pfield (pos, Pointer, Mutable), [Lvar mid], Loc_unknown)), set_idents (pos + 1) ids) in Llet(Strict, Pgenval, mid, transl_module ~scopes Tcoerce_none None modl, set_idents 0 ids) @@ -1532,7 +1564,7 @@ let transl_toplevel_item ~scopes item = lambda_unit | id :: ids -> Lsequence(toploop_setvalue id - (Lprim(Pfield pos, [Lvar mid], Loc_unknown)), + (Lprim(Pfield (pos, Pointer, Mutable), [Lvar mid], Loc_unknown)), set_idents (pos + 1) ids) in Llet(pure, Pgenval, mid, @@ -1628,7 +1660,7 @@ let transl_store_package component_names target_name coercion = (fun pos _id -> Lprim(Psetfield(pos, Pointer, Root_initialization), [Lprim(Pgetglobal target_name, [], Loc_unknown); - Lprim(Pfield pos, [Lvar blk], Loc_unknown)], + Lprim(Pfield (pos, Pointer, Mutable), [Lvar blk], Loc_unknown)], Loc_unknown)) 0 pos_cc_list)) (* diff --git a/lambda/translobj.ml b/lambda/translobj.ml index d7f11beaca..422c55c3df 100644 --- a/lambda/translobj.ml +++ b/lambda/translobj.ml @@ -125,7 +125,8 @@ let transl_label_init_flambda f = let transl_store_label_init glob size f arg = assert(not Config.flambda); assert(!Clflags.native_code); - method_cache := Lprim(Pfield size, + method_cache := Lprim(Pfield (size, Pointer, Mutable), + (* XXX KC: conservative *) [Lprim(Pgetglobal glob, [], Loc_unknown)], Loc_unknown); let expr = f arg in diff --git a/lambda/translprim.ml b/lambda/translprim.ml index 6c9bf92bd3..fff8614de6 100644 --- a/lambda/translprim.ml +++ b/lambda/translprim.ml @@ -123,8 +123,8 @@ let primitives_table = "%loc_POS", Loc Loc_POS; "%loc_MODULE", Loc Loc_MODULE; "%loc_FUNCTION", Loc Loc_FUNCTION; - "%field0", Primitive ((Pfield 0), 1); - "%field1", Primitive ((Pfield 1), 1); + "%field0", Primitive (Pfield(0, Pointer, Mutable), 1); + "%field1", Primitive (Pfield(1, Pointer, Mutable), 1); "%setfield0", Primitive ((Psetfield(0, Pointer, Assignment)), 2); "%makeblock", Primitive ((Pmakeblock(0, Immutable, None)), 1); "%makemutable", Primitive ((Pmakeblock(0, Mutable, None)), 1); @@ -358,6 +358,14 @@ let primitives_table = "%greaterequal", Comparison(Greater_equal, Compare_generic); "%greaterthan", Comparison(Greater_than, Compare_generic); "%compare", Comparison(Compare, Compare_generic); + "%atomic_load", Primitive ((Patomic_load {immediate_or_pointer=Pointer}), 1); + "%atomic_exchange", Primitive (Patomic_exchange, 2); + "%atomic_cas", Primitive (Patomic_cas, 3); + "%atomic_fetch_add", Primitive (Patomic_fetch_add, 2); + "%perform", Primitive (Pperform, 1); + "%resume", Primitive (Presume, 3); + "%poll", Primitive (Ppoll, 1); + "%nop", Primitive (Pnop, 1); ] @@ -422,6 +430,12 @@ let specialize_primitive env ty ~has_constant_constructor prim = | Pointer -> None | Immediate -> Some (Primitive (Psetfield(n, Immediate, init), arity)) end + | Primitive (Pfield (n, Pointer, mut), arity), _ -> + (* try strength reduction based on the *result type* *) + let is_int = match is_function_type env ty with + | None -> Pointer + | Some (_p1, rhs) -> maybe_pointer_type env rhs in + Some (Primitive (Pfield (n, is_int, mut), arity)) | Primitive (Parraylength t, arity), [p] -> begin let array_type = glb_array_type t (array_type_kind env p) in if t = array_type then None @@ -467,6 +481,12 @@ let specialize_primitive env ty ~has_constant_constructor prim = if useful then Some (Primitive (Pmakeblock(tag, mut, Some shape), arity)) else None end + | Primitive (Patomic_load { immediate_or_pointer = Pointer }, arity), _ -> begin + let is_int = match is_function_type env ty with + | None -> Pointer + | Some (_p1, rhs) -> maybe_pointer_type env rhs in + Some (Primitive (Patomic_load {immediate_or_pointer = is_int}, arity)) + end | Comparison(comp, Compare_generic), p1 :: _ -> if (has_constant_constructor && simplify_constant_constructor comp) then begin @@ -757,6 +777,7 @@ let lambda_primitive_needs_event_after = function | Pbytes_load_64 _ | Pbytes_set_16 _ | Pbytes_set_32 _ | Pbytes_set_64 _ | Pbigstring_load_16 _ | Pbigstring_load_32 _ | Pbigstring_load_64 _ | Pbigstring_set_16 _ | Pbigstring_set_32 _ | Pbigstring_set_64 _ + | Prunstack | Pperform | Preperform | Presume | Ppoll | Pbbswap _ -> true | Pidentity | Pbytes_to_string | Pbytes_of_string | Pignore | Psetglobal _ @@ -769,6 +790,7 @@ let lambda_primitive_needs_event_after = function | Pfloatcomp _ | Pstringlength | Pstringrefu | Pbyteslength | Pbytesrefu | Pbytessetu | Pmakearray ((Pintarray | Paddrarray | Pfloatarray), _) | Parraylength _ | Parrayrefu _ | Parraysetu _ | Pisint | Pisout + | Patomic_exchange | Patomic_cas | Patomic_fetch_add | Patomic_load _ | Pnop | Pintofbint _ | Pctconst _ | Pbswap16 | Pint_as_pointer | Popaque -> false (* Determine if a primitive should be surrounded by an "after" debug event *) diff --git a/middle_end/clambda_primitives.ml b/middle_end/clambda_primitives.ml index 3dd0587972..eace031fab 100644 --- a/middle_end/clambda_primitives.ml +++ b/middle_end/clambda_primitives.ml @@ -34,13 +34,18 @@ type primitive = | Pread_symbol of string (* Operations on heap blocks *) | Pmakeblock of int * mutable_flag * block_shape - | Pfield of int + | Pfield of int * immediate_or_pointer * mutable_flag | Pfield_computed | Psetfield of int * immediate_or_pointer * initialization_or_assignment | Psetfield_computed of immediate_or_pointer * initialization_or_assignment | Pfloatfield of int | Psetfloatfield of int * initialization_or_assignment | Pduprecord of Types.record_representation * int + (* Context switches *) + | Prunstack + | Pperform + | Presume + | Preperform (* External call *) | Pccall of Primitive.description (* Exceptions *) @@ -114,8 +119,17 @@ type primitive = | Pbbswap of boxed_integer (* Integer to external pointer *) | Pint_as_pointer + (* Atomic operations *) + | Patomic_load of {immediate_or_pointer : immediate_or_pointer} + | Patomic_exchange + | Patomic_cas + | Patomic_fetch_add (* Inhibition of optimisation *) | Popaque + (* Polling for interrupts *) + | Ppoll + (* nop instruction for debugging *) + | Pnop and integer_comparison = Lambda.integer_comparison = Ceq | Cne | Clt | Cgt | Cle | Cge diff --git a/middle_end/clambda_primitives.mli b/middle_end/clambda_primitives.mli index a75cd04814..74daefdd95 100644 --- a/middle_end/clambda_primitives.mli +++ b/middle_end/clambda_primitives.mli @@ -34,13 +34,18 @@ type primitive = | Pread_symbol of string (* Operations on heap blocks *) | Pmakeblock of int * mutable_flag * block_shape - | Pfield of int + | Pfield of int * immediate_or_pointer * mutable_flag | Pfield_computed | Psetfield of int * immediate_or_pointer * initialization_or_assignment | Psetfield_computed of immediate_or_pointer * initialization_or_assignment | Pfloatfield of int | Psetfloatfield of int * initialization_or_assignment | Pduprecord of Types.record_representation * int + (* Context switches *) + | Prunstack + | Pperform + | Presume + | Preperform (* External call *) | Pccall of Primitive.description (* Exceptions *) @@ -117,8 +122,18 @@ type primitive = | Pbbswap of boxed_integer (* Integer to external pointer *) | Pint_as_pointer + (* Atomic operations *) + | Patomic_load of {immediate_or_pointer : immediate_or_pointer} + | Patomic_exchange + | Patomic_cas + | Patomic_fetch_add (* Inhibition of optimisation *) | Popaque + (* Polling for interrupts *) + | Ppoll + (* nop instruction for debugging *) + | Pnop + and integer_comparison = Lambda.integer_comparison = Ceq | Cne | Clt | Cgt | Cle | Cge diff --git a/middle_end/closure/closure.ml b/middle_end/closure/closure.ml index a51768216c..bc942c27c8 100644 --- a/middle_end/closure/closure.ml +++ b/middle_end/closure/closure.ml @@ -54,7 +54,7 @@ let rec build_closure_env env_param pos = function [] -> V.Map.empty | id :: rem -> V.Map.add id - (Uprim(P.Pfield pos, [Uvar env_param], Debuginfo.none)) + (Uprim(P.Pfield(pos, Pointer, Immutable), [Uvar env_param], Debuginfo.none)) (build_closure_env env_param (pos+1) rem) (* Auxiliary for accessing globals. We change the name of the global @@ -117,10 +117,15 @@ let prim_size prim args = match prim with | Pread_symbol _ -> 1 | Pmakeblock _ -> 5 + List.length args - | Pfield _ -> 1 + | Pfield(_, isptr, Mutable) -> + begin match isptr with + | Pointer -> 2 + | Immediate -> 1 + end + | Pfield(_, _, Immutable) -> 1 | Psetfield(_f, isptr, init) -> begin match init with - | Root_initialization -> 1 (* never causes a write barrier hit *) + | Root_initialization | Assignment | Heap_initialization -> match isptr with | Pointer -> 4 @@ -478,10 +483,10 @@ let simplif_prim_pure ~backend fpc p (args, approxs) dbg = (Uprim(p, args, dbg), Value_tuple (Array.of_list approxs)) end (* Field access *) - | Pfield n, _, [ Value_const(Uconst_ref(_, Some (Uconst_block(_, l)))) ] + | Pfield (n, _, _), _, [ Value_const(Uconst_ref(_, Some (Uconst_block(_, l)))) ] when n < List.length l -> make_const (List.nth l n) - | Pfield n, [ Uprim(P.Pmakeblock _, ul, _) ], [approx] + | Pfield(n, _, _), [ Uprim(P.Pmakeblock _, ul, _) ], [approx] when n < List.length ul -> (List.nth ul n, field_approx n approx) (* Strings *) @@ -819,7 +824,7 @@ let check_constant_result ulam approx = let glb = Uprim(P.Pread_symbol id, [], Debuginfo.none) in - Uprim(P.Pfield i, [glb], Debuginfo.none), approx + Uprim(P.Pfield(i, Pointer, Immutable), [glb], Debuginfo.none), approx end | _ -> (ulam, approx) @@ -1081,10 +1086,10 @@ let rec close ({ backend; fenv; cenv ; mutable_vars } as env) lam = let dbg = Debuginfo.from_location loc in check_constant_result (getglobal dbg id) (Compilenv.global_approx id) - | Lprim(Pfield n, [lam], loc) -> + | Lprim(Pfield (n, ptr, mut), [lam], loc) -> let (ulam, approx) = close env lam in let dbg = Debuginfo.from_location loc in - check_constant_result (Uprim(P.Pfield n, [ulam], dbg)) + check_constant_result (Uprim(P.Pfield (n, ptr, mut), [ulam], dbg)) (field_approx n approx) | Lprim(Psetfield(n, is_ptr, init), [Lprim(Pgetglobal id, [], _); lam], loc)-> let (ulam, approx) = close env lam in diff --git a/middle_end/convert_primitives.ml b/middle_end/convert_primitives.ml index 4ea177393e..8ea75c2e3a 100644 --- a/middle_end/convert_primitives.ml +++ b/middle_end/convert_primitives.ml @@ -26,7 +26,8 @@ let convert (prim : Lambda.primitive) : Clambda_primitives.primitive = match prim with | Pmakeblock (tag, mutability, shape) -> Pmakeblock (tag, mutability, shape) - | Pfield field -> Pfield field + | Pfield (field, imm_or_pointer, mutability) -> + Pfield (field, imm_or_pointer, mutability) | Pfield_computed -> Pfield_computed | Psetfield (field, imm_or_pointer, init_or_assign) -> Psetfield (field, imm_or_pointer, init_or_assign) @@ -36,6 +37,10 @@ let convert (prim : Lambda.primitive) : Clambda_primitives.primitive = | Psetfloatfield (field, init_or_assign) -> Psetfloatfield (field, init_or_assign) | Pduprecord (repr, size) -> Pduprecord (repr, size) + | Prunstack -> Prunstack + | Pperform -> Pperform + | Presume -> Presume + | Preperform -> Preperform | Pccall prim -> Pccall prim | Praise kind -> Praise kind | Psequand -> Psequand @@ -139,8 +144,14 @@ let convert (prim : Lambda.primitive) : Clambda_primitives.primitive = | Pbigarraydim dim -> Pbigarraydim dim | Pbswap16 -> Pbswap16 | Pint_as_pointer -> Pint_as_pointer + | Patomic_load { immediate_or_pointer } -> + Patomic_load { immediate_or_pointer } + | Patomic_exchange -> Patomic_exchange + | Patomic_cas -> Patomic_cas + | Patomic_fetch_add -> Patomic_fetch_add | Popaque -> Popaque - + | Ppoll -> Ppoll + | Pnop -> Pnop | Pbytes_to_string | Pbytes_of_string | Pctconst _ diff --git a/middle_end/flambda/build_export_info.ml b/middle_end/flambda/build_export_info.ml index 554b69a2e2..a3cb96d251 100644 --- a/middle_end/flambda/build_export_info.ml +++ b/middle_end/flambda/build_export_info.ml @@ -286,7 +286,7 @@ and descr_of_named (env : Env.t) (named : Flambda.named) Value_block (Tag.create_exn tag, Array.of_list approxs) in Value_id (Env.new_descr env descr) - | Prim (Pfield i, [arg], _) -> + | Prim (Pfield (i, _, _), [arg], _) -> begin match Env.get_descr env (Env.find_approx env arg) with | Some (Value_block (_, fields)) when Array.length fields > i -> fields.(i) | _ -> Value_unknown diff --git a/middle_end/flambda/closure_conversion.ml b/middle_end/flambda/closure_conversion.ml index 8c731a9faa..0dd0f972bf 100644 --- a/middle_end/flambda/closure_conversion.ml +++ b/middle_end/flambda/closure_conversion.ml @@ -92,7 +92,7 @@ let tupled_function_call_stub original_params unboxed_version ~closure_bound_var let _, body = List.fold_left (fun (pos, body) param -> let lam : Flambda.named = - Prim (Pfield pos, [tuple_param_var], Debuginfo.none) + Prim (Pfield (pos, Pointer, Mutable), [tuple_param_var], Debuginfo.none) in pos + 1, Flambda.create_let param lam body) (0, call) params @@ -708,9 +708,9 @@ let lambda_to_flambda ~backend ~module_ident ~size ~filename lam Flambda.create_let sym_v (Symbol block_symbol) (Flambda.create_let result_v - (Prim (Pfield 0, [sym_v], Debuginfo.none)) + (Prim (Pfield (0, Pointer, Mutable), [sym_v], Debuginfo.none)) (Flambda.create_let value_v - (Prim (Pfield pos, [result_v], Debuginfo.none)) + (Prim (Pfield (pos, Pointer, Mutable), [result_v], Debuginfo.none)) (Var value_v)))) in let module_initializer : Flambda.program_body = diff --git a/middle_end/flambda/extract_projections.ml b/middle_end/flambda/extract_projections.ml index 33cd473ecd..a368b3bd7f 100644 --- a/middle_end/flambda/extract_projections.ml +++ b/middle_end/flambda/extract_projections.ml @@ -124,7 +124,7 @@ let rec analyse_expr ~which_variables expr = when Variable.Map.mem move.closure which_variables -> projections := Projection.Set.add (Move_within_set_of_closures move) !projections - | Prim (Pfield field_index, [var], _dbg) + | Prim (Pfield (field_index, _, _), [var], _dbg) when Variable.Map.mem var which_variables -> projections := Projection.Set.add (Field (field_index, var)) !projections diff --git a/middle_end/flambda/flambda_to_clambda.ml b/middle_end/flambda/flambda_to_clambda.ml index 6b4fae2462..c28167e042 100644 --- a/middle_end/flambda/flambda_to_clambda.ml +++ b/middle_end/flambda/flambda_to_clambda.ml @@ -371,7 +371,8 @@ and to_clambda_named t env var (named : Flambda.named) : Clambda.ulambda = Flambda.print_named named end | Read_symbol_field (symbol, field) -> - Uprim (Pfield field, [to_clambda_symbol env symbol], Debuginfo.none) + Uprim (Pfield (field, Pointer, Mutable), + [to_clambda_symbol env symbol], Debuginfo.none) | Set_of_closures set_of_closures -> to_clambda_set_of_closures t env set_of_closures | Project_closure { set_of_closures; closure_id } -> @@ -396,12 +397,13 @@ and to_clambda_named t env var (named : Flambda.named) : Clambda.ulambda = let fun_offset = get_fun_offset t closure_id in let var_offset = get_fv_offset t var in let pos = var_offset - fun_offset in - Uprim (Pfield pos, + Uprim (Pfield (pos, Pointer, Mutable), [check_field t (check_closure t ulam (Expr (Var closure))) pos (Some named)], Debuginfo.none) - | Prim (Pfield index, [block], dbg) -> - Uprim (Pfield index, [check_field t (subst_var env block) index None], dbg) + | Prim (Pfield (index, ptr, mut), [block], dbg) -> + Uprim (Pfield (index, ptr, mut), + [check_field t (subst_var env block) index None], dbg) | Prim (Psetfield (index, maybe_ptr, init), [block; new_value], dbg) -> Uprim (Psetfield (index, maybe_ptr, init), [ check_field t (subst_var env block) index None; @@ -514,7 +516,8 @@ and to_clambda_set_of_closures t env in let pos = var_offset - fun_offset in Env.add_subst env id - (Uprim (Pfield pos, [Clambda.Uvar env_var], Debuginfo.none)) + (Uprim (Pfield (pos, Pointer, Mutable), + [Clambda.Uvar env_var], Debuginfo.none)) in let env = Variable.Map.fold add_env_free_variable free_vars env in (* Add the Clambda expressions for all functions defined in the current diff --git a/middle_end/flambda/flambda_utils.ml b/middle_end/flambda/flambda_utils.ml index c204f5e67c..1eb9705a34 100644 --- a/middle_end/flambda/flambda_utils.ml +++ b/middle_end/flambda/flambda_utils.ml @@ -543,7 +543,7 @@ let substitute_read_symbol_field_for_variables Expr ( Flambda.create_let block (make_named t) (Flambda.create_let field - (Prim (Pfield h, [block], Debuginfo.none)) + (Prim (Pfield (h, Pointer, Mutable), [block], Debuginfo.none)) (Var field))) in Flambda.create_let fresh_var (make_named path) expr @@ -902,7 +902,7 @@ let projection_to_named (projection : Projection.t) : Flambda.named = | Project_closure project_closure -> Project_closure project_closure | Move_within_set_of_closures move -> Move_within_set_of_closures move | Field (field_index, var) -> - Prim (Pfield field_index, [var], Debuginfo.none) + Prim (Pfield (field_index, Pointer, Mutable), [var], Debuginfo.none) type specialised_to_same_as = | Not_specialised diff --git a/middle_end/flambda/inline_and_simplify.ml b/middle_end/flambda/inline_and_simplify.ml index 2f0b0a773f..13349e42b7 100644 --- a/middle_end/flambda/inline_and_simplify.ml +++ b/middle_end/flambda/inline_and_simplify.ml @@ -991,7 +991,7 @@ and simplify_named env r (tree : Flambda.named) : Flambda.named * R.t = let tree = Flambda.Prim (prim, args, dbg) in begin match prim, args, args_approxs with (* CR-someday mshinwell: Optimise [Pfield_computed]. *) - | Pfield field_index, [arg], [arg_approx] -> + | Pfield (field_index, _, _), [arg], [arg_approx] -> let projection : Projection.t = Field (field_index, arg) in begin match E.find_projection env ~projection with | Some var -> diff --git a/middle_end/flambda/lift_constants.ml b/middle_end/flambda/lift_constants.ml index dd60de9ce2..4af9829d85 100644 --- a/middle_end/flambda/lift_constants.ml +++ b/middle_end/flambda/lift_constants.ml @@ -89,7 +89,7 @@ let assign_symbols_and_collect_constant_definitions | Project_closure ({ closure_id } as project_closure) -> assign_existing_symbol (closure_symbol ~backend closure_id); record_definition (AA.Project_closure project_closure) - | Prim (Pfield index, [block], _) -> + | Prim (Pfield (index, _, _), [block], _) -> record_definition (AA.Field (block, index)) | Prim (Pfield _, _, _) -> Misc.fatal_errorf "[Pfield] with the wrong number of arguments" @@ -997,7 +997,7 @@ let lift_constants (program : Flambda.program) ~backend = constant_definitions in let effect_tbl = - Symbol.Tbl.map effect_tbl (fun (effect, dep) -> rewrite_expr effect, dep) + Symbol.Tbl.map effect_tbl (fun (eff, dep) -> rewrite_expr eff, dep) in let initialize_symbol_tbl = Symbol.Tbl.map initialize_symbol_tbl (fun (tag, fields, dep) -> diff --git a/middle_end/flambda/lift_let_to_initialize_symbol.ml b/middle_end/flambda/lift_let_to_initialize_symbol.ml index ccef0d8a1f..32703833b7 100644 --- a/middle_end/flambda/lift_let_to_initialize_symbol.ml +++ b/middle_end/flambda/lift_let_to_initialize_symbol.ml @@ -264,8 +264,8 @@ let add_extracted introduced program = match extracted with | Initialisation (symbol, tag, def) -> Flambda.Initialize_symbol (symbol, tag, def, program) - | Effect effect -> - Flambda.Effect (effect, program)) + | Effect eff -> + Flambda.Effect (eff, program)) introduced program let rec split_program (program : Flambda.program_body) : Flambda.program_body = diff --git a/middle_end/flambda/ref_to_variables.ml b/middle_end/flambda/ref_to_variables.ml index aa2a73c630..746374e885 100644 --- a/middle_end/flambda/ref_to_variables.ml +++ b/middle_end/flambda/ref_to_variables.ml @@ -155,7 +155,7 @@ let eliminate_ref_of_expr flam = flam and aux_named (named : Flambda.named) : Flambda.named = match named with - | Prim(Pfield field, [v], _) + | Prim(Pfield (field, _, _), [v], _) when convertible_variable v -> (match get_variable v field with | None -> Expr Proved_unreachable diff --git a/middle_end/flambda/remove_unused_program_constructs.ml b/middle_end/flambda/remove_unused_program_constructs.ml index 059d68bcba..468223dcfa 100644 --- a/middle_end/flambda/remove_unused_program_constructs.ml +++ b/middle_end/flambda/remove_unused_program_constructs.ml @@ -94,14 +94,14 @@ let rec loop (program : Flambda.program_body) Flambda.Effect (field, program), dep) (program, dep) fields end - | Effect (effect, program) -> + | Effect (eff, program) -> let program, dep = loop program in - if Effect_analysis.no_effects effect then begin + if Effect_analysis.no_effects eff then begin program, dep end else begin - let new_dep = dependency effect in + let new_dep = dependency eff in let dep = Symbol.Set.union new_dep dep in - Effect (effect, program), dep + Effect (eff, program), dep end | End symbol -> program, Symbol.Set.singleton symbol diff --git a/middle_end/internal_variable_names.ml b/middle_end/internal_variable_names.ml index d139dbb21e..98c6a8bfa8 100644 --- a/middle_end/internal_variable_names.ml +++ b/middle_end/internal_variable_names.ml @@ -172,6 +172,17 @@ let psubfloat = "Psubfloat" let psubint = "Psubint" let pxorbint = "Pxorbint" let pxorint = "Pxorint" +let patomic_cas = "Patomic_cas" +let patomic_exchange = "Patomic_exchange" +let patomic_fetch_add = "Patomic_fetch_add" +let patomic_load = "Patomic_load" +let prunstack = "Prunstack" +let pperform = "Pperform" +let presume = "Presume" +let preperform = "Preperform" +let ppoll = "Ppoll" +let pnop = "Pnop" + let pabsfloat_arg = "Pabsfloat_arg" let paddbint_arg = "Paddbint_arg" let paddfloat_arg = "Paddfloat_arg" @@ -277,6 +288,17 @@ let psubfloat_arg = "Psubfloat_arg" let psubint_arg = "Psubint_arg" let pxorbint_arg = "Pxorbint_arg" let pxorint_arg = "Pxorint_arg" +let patomic_cas_arg = "Patomic_cas_arg" +let patomic_exchange_arg = "Patomic_exchange_arg" +let patomic_fetch_add_arg = "Patomic_fetch_add_arg" +let patomic_load_arg = "Patomic_load_arg" +let prunstack_arg = "Prunstack_arg" +let pperform_arg = "Pperform_arg" +let presume_arg = "Presume_arg" +let preperform_arg = "Preperform_arg" +let ppoll_arg = "Ppoll_arg" +let pnop_arg = "Pnop_arg" + let raise = "raise" let raise_arg = "raise_arg" let read_mutable = "read_mutable" @@ -414,6 +436,16 @@ let of_primitive : Lambda.primitive -> string = function | Pbbswap _ -> pbbswap | Pint_as_pointer -> pint_as_pointer | Popaque -> popaque + | Patomic_cas -> patomic_cas + | Patomic_exchange -> patomic_exchange + | Patomic_fetch_add -> patomic_fetch_add + | Patomic_load _ -> patomic_load + | Prunstack -> prunstack + | Pperform -> pperform + | Presume -> presume + | Preperform -> preperform + | Ppoll -> ppoll + | Pnop -> pnop let of_primitive_arg : Lambda.primitive -> string = function | Pidentity -> pidentity_arg @@ -520,3 +552,13 @@ let of_primitive_arg : Lambda.primitive -> string = function | Pbbswap _ -> pbbswap_arg | Pint_as_pointer -> pint_as_pointer_arg | Popaque -> popaque_arg + | Patomic_cas -> patomic_cas_arg + | Patomic_exchange -> patomic_exchange_arg + | Patomic_fetch_add -> patomic_fetch_add_arg + | Patomic_load _ -> patomic_load_arg + | Prunstack -> prunstack_arg + | Pperform -> pperform_arg + | Presume -> presume_arg + | Preperform -> preperform_arg + | Ppoll -> ppoll_arg + | Pnop -> pnop_arg diff --git a/middle_end/printclambda_primitives.ml b/middle_end/printclambda_primitives.ml index 2e94989155..5c591bfc21 100644 --- a/middle_end/printclambda_primitives.ml +++ b/middle_end/printclambda_primitives.ml @@ -61,7 +61,14 @@ let primitive ppf (prim:Clambda_primitives.primitive) = fprintf ppf "makeblock %i%a" tag Printlambda.block_shape shape | Pmakeblock(tag, Mutable, shape) -> fprintf ppf "makemutable %i%a" tag Printlambda.block_shape shape - | Pfield n -> fprintf ppf "field %i" n + | Pfield(n, ptr, mut) -> + let instr = + match ptr, mut with + | Immediate, _ -> "field_int " + | Pointer, Mutable -> "field_mut " + | Pointer, Immutable -> "field_imm " + in + fprintf ppf "%s%i" instr n | Pfield_computed -> fprintf ppf "field_computed" | Psetfield(n, ptr, init) -> let instr = @@ -100,6 +107,10 @@ let primitive ppf (prim:Clambda_primitives.primitive) = fprintf ppf "setfloatfield%s %i" init n | Pduprecord (rep, size) -> fprintf ppf "duprecord %a %i" Printlambda.record_rep rep size + | Prunstack -> fprintf ppf "runstack" + | Pperform -> fprintf ppf "perform" + | Presume -> fprintf ppf "resume" + | Preperform -> fprintf ppf "reperform" | Pccall p -> fprintf ppf "%s" p.Primitive.prim_name | Praise k -> fprintf ppf "%s" (Lambda.raise_kind k) | Psequand -> fprintf ppf "&&" @@ -202,4 +213,13 @@ let primitive ppf (prim:Clambda_primitives.primitive) = | Pbswap16 -> fprintf ppf "bswap16" | Pbbswap(bi) -> print_boxed_integer "bswap" ppf bi | Pint_as_pointer -> fprintf ppf "int_as_pointer" + | Patomic_load {immediate_or_pointer} -> + (match immediate_or_pointer with + | Immediate -> fprintf ppf "atomic_load_imm" + | Pointer -> fprintf ppf "atomic_load_ptr") + | Patomic_exchange -> fprintf ppf "atomic_exchange" + | Patomic_cas -> fprintf ppf "atomic_cas" + | Patomic_fetch_add -> fprintf ppf "atomic_fetch_add" | Popaque -> fprintf ppf "opaque" + | Ppoll -> fprintf ppf "poll" + | Pnop -> fprintf ppf "nop" diff --git a/middle_end/semantics_of_primitives.ml b/middle_end/semantics_of_primitives.ml index 47ed8c3e59..71feafc94b 100644 --- a/middle_end/semantics_of_primitives.ml +++ b/middle_end/semantics_of_primitives.ml @@ -33,8 +33,13 @@ let for_primitive (prim : Clambda_primitives.primitive) = ( "caml_format_float" | "caml_format_int" | "caml_int32_format" | "caml_nativeint_format" | "caml_int64_format" ) } -> No_effects, No_coeffects + | Pnop -> Arbitrary_effects, Has_coeffects (* XXX KC: conservative so that + the optimiser will not move it + around. Is that right? *) | Pccall _ -> Arbitrary_effects, Has_coeffects | Praise _ -> Arbitrary_effects, No_coeffects + | Prunstack | Pperform | Presume | Preperform -> Arbitrary_effects, Has_coeffects + | Ppoll -> Arbitrary_effects, Has_coeffects | Pnot | Pnegint | Paddint @@ -115,6 +120,10 @@ let for_primitive (prim : Clambda_primitives.primitive) = | Psetfield _ | Psetfield_computed _ | Psetfloatfield _ + | Patomic_load _ + | Patomic_exchange + | Patomic_cas + | Patomic_fetch_add | Parraysetu _ | Parraysets _ | Pbytessetu diff --git a/ocaml-variants.opam b/ocaml-variants.opam index ee159c3eca..6f719f4389 100644 --- a/ocaml-variants.opam +++ b/ocaml-variants.opam @@ -1,6 +1,26 @@ +(* In order to use the development compiler with opam 2.0, first create a new + switch + + opam switch create 4.12.0+multicore --empty + + Initial build: + + opam pin add -k path --inplace-build ocaml-variants.4.12.0+multicore . + + This installs the compiler for the new opam switch. Subsequent builds can be + done locally with: + + make world; make world.opt + + Subsequent installs are done with: + + opam install --assume-built ocaml-variants + +*) + opam-version: "2.0" -version: "4.12.0+trunk" -synopsis: "OCaml development version" +version: "4.12.0+multicore" +synopsis: "OCaml multicore 4.12.0" depends: [ "ocaml" {= "4.12.0" & post} "base-unix" {post} @@ -11,18 +31,11 @@ conflict-class: "ocaml-core-compiler" flags: compiler setenv: CAML_LD_LIBRARY_PATH = "%{lib}%/stublibs" build: [ - ["./configure" "--prefix=%{prefix}%"] + ["./configure" "--prefix=%{prefix}%" "--enable-debug-runtime"] [make "-j%{jobs}%"] ] install: [make "install"] -maintainer: "caml-list@inria.fr" -homepage: "https://github.com/ocaml/ocaml/" -bug-reports: "https://github.com/ocaml/ocaml/issues" -authors: [ - "Xavier Leroy" - "Damien Doligez" - "Alain Frisch" - "Jacques Garrigue" - "Didier Rémy" - "Jérôme Vouillon" -] +maintainer: "kc@kcsrk.info" +homepage: "https://github.com/ocaml-multicore/ocaml-multicore" +bug-reports: "https://github.com/ocaml-multicore/ocaml-multicore/issues" +authors: "Xavier Leroy and many contributors" diff --git a/ocamldoc/odoc_ast.ml b/ocamldoc/odoc_ast.ml index c7cc62b8ad..f0ae423bbf 100644 --- a/ocamldoc/odoc_ast.ml +++ b/ocamldoc/odoc_ast.ml @@ -77,6 +77,7 @@ module Typedtree_search = end | Typedtree.Tstr_exception ext -> Hashtbl.add table (E (Name.from_ident ext.tyexn_constructor.ext_id)) tt + | Typedtree.Tstr_effect _ext -> failwith "Not implemented" (* FIXME *) | Typedtree.Tstr_type (rf, ident_type_decl_list) -> List.iter (fun td -> @@ -1390,6 +1391,8 @@ module Analyser = in (0, new_env, [ Element_exception new_ext ]) + | Parsetree.Pstr_effect _ext -> failwith "Not implemented" (* FIXME *) + | Parsetree.Pstr_module {Parsetree.pmb_name={txt=None}} -> (0, env, []) diff --git a/ocamldoc/odoc_sig.ml b/ocamldoc/odoc_sig.ml index 9e4d1e4454..c63ceee2ca 100644 --- a/ocamldoc/odoc_sig.ml +++ b/ocamldoc/odoc_sig.ml @@ -477,6 +477,7 @@ module Analyser = | Parsetree.Psig_extension _ | Parsetree.Psig_value _ | Parsetree.Psig_typext _ + | Parsetree.Psig_effect _ | Parsetree.Psig_exception _ | Parsetree.Psig_open _ | Parsetree.Psig_include _ @@ -911,6 +912,8 @@ module Analyser = let new_env = Odoc_env.add_extension env e.ex_name in (maybe_more, new_env, [ Element_exception e ]) + | Parsetree.Psig_effect _ext -> failwith "Not implemented" (* FIXME *) + | Parsetree.Psig_type (rf, name_type_decl_list) -> let extended_env = List.fold_left diff --git a/ocamltest/ocaml_actions.ml b/ocamltest/ocaml_actions.ml index 1e152a6039..12c146d743 100644 --- a/ocamltest/ocaml_actions.ml +++ b/ocamltest/ocaml_actions.ml @@ -633,19 +633,40 @@ let mklib log env = let ocamlmklib = Actions.make "ocamlmklib" mklib -let finalise_codegen_cc test_basename _log env = - let test_module = - Filename.make_filename test_basename "s" - in - let archmod = Ocaml_files.asmgen_archmod in - let modules = test_module ^ " " ^ archmod in - let program = Filename.make_filename test_basename "out" in - let env = Environments.add_bindings - [ - Ocaml_variables.modules, modules; - Builtin_variables.program, program; - ] env in - (Result.pass, env) +let finalise_codegen_cc test_basename log env = + (* HACKED for multicore asmgen tests *) + let obj = Filename.make_filename test_basename Ocamltest_config.objext in + let src = Filename.make_filename test_basename "s" in + let what = "Running assembler on codegen" in + Printf.fprintf log "%s\n%!" what; + let commandline = [Ocamltest_config.asm; "-o"; obj; src] in + let expected_exit_status = 0 in + let exit_status = + Actions_helpers.run_cmd + ~environment:default_ocaml_env + ~stdout_variable:Ocaml_variables.compiler_output + ~stderr_variable:Ocaml_variables.compiler_output + ~append:true + log env commandline in + if exit_status=expected_exit_status + then begin + let archmod = Ocaml_files.asmgen_archmod in + let modules = obj ^ " " ^ archmod in + let program = Filename.make_filename test_basename "out" in + let env = Environments.add_bindings + [ + Builtin_variables.program, program; + Ocaml_variables.all_modules, modules; + Ocaml_variables.flags, + (Environments.safe_lookup Builtin_variables.arguments env); + ] env in + (Result.pass, env) + end else begin + let reason = + (Actions_helpers.mkreason + what (String.concat " " commandline) exit_status) in + (Result.fail_with_reason reason, env) + end let finalise_codegen_msvc test_basename log env = let obj = Filename.make_filename test_basename Ocamltest_config.objext in diff --git a/ocamltest/ocaml_tests.ml b/ocamltest/ocaml_tests.ml index d84eeb43f7..649bf9cc81 100644 --- a/ocamltest/ocaml_tests.ml +++ b/ocamltest/ocaml_tests.ml @@ -121,9 +121,9 @@ let asmgen_actions = else if Ocamltest_config.spacetime then [asmgen_skip_on_spacetime] else if msvc64 then [asmgen_skip_on_msvc64] else [ - setup_simple_build_env; + setup_ocamlc_opt_build_env; codegen; - cc; + ocamlc_opt; ] let asmgen = diff --git a/otherlibs/num/.depend b/otherlibs/num/.depend new file mode 100644 index 0000000000..e4ca360458 --- /dev/null +++ b/otherlibs/num/.depend @@ -0,0 +1,44 @@ +bng.o: bng.c bng.h ../../runtime/caml/config.h \ + ../../runtime/caml/../../config/m.h ../../runtime/caml/../../config/s.h \ + ../../runtime/caml/compatibility.h bng_amd64.c bng_digit.c +bng_amd64.o: bng_amd64.c +bng_arm64.o: bng_arm64.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 ../../runtime/caml/alloc.h \ + ../../runtime/caml/compatibility.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/../../config/m.h \ + ../../runtime/caml/../../config/s.h ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/domain_state.h ../../runtime/caml/domain_state.tbl \ + ../../runtime/caml/byte_domain_state.tbl ../../runtime/caml/config.h \ + ../../runtime/caml/custom.h ../../runtime/caml/intext.h \ + ../../runtime/caml/io.h ../../runtime/caml/platform.h \ + ../../runtime/caml/memory.h ../../runtime/caml/gc.h \ + ../../runtime/caml/major_gc.h ../../runtime/caml/minor_gc.h \ + ../../runtime/caml/addrmap.h ../../runtime/caml/domain.h \ + ../../runtime/caml/alloc.h ../../runtime/caml/fail.h \ + ../../runtime/caml/hash.h ../../runtime/caml/memory.h \ + ../../runtime/caml/mlvalues.h bng.h nat.h +arith_flags.cmo : arith_flags.cmi +arith_flags.cmx : arith_flags.cmi +arith_flags.cmi : +arith_status.cmo : arith_flags.cmi arith_status.cmi +arith_status.cmx : arith_flags.cmx arith_status.cmi +arith_status.cmi : +big_int.cmo : nat.cmi int_misc.cmi big_int.cmi +big_int.cmx : nat.cmx int_misc.cmx big_int.cmi +big_int.cmi : nat.cmi +int_misc.cmo : int_misc.cmi +int_misc.cmx : int_misc.cmi +int_misc.cmi : +nat.cmo : int_misc.cmi nat.cmi +nat.cmx : int_misc.cmx nat.cmi +nat.cmi : +num.cmo : ratio.cmi nat.cmi int_misc.cmi big_int.cmi arith_flags.cmi num.cmi +num.cmx : ratio.cmx nat.cmx int_misc.cmx big_int.cmx arith_flags.cmx num.cmi +num.cmi : ratio.cmi nat.cmi big_int.cmi +ratio.cmo : nat.cmi int_misc.cmi big_int.cmi arith_flags.cmi ratio.cmi +ratio.cmx : nat.cmx int_misc.cmx big_int.cmx arith_flags.cmx ratio.cmi +ratio.cmi : nat.cmi big_int.cmi diff --git a/otherlibs/num/.depend.nt b/otherlibs/num/.depend.nt new file mode 100644 index 0000000000..7a28387fe4 --- /dev/null +++ b/otherlibs/num/.depend.nt @@ -0,0 +1,66 @@ +bng.dobj: bng.c bng.h ../../byterun/config.h ../../config/m.h \ + ../../config/s.h ../../byterun/compatibility.h bng_ppc.c bng_digit.c +bng_alpha.dobj: bng_alpha.c +bng_amd64.dobj: bng_amd64.c +bng_digit.dobj: bng_digit.c +bng_ia32.dobj: bng_ia32.c +bng_mips.dobj: bng_mips.c +bng_ppc.dobj: bng_ppc.c +bng_sparc.dobj: bng_sparc.c +nat_stubs.dobj: nat_stubs.c ../../byterun/alloc.h \ + ../../byterun/compatibility.h ../../byterun/misc.h \ + ../../byterun/config.h ../../config/m.h ../../config/s.h \ + ../../byterun/mlvalues.h ../../byterun/custom.h ../../byterun/intext.h \ + ../../byterun/io.h ../../byterun/fix_code.h ../../byterun/fail.h \ + ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \ + ../../byterun/minor_gc.h bng.h nat.h +big_int.cmi: nat.cmi +num.cmi: ratio.cmi nat.cmi big_int.cmi +ratio.cmi: nat.cmi big_int.cmi +arith_flags.cmo: arith_flags.cmi +arith_flags.cmx: arith_flags.cmi +arith_status.cmo: arith_flags.cmi arith_status.cmi +arith_status.cmx: arith_flags.cmx arith_status.cmi +big_int.cmo: nat.cmi int_misc.cmi big_int.cmi +big_int.cmx: nat.cmx int_misc.cmx big_int.cmi +int_misc.cmo: int_misc.cmi +int_misc.cmx: int_misc.cmi +nat.cmo: int_misc.cmi nat.cmi +nat.cmx: int_misc.cmx nat.cmi +num.cmo: ratio.cmi nat.cmi int_misc.cmi big_int.cmi arith_flags.cmi num.cmi +num.cmx: ratio.cmx nat.cmx int_misc.cmx big_int.cmx arith_flags.cmx num.cmi +ratio.cmo: nat.cmi int_misc.cmi big_int.cmi arith_flags.cmi ratio.cmi +ratio.cmx: nat.cmx int_misc.cmx big_int.cmx arith_flags.cmx ratio.cmi +bng.sobj: bng.c bng.h ../../byterun/config.h ../../config/m.h \ + ../../config/s.h ../../byterun/compatibility.h bng_ppc.c bng_digit.c +bng_alpha.sobj: bng_alpha.c +bng_amd64.sobj: bng_amd64.c +bng_digit.sobj: bng_digit.c +bng_ia32.sobj: bng_ia32.c +bng_mips.sobj: bng_mips.c +bng_ppc.sobj: bng_ppc.c +bng_sparc.sobj: bng_sparc.c +nat_stubs.sobj: nat_stubs.c ../../byterun/alloc.h \ + ../../byterun/compatibility.h ../../byterun/misc.h \ + ../../byterun/config.h ../../config/m.h ../../config/s.h \ + ../../byterun/mlvalues.h ../../byterun/custom.h ../../byterun/intext.h \ + ../../byterun/io.h ../../byterun/fix_code.h ../../byterun/fail.h \ + ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \ + ../../byterun/minor_gc.h bng.h nat.h +big_int.cmi: nat.cmi +num.cmi: ratio.cmi nat.cmi big_int.cmi +ratio.cmi: nat.cmi big_int.cmi +arith_flags.cmo: arith_flags.cmi +arith_flags.cmx: arith_flags.cmi +arith_status.cmo: arith_flags.cmi arith_status.cmi +arith_status.cmx: arith_flags.cmx arith_status.cmi +big_int.cmo: nat.cmi int_misc.cmi big_int.cmi +big_int.cmx: nat.cmx int_misc.cmx big_int.cmi +int_misc.cmo: int_misc.cmi +int_misc.cmx: int_misc.cmi +nat.cmo: int_misc.cmi nat.cmi +nat.cmx: int_misc.cmx nat.cmi +num.cmo: ratio.cmi nat.cmi int_misc.cmi big_int.cmi arith_flags.cmi num.cmi +num.cmx: ratio.cmx nat.cmx int_misc.cmx big_int.cmx arith_flags.cmx num.cmi +ratio.cmo: nat.cmi int_misc.cmi big_int.cmi arith_flags.cmi ratio.cmi +ratio.cmx: nat.cmx int_misc.cmx big_int.cmx arith_flags.cmx ratio.cmi diff --git a/otherlibs/str/str.ml b/otherlibs/str/str.ml index 6242be7fc4..f235c7bf2f 100644 --- a/otherlibs/str/str.ml +++ b/otherlibs/str/str.ml @@ -94,10 +94,10 @@ module Charset = r let fold_case s = - (let r = make_empty() in - iter (fun c -> add r (Char.lowercase c); add r (Char.uppercase c)) s; - r)[@ocaml.warning "-3"] - + let r = make_empty() in + iter (fun c -> add r (Char.lowercase_ascii c); + add r (Char.uppercase_ascii c)) s; + r end (** Abstract syntax tree for regular expressions *) @@ -217,9 +217,9 @@ let charclass_of_regexp fold_case re = (* The case fold table: maps characters to their lowercase equivalent *) let fold_case_table = - (let t = Bytes.create 256 in - for i = 0 to 255 do Bytes.set t i (Char.lowercase(Char.chr i)) done; - Bytes.to_string t)[@ocaml.warning "-3"] + let t = Bytes.create 256 in + for i = 0 to 255 do Bytes.set t i (Char.lowercase_ascii(Char.chr i)) done; + Bytes.to_string t module StringMap = Map.Make(struct type t = string let compare (x:t) y = compare x y end) @@ -275,8 +275,7 @@ let compile fold_case re = let rec emit_code = function Char c -> if fold_case then - emit_instr op_CHARNORM (Char.code (Char.lowercase c)) - [@ocaml.warning "-3"] + emit_instr op_CHARNORM (Char.code (Char.lowercase_ascii c)) else emit_instr op_CHAR (Char.code c) | String s -> @@ -284,8 +283,7 @@ let compile fold_case re = 0 -> () | 1 -> if fold_case then - emit_instr op_CHARNORM (Char.code (Char.lowercase s.[0])) - [@ocaml.warning "-3"] + emit_instr op_CHARNORM (Char.code (Char.lowercase_ascii s.[0])) else emit_instr op_CHAR (Char.code s.[0]) | _ -> @@ -298,8 +296,7 @@ let compile fold_case re = emit_code (String (string_after s (i+1))) with Not_found -> if fold_case then - emit_instr op_STRINGNORM (cpool_index (String.lowercase s)) - [@ocaml.warning "-3"] + emit_instr op_STRINGNORM (cpool_index (String.lowercase_ascii s)) else emit_instr op_STRING (cpool_index s) end diff --git a/otherlibs/str/strstubs.c b/otherlibs/str/strstubs.c index 51d7b79687..03a85c10cb 100644 --- a/otherlibs/str/strstubs.c +++ b/otherlibs/str/strstubs.c @@ -130,7 +130,8 @@ static unsigned char re_word_letters[32] = { static value re_alloc_groups(value re, unsigned char * starttxt, struct re_group * groups) { - value res; + CAMLparam1(re); + CAMLlocal1(res); int n = Numgroups(re); int i; struct re_group * group; @@ -146,9 +147,10 @@ static value re_alloc_groups(value re, unsigned char * starttxt, Field(res, i * 2 + 1) = Val_long(group->end - starttxt); } } - return res; + CAMLreturn(res); } + /* The bytecode interpreter for the NFA. Return Caml array of matched groups on success, 0 on failure. */ @@ -185,7 +187,7 @@ static value re_match(value re, *q = NULL; } - pc = &Field(Prog(re), 0); + pc = Op_val(Prog(re)); stack = &initial_stack; sp = stack->point; cpool = Cpool(re); @@ -532,8 +534,8 @@ CAMLprim value re_replacement_text(value repl, value groups, value orig) case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': c -= '0'; - start = Long_val(Field(groups, c*2)); - end = Long_val(Field(groups, c*2 + 1)); + start = Long_field(groups, c*2); + end = Long_field(groups, c*2 + 1); len = end - start; memmove (q, &Byte(orig, start), len); q += len; diff --git a/otherlibs/systhreads/st_posix.h b/otherlibs/systhreads/st_posix.h index 17ed151412..256a90cbb2 100644 --- a/otherlibs/systhreads/st_posix.h +++ b/otherlibs/systhreads/st_posix.h @@ -15,33 +15,42 @@ /* POSIX thread implementation of the "st" interface */ -#include <assert.h> -#include <errno.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> +#define CAML_INTERNALS + +#include "caml/alloc.h" +#include "caml/domain_state.h" +#include "caml/platform.h" +#include "caml/custom.h" +#include "caml/memory.h" +#include "caml/fail.h" +#include "caml/alloc.h" +#include "caml/startup.h" +#include "caml/fiber.h" +#include "caml/callback.h" +#include "caml/weak.h" +#include "caml/finalise.h" +#include "caml/domain.h" +#include "caml/printexc.h" +#include "caml/backtrace.h" #include <pthread.h> -#ifdef __sun -#define _POSIX_PTHREAD_SEMANTICS -#endif #include <signal.h> -#include <time.h> -#include <sys/time.h> -#ifdef __linux__ -#include <unistd.h> +#include <caml/signals.h> + +#ifdef __GNUC__ +#undef INLINE +#define INLINE inline +#else +#define INLINE #endif typedef int st_retcode; -#define SIGPREEMPTION SIGVTALRM - /* OS-specific initialization */ -static int st_initialize(void) -{ - caml_sigmask_hook = pthread_sigmask; - return 0; -} +/* static int st_initialize(void) */ +/* { */ +/* return 0; */ +/* } */ /* Thread creation. Created in detached mode if [res] is NULL. */ @@ -65,7 +74,7 @@ static int st_thread_create(st_thread_id * res, /* Cleanup at thread exit */ -Caml_inline void st_thread_cleanup(void) +static INLINE void st_thread_cleanup(void) { return; } @@ -81,12 +90,6 @@ static void st_thread_exit(void) pthread_exit(NULL); } -static void st_thread_join(st_thread_id thr) -{ - pthread_join(thr, NULL); - /* best effort: ignore errors */ -} - /* Thread-specific state */ typedef pthread_key_t st_tlskey; @@ -96,12 +99,12 @@ static int st_tls_newkey(st_tlskey * res) return pthread_key_create(res, NULL); } -Caml_inline void * st_tls_get(st_tlskey k) +static INLINE void * st_tls_get(st_tlskey k) { return pthread_getspecific(k); } -Caml_inline void st_tls_set(st_tlskey k, void * v) +static INLINE void st_tls_set(st_tlskey k, void * v) { pthread_setspecific(k, v); } @@ -112,44 +115,75 @@ Caml_inline void st_tls_set(st_tlskey k, void * v) threads. */ typedef struct { - pthread_mutex_t lock; /* to protect contents */ - int busy; /* 0 = free, 1 = taken */ - volatile int waiters; /* number of threads waiting on master lock */ - pthread_cond_t is_free; /* signaled when free */ + caml_plat_mutex lock; /* to protect contents */ + atomic_uintnat busy; /* 0 = free, 1 = taken */ + atomic_uintnat waiters; /* number of threads waiting on master lock */ + caml_plat_cond free; /* signaled when free */ } st_masterlock; -static void st_masterlock_init(st_masterlock * m) -{ - pthread_mutex_init(&m->lock, NULL); - pthread_cond_init(&m->is_free, NULL); - m->busy = 1; - m->waiters = 0; +static void st_masterlock_init(st_masterlock *m) { + + caml_plat_mutex_init(&m->lock); + caml_plat_cond_init(&m->free, &m->lock); + atomic_store_rel(&m->busy, 1); + atomic_store_rel(&m->waiters, 0); + + return; +}; + +static void st_bt_lock_acquire(st_masterlock *m) { + + // We do not want to signal the backup thread is it is not "working" + // as it may very well not be, because we could have just resumed + // execution from another thread right away. + if (caml_bt_is_in_blocking_section()) { + caml_bt_enter_ocaml(); + } + + caml_acquire_domain_lock(); + + return; } -static void st_masterlock_acquire(st_masterlock * m) -{ - pthread_mutex_lock(&m->lock); - while (m->busy) { - m->waiters ++; - pthread_cond_wait(&m->is_free, &m->lock); - m->waiters --; +static void st_bt_lock_release(st_masterlock *m) { + + // Here we do want to signal the backup thread iff there's + // no thread waiting to be scheduled, and the backup thread is currently + // idle. + if (atomic_load_acq(&m->waiters) == 0 && + caml_bt_is_in_blocking_section() == 0) { + caml_bt_exit_ocaml(); } - m->busy = 1; - pthread_mutex_unlock(&m->lock); + + caml_release_domain_lock(); + + return; } -static void st_masterlock_release(st_masterlock * m) +static void st_masterlock_acquire(st_masterlock *m) { - pthread_mutex_lock(&m->lock); - m->busy = 0; - pthread_mutex_unlock(&m->lock); - pthread_cond_signal(&m->is_free); + caml_plat_lock(&m->lock); + while (atomic_load_acq(&m->busy)) { + atomic_fetch_add(&m->waiters, +1); + caml_plat_wait(&m->free); + atomic_fetch_add(&m->waiters, -1); + } + atomic_store_rel(&m->busy, 1); + st_bt_lock_acquire(m); + caml_plat_unlock(&m->lock); + + return; } -CAMLno_tsan /* This can be called for reading [waiters] without locking. */ -Caml_inline int st_masterlock_waiters(st_masterlock * m) +static void st_masterlock_release(st_masterlock * m) { - return m->waiters; + caml_plat_lock(&m->lock); + atomic_store_rel(&m->busy, 0); + st_bt_lock_release(m); + caml_plat_signal(&m->free); + caml_plat_unlock(&m->lock); + + return; } /* Scheduling hints */ @@ -161,169 +195,165 @@ Caml_inline int st_masterlock_waiters(st_masterlock * m) off the lock to a waiter we know exists, it's safe, as they'll certainly re-wake us later. */ -Caml_inline void st_thread_yield(st_masterlock * m) + +static INLINE void st_thread_yield(st_masterlock * m) { - pthread_mutex_lock(&m->lock); + uintnat waiters; + + caml_plat_lock(&m->lock); /* We must hold the lock to call this. */ - assert(m->busy); /* We already checked this without the lock, but we might have raced--if there's no waiter, there's nothing to do and no one to wake us if we did wait, so just keep going. */ - if (m->waiters == 0) { - pthread_mutex_unlock(&m->lock); + waiters = atomic_load_acq(&m->waiters); + + if (waiters == 0) { + caml_plat_unlock(&m->lock); return; } - m->busy = 0; - pthread_cond_signal(&m->is_free); - m->waiters++; + atomic_store_rel(&m->busy, 0); + + caml_plat_signal(&m->free); + // releasing the domain lock but not triggering bt messaging + // messaging the bt should not be required because yield assumes + // that a thread will resume execution (be it the yielding thread + // or a waiting thread + caml_release_domain_lock(); + atomic_fetch_add(&m->waiters, +1); do { /* Note: the POSIX spec prevents the above signal from pairing with this wait, which is good: we'll reliably continue waiting until the next yield() or enter_blocking_section() call (or we see a spurious condvar wakeup, which are rare at best.) */ - pthread_cond_wait(&m->is_free, &m->lock); - } while (m->busy); - m->busy = 1; - m->waiters--; - pthread_mutex_unlock(&m->lock); + caml_plat_wait(&m->free); + } while (atomic_load_acq(&m->busy)); + + atomic_store_rel(&m->busy, 1); + atomic_fetch_add(&m->waiters, -1); + + caml_acquire_domain_lock(); + + caml_plat_unlock(&m->lock); + + return; } /* Mutexes */ -typedef pthread_mutex_t * st_mutex; +typedef caml_plat_mutex * st_mutex; static int st_mutex_create(st_mutex * res) { - int rc; - st_mutex m = caml_stat_alloc_noexc(sizeof(pthread_mutex_t)); - if (m == NULL) return ENOMEM; - rc = pthread_mutex_init(m, NULL); - if (rc != 0) { caml_stat_free(m); return rc; } - *res = m; + st_mutex mut = caml_stat_alloc_noexc(sizeof(caml_plat_mutex)); + caml_plat_mutex_init(mut); + *res = mut; return 0; } static int st_mutex_destroy(st_mutex m) { - int rc; - rc = pthread_mutex_destroy(m); + caml_plat_mutex_free(m); caml_stat_free(m); - return rc; + return 0; } -Caml_inline int st_mutex_lock(st_mutex m) +static INLINE void st_mutex_lock(st_mutex m) { - return pthread_mutex_lock(m); + return caml_plat_lock(m); } -#define PREVIOUSLY_UNLOCKED 0 -#define ALREADY_LOCKED EBUSY +#define MUTEX_PREVIOUSLY_UNLOCKED 1 +#define MUTEX_ALREADY_LOCKED 0 -Caml_inline int st_mutex_trylock(st_mutex m) +static INLINE int st_mutex_trylock(st_mutex m) { - return pthread_mutex_trylock(m); + int retcode = caml_plat_try_lock(m); + return retcode; } -Caml_inline int st_mutex_unlock(st_mutex m) +static INLINE void st_mutex_unlock(st_mutex m) { - return pthread_mutex_unlock(m); + return caml_plat_unlock(m); } /* Condition variables */ -typedef pthread_cond_t * st_condvar; +typedef caml_plat_cond * st_condvar; -static int st_condvar_create(st_condvar * res) +static void st_condvar_create(st_condvar * res) { - int rc; - st_condvar c = caml_stat_alloc_noexc(sizeof(pthread_cond_t)); - if (c == NULL) return ENOMEM; - rc = pthread_cond_init(c, NULL); - if (rc != 0) { caml_stat_free(c); return rc; } - *res = c; - return 0; + st_condvar cond = caml_stat_alloc_noexc(sizeof(caml_plat_cond)); + caml_plat_cond_init_no_mutex(cond); + *res = cond; } -static int st_condvar_destroy(st_condvar c) +static void st_condvar_destroy(st_condvar c) { - int rc; - rc = pthread_cond_destroy(c); + caml_plat_cond_free(c); caml_stat_free(c); - return rc; } -Caml_inline int st_condvar_signal(st_condvar c) +static INLINE void st_condvar_signal(st_condvar c) { - return pthread_cond_signal(c); + return check_err("st_condvar_signal", pthread_cond_signal(&c->cond)); } -Caml_inline int st_condvar_broadcast(st_condvar c) +static INLINE void st_condvar_broadcast(st_condvar c) { - return pthread_cond_broadcast(c); + return check_err("st_condvar_broadcast", pthread_cond_broadcast(&c->cond)); } -Caml_inline int st_condvar_wait(st_condvar c, st_mutex m) +static INLINE void st_condvar_wait(st_condvar c, st_mutex m) { - return pthread_cond_wait(c, m); + caml_plat_cond_set_mutex(c, m); + caml_plat_wait(c); + return; } /* Triggered events */ typedef struct st_event_struct { - pthread_mutex_t lock; /* to protect contents */ + caml_plat_mutex lock; /* to protect contents */ int status; /* 0 = not triggered, 1 = triggered */ - pthread_cond_t triggered; /* signaled when triggered */ + caml_plat_cond triggered; /* signaled when triggered */ } * st_event; -static int st_event_create(st_event * res) + +static void st_event_create(st_event * res) { - int rc; - st_event e = caml_stat_alloc_noexc(sizeof(struct st_event_struct)); - if (e == NULL) return ENOMEM; - rc = pthread_mutex_init(&e->lock, NULL); - if (rc != 0) { caml_stat_free(e); return rc; } - rc = pthread_cond_init(&e->triggered, NULL); - if (rc != 0) - { pthread_mutex_destroy(&e->lock); caml_stat_free(e); return rc; } + st_event e = caml_stat_alloc(sizeof(struct st_event_struct)); + caml_plat_mutex_init(&e->lock); + caml_plat_cond_init(&e->triggered, &e->lock); e->status = 0; *res = e; - return 0; + return ; } -static int st_event_destroy(st_event e) +static void st_event_destroy(st_event e) { - int rc1, rc2; - rc1 = pthread_mutex_destroy(&e->lock); - rc2 = pthread_cond_destroy(&e->triggered); + caml_plat_cond_free(&e->triggered); + caml_plat_mutex_free(&e->lock); caml_stat_free(e); - return rc1 != 0 ? rc1 : rc2; } -static int st_event_trigger(st_event e) +static void st_event_trigger(st_event e) { - int rc; - rc = pthread_mutex_lock(&e->lock); - if (rc != 0) return rc; + caml_plat_lock(&e->lock); e->status = 1; - rc = pthread_mutex_unlock(&e->lock); - if (rc != 0) return rc; - rc = pthread_cond_broadcast(&e->triggered); - return rc; + caml_plat_signal(&e->triggered); + caml_plat_unlock(&e->lock); + return; } -static int st_event_wait(st_event e) +static void st_event_wait(st_event e) { - int rc; - rc = pthread_mutex_lock(&e->lock); - if (rc != 0) return rc; + caml_plat_lock(&e->lock); while(e->status == 0) { - rc = pthread_cond_wait(&e->triggered, &e->lock); - if (rc != 0) return rc; + caml_plat_wait(&e->triggered); } - rc = pthread_mutex_unlock(&e->lock); - return rc; + caml_plat_unlock(&e->lock); } /* Reporting errors */ @@ -346,33 +376,6 @@ static void st_check_error(int retcode, char * msg) caml_raise_sys_error(str); } -/* Variable used to stop the "tick" thread */ -static volatile int caml_tick_thread_stop = 0; - -/* The tick thread: posts a SIGPREEMPTION signal periodically */ - -static void * caml_thread_tick(void * arg) -{ - struct timeval timeout; - sigset_t mask; - - /* Block all signals so that we don't try to execute an OCaml signal handler*/ - sigfillset(&mask); - pthread_sigmask(SIG_BLOCK, &mask, NULL); - while(! caml_tick_thread_stop) { - /* select() seems to be the most efficient way to suspend the - thread for sub-second intervals */ - timeout.tv_sec = 0; - timeout.tv_usec = Thread_timeout * 1000; - select(0, NULL, NULL, NULL, &timeout); - /* The preemption signal should never cause a callback, so don't - go through caml_handle_signal(), just record signal delivery via - caml_record_signal(). */ - caml_record_signal(SIGPREEMPTION); - } - return NULL; -} - /* "At fork" processing */ #if defined(__ANDROID__) @@ -396,7 +399,7 @@ static void st_decode_sigset(value vset, sigset_t * set) { sigemptyset(set); while (vset != Val_int(0)) { - int sig = caml_convert_signal_number(Int_val(Field(vset, 0))); + int sig = caml_convert_signal_number(Int_field(vset, 0)); sigaddset(set, sig); vset = Field(vset, 1); } @@ -415,8 +418,8 @@ static value st_encode_sigset(sigset_t * set) for (i = 1; i < NSIG; i++) if (sigismember(set, i) > 0) { value newcons = caml_alloc_small(2, 0); - Field(newcons, 0) = Val_int(caml_rev_convert_signal_number(i)); - Field(newcons, 1) = res; + caml_modify_field(newcons, 0, Val_int(caml_rev_convert_signal_number(i))); + caml_modify_field(newcons, 1, res); res = newcons; } End_roots(); diff --git a/otherlibs/systhreads/st_stubs.c b/otherlibs/systhreads/st_stubs.c index 285466edbb..8d00eefdc0 100644 --- a/otherlibs/systhreads/st_stubs.c +++ b/otherlibs/systhreads/st_stubs.c @@ -15,48 +15,30 @@ #define CAML_INTERNALS +#include <pthread.h> +#include <signal.h> +#include <stdio.h> + #include "caml/alloc.h" -#include "caml/backtrace.h" -#include "caml/callback.h" +#include "caml/domain_state.h" +#include "caml/platform.h" #include "caml/custom.h" -#include "caml/domain.h" -#include "caml/fail.h" -#include "caml/io.h" #include "caml/memory.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" +#include "caml/fail.h" +#include "caml/alloc.h" +#include "caml/startup.h" +#include "caml/fiber.h" +#include "caml/callback.h" +#include "caml/weak.h" +#include "caml/finalise.h" +#include "caml/domain.h" #include "caml/printexc.h" -#include "caml/roots.h" +#include "caml/backtrace.h" #include "caml/signals.h" -#ifdef NATIVE_CODE -#include "caml/stack.h" -#else -#include "caml/stacks.h" -#endif -#include "caml/sys.h" -#include "caml/memprof.h" -#include "threads.h" - -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) -#include "caml/spacetime.h" -#endif - -#ifndef NATIVE_CODE -/* Initial size of bytecode stack when a thread is created (4 Ko) */ -#define Thread_stack_size (Stack_size / 4) -#endif - -/* Max computation time before rescheduling, in milliseconds */ -#define Thread_timeout 50 -/* OS-specific code */ -#ifdef _WIN32 -#include "st_win32.h" -#else #include "st_posix.h" -#endif -/* The ML value describing a thread (heap-allocated) */ +/* ML value for a thread descriptor */ struct caml_thread_descr { value ident; /* Unique integer ID */ @@ -65,76 +47,65 @@ struct caml_thread_descr { }; #define Ident(v) (((struct caml_thread_descr *)(v))->ident) -#define Start_closure(v) (((struct caml_thread_descr *)(v))->start_closure) +#define Clos(v) (((struct caml_thread_descr *)(v))->start_closure) #define Terminated(v) (((struct caml_thread_descr *)(v))->terminated) -/* The infos on threads (allocated via caml_stat_alloc()) */ - +/* structure holding runtime state */ struct caml_thread_struct { - value descr; /* The heap-allocated descriptor (root) */ - struct caml_thread_struct * next; /* Double linking of running threads */ - struct caml_thread_struct * prev; -#ifdef NATIVE_CODE - char * top_of_stack; /* Top of stack for this thread (approx.) */ - char * bottom_of_stack; /* Saved value of Caml_state->bottom_of_stack */ - uintnat last_retaddr; /* Saved value of Caml_state->last_return_address */ - value * gc_regs; /* Saved value of Caml_state->gc_regs */ - char * exception_pointer; /* Saved value of Caml_state->exception_pointer */ - struct caml__roots_block * local_roots; /* Saved value of local_roots */ - struct longjmp_buffer * exit_buf; /* For thread exit */ -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - value internal_spacetime_trie_root; - value internal_spacetime_finaliser_trie_root; - value* spacetime_trie_node_ptr; - value* spacetime_finaliser_trie_root; -#endif -#else - value * stack_low; /* The execution stack for this thread */ - value * stack_high; - value * stack_threshold; - value * sp; /* Saved value of Caml_state->extern_sp for this thread */ - value * trapsp; /* Saved value of Caml_state->trapsp for this thread */ - /* Saved value of Caml_state->local_roots */ - struct caml__roots_block * local_roots; - struct longjmp_buffer * external_raise; /* Saved Caml_state->external_raise */ -#endif - int backtrace_pos; /* Saved Caml_state->backtrace_pos */ - backtrace_slot * backtrace_buffer; /* Saved Caml_state->backtrace_buffer */ - value backtrace_last_exn; /* Saved Caml_state->backtrace_last_exn (root) */ - struct caml_memprof_th_ctx memprof_ctx; -}; -typedef struct caml_thread_struct * caml_thread_t; + value descr; -/* The "head" of the circular list of thread descriptors */ -static caml_thread_t all_threads = NULL; + struct caml_thread_struct * next; + struct caml_thread_struct * prev; -/* The descriptor for the currently executing thread */ -static caml_thread_t curr_thread = NULL; + int domain_id; + + struct stack_info* current_stack; + struct c_stack_link* c_stack; + struct caml__roots_block *local_roots; + struct longjmp_buffer *exit_buf; + int backtrace_pos; + code_t * backtrace_buffer; + caml_root backtrace_last_exn; + value * gc_regs; + value * gc_regs_buckets; + value ** gc_regs_slot; + void * exn_handler; + + #ifndef NATIVE_CODE + intnat trap_sp_off; + intnat trap_barrier_off; + struct caml_exception_context* external_raise; + #endif -/* The master lock protecting the OCaml runtime system */ -static st_masterlock caml_master_lock; +}; -/* Whether the "tick" thread is already running */ -static int caml_tick_thread_running = 0; +typedef struct caml_thread_struct* caml_thread_t; -/* The thread identifier of the "tick" thread */ -static st_thread_id caml_tick_thread_id; +/* overall table for threads accross domains */ +struct caml_thread_table { + caml_thread_t all_threads; + caml_thread_t current_thread; + st_tlskey thread_key; + st_masterlock thread_lock; +}; -/* The key used for storing the thread descriptor in the specific data - of the corresponding system thread. */ -static st_tlskey thread_descriptor_key; +/* thread_table instance, up to Max_domains */ +static struct caml_thread_table thread_table[Max_domains]; -/* The key used for unlocking I/O channels on exceptions */ -static st_tlskey last_channel_locked_key; +#define Thread_main_lock thread_table[Caml_state->id].thread_lock +#define Thread_key thread_table[Caml_state->id].thread_key +#define All_threads thread_table[Caml_state->id].all_threads +#define Current_thread thread_table[Caml_state->id].current_thread /* Identifier for next thread creation */ -static intnat thread_next_ident = 0; +static atomic_uintnat thread_next_id; /* Forward declarations */ -static value caml_threadstatus_new (void); -static void caml_threadstatus_terminate (value); -static st_retcode caml_threadstatus_wait (value); + +static value caml_threadstatus_new (value unit); +static void caml_threadstatus_terminate (value wrapper); +static void caml_threadstatus_wait (value wrapper); /* Imports from the native-code runtime system */ #ifdef NATIVE_CODE @@ -144,198 +115,88 @@ extern void (*caml_termination_hook)(void); /* Hook for scanning the stacks of the other threads */ -static void (*prev_scan_roots_hook) (scanning_action); +static void (*prev_scan_roots_hook) (scanning_action, void *, struct domain *); -static void caml_thread_scan_roots(scanning_action action) +static void caml_thread_scan_roots(scanning_action action, void *fdata, struct domain *self) { caml_thread_t th; - th = curr_thread; - do { - (*action)(th->descr, &th->descr); - (*action)(th->backtrace_last_exn, &th->backtrace_last_exn); - /* Don't rescan the stack of the current thread, it was done already */ - if (th != curr_thread) { -#ifdef NATIVE_CODE - if (th->bottom_of_stack != NULL) - caml_do_local_roots(action, th->bottom_of_stack, th->last_retaddr, - th->gc_regs, th->local_roots); -#else - caml_do_local_roots(action, th->sp, th->stack_high, th->local_roots); -#endif - } - th = th->next; - } while (th != curr_thread); - /* Hook */ - if (prev_scan_roots_hook != NULL) (*prev_scan_roots_hook)(action); -} - -/* Saving and restoring runtime state in curr_thread */ - -Caml_inline void caml_thread_save_runtime_state(void) -{ -#ifdef NATIVE_CODE - curr_thread->top_of_stack = Caml_state->top_of_stack; - curr_thread->bottom_of_stack = Caml_state->bottom_of_stack; - curr_thread->last_retaddr = Caml_state->last_return_address; - curr_thread->gc_regs = Caml_state->gc_regs; - curr_thread->exception_pointer = Caml_state->exception_pointer; -#ifdef WITH_SPACETIME - curr_thread->spacetime_trie_node_ptr - = caml_spacetime_trie_node_ptr; - curr_thread->spacetime_finaliser_trie_root - = caml_spacetime_finaliser_trie_root; -#endif -#else - curr_thread->stack_low = Caml_state->stack_low; - curr_thread->stack_high = Caml_state->stack_high; - curr_thread->stack_threshold = Caml_state->stack_threshold; - curr_thread->sp = Caml_state->extern_sp; - curr_thread->trapsp = Caml_state->trapsp; - curr_thread->external_raise = Caml_state->external_raise; -#endif - curr_thread->local_roots = Caml_state->local_roots; - curr_thread->backtrace_pos = Caml_state->backtrace_pos; - curr_thread->backtrace_buffer = Caml_state->backtrace_buffer; - curr_thread->backtrace_last_exn = Caml_state->backtrace_last_exn; - caml_memprof_save_th_ctx(&curr_thread->memprof_ctx); -} - -Caml_inline void caml_thread_restore_runtime_state(void) -{ -#ifdef NATIVE_CODE - Caml_state->top_of_stack = curr_thread->top_of_stack; - Caml_state->bottom_of_stack= curr_thread->bottom_of_stack; - Caml_state->last_return_address = curr_thread->last_retaddr; - Caml_state->gc_regs = curr_thread->gc_regs; - Caml_state->exception_pointer = curr_thread->exception_pointer; -#ifdef WITH_SPACETIME - caml_spacetime_trie_node_ptr - = curr_thread->spacetime_trie_node_ptr; - caml_spacetime_finaliser_trie_root - = curr_thread->spacetime_finaliser_trie_root; -#endif -#else - Caml_state->stack_low = curr_thread->stack_low; - Caml_state->stack_high = curr_thread->stack_high; - Caml_state->stack_threshold = curr_thread->stack_threshold; - Caml_state->extern_sp = curr_thread->sp; - Caml_state->trapsp = curr_thread->trapsp; - Caml_state->external_raise = curr_thread->external_raise; -#endif - Caml_state->local_roots = curr_thread->local_roots; - Caml_state->backtrace_pos = curr_thread->backtrace_pos; - Caml_state->backtrace_buffer = curr_thread->backtrace_buffer; - Caml_state->backtrace_last_exn = curr_thread->backtrace_last_exn; - caml_memprof_restore_th_ctx(&curr_thread->memprof_ctx); + th = Current_thread; + + // a GC could be triggered before current_dec is initialized + if (th != NULL) { + do { + (*action)(fdata, th->descr, &th->descr); + + if (th != Current_thread) { + if (th->current_stack != NULL) + caml_do_local_roots(action, fdata, th->local_roots, th->current_stack, th->gc_regs); + } + th = th->next; + } while (th != Current_thread); + + }; + + if (prev_scan_roots_hook != NULL) (*prev_scan_roots_hook)(action, fdata, self); + + return; +} + +void caml_thread_save_runtime_state(void) +{ + Current_thread->current_stack = Caml_state->current_stack; + Current_thread->c_stack = Caml_state->c_stack; + Current_thread->gc_regs = Caml_state->gc_regs; + Current_thread->gc_regs_buckets = Caml_state->gc_regs_buckets; + Current_thread->gc_regs_slot = Caml_state->gc_regs_slot; + Current_thread->exn_handler = Caml_state->exn_handler; + Current_thread->local_roots = Caml_state->local_roots; + Current_thread->backtrace_pos = Caml_state->backtrace_pos; + Current_thread->backtrace_buffer = Caml_state->backtrace_buffer; + Current_thread->backtrace_last_exn = Caml_state->backtrace_last_exn; + #ifndef NATIVE_CODE + Current_thread->trap_sp_off = Caml_state->trap_sp_off; + Current_thread->trap_barrier_off = Caml_state->trap_barrier_off; + Current_thread->external_raise = Caml_state->external_raise; + #endif +} + +void caml_thread_restore_runtime_state(void) +{ + Caml_state->current_stack = Current_thread->current_stack; + Caml_state->c_stack = Current_thread->c_stack; + Caml_state->gc_regs = Current_thread->gc_regs; + Caml_state->gc_regs_buckets = Current_thread->gc_regs_buckets; + Caml_state->gc_regs_slot = Current_thread->gc_regs_slot; + Caml_state->exn_handler = Current_thread->exn_handler; + Caml_state->local_roots = Current_thread->local_roots; + Caml_state->backtrace_pos = Current_thread->backtrace_pos; + Caml_state->backtrace_buffer = Current_thread->backtrace_buffer; + Caml_state->backtrace_last_exn = Current_thread->backtrace_last_exn; + #ifndef NATIVE_CODE + Caml_state->trap_sp_off = Current_thread->trap_sp_off; + Caml_state->trap_barrier_off = Current_thread->trap_barrier_off; + Caml_state->external_raise = Current_thread->external_raise; + #endif } /* Hooks for caml_enter_blocking_section and caml_leave_blocking_section */ - static void caml_thread_enter_blocking_section(void) { - /* Save the current runtime state in the thread descriptor - of the current thread */ + Current_thread = st_tls_get(Thread_key); caml_thread_save_runtime_state(); - /* Tell other threads that the runtime is free */ - st_masterlock_release(&caml_master_lock); + st_tls_set(Thread_key, Current_thread); + st_masterlock_release(&Thread_main_lock); } static void caml_thread_leave_blocking_section(void) { - /* Wait until the runtime is free */ - st_masterlock_acquire(&caml_master_lock); - /* Update curr_thread to point to the thread descriptor corresponding - to the thread currently executing */ - curr_thread = st_tls_get(thread_descriptor_key); - /* Restore the runtime state from the curr_thread descriptor */ + st_masterlock_acquire(&Thread_main_lock); + Current_thread = st_tls_get(Thread_key); caml_thread_restore_runtime_state(); } -static int caml_thread_try_leave_blocking_section(void) -{ - /* Disable immediate processing of signals (PR#3659). - try_leave_blocking_section always fails, forcing the signal to be - recorded and processed at the next leave_blocking_section or - polling. */ - return 0; -} - -/* Hooks for I/O locking */ - -static void caml_io_mutex_free(struct channel *chan) -{ - st_mutex mutex = chan->mutex; - if (mutex != NULL) { - st_mutex_destroy(mutex); - chan->mutex = NULL; - } -} - -static void caml_io_mutex_lock(struct channel *chan) -{ - st_mutex mutex = chan->mutex; - - if (mutex == NULL) { - st_check_error(st_mutex_create(&mutex), "channel locking"); /*PR#7038*/ - chan->mutex = mutex; - } - /* PR#4351: first try to acquire mutex without releasing the master lock */ - if (st_mutex_trylock(mutex) == PREVIOUSLY_UNLOCKED) { - st_tls_set(last_channel_locked_key, (void *) chan); - return; - } - /* If unsuccessful, block on mutex */ - caml_enter_blocking_section(); - st_mutex_lock(mutex); - /* Problem: if a signal occurs at this point, - and the signal handler raises an exception, we will not - unlock the mutex. The alternative (doing the setspecific - before locking the mutex is also incorrect, since we could - then unlock a mutex that is unlocked or locked by someone else. */ - st_tls_set(last_channel_locked_key, (void *) chan); - caml_leave_blocking_section(); -} - -static void caml_io_mutex_unlock(struct channel *chan) -{ - st_mutex_unlock(chan->mutex); - st_tls_set(last_channel_locked_key, NULL); -} - -static void caml_io_mutex_unlock_exn(void) -{ - struct channel * chan = st_tls_get(last_channel_locked_key); - if (chan != NULL) caml_io_mutex_unlock(chan); -} - -/* Hook for estimating stack usage */ - -static uintnat (*prev_stack_usage_hook)(void); - -static uintnat caml_thread_stack_usage(void) -{ - uintnat sz; - caml_thread_t th; - - /* Don't add stack for current thread, this is done elsewhere */ - for (sz = 0, th = curr_thread->next; - th != curr_thread; - th = th->next) { -#ifdef NATIVE_CODE - if(th->top_of_stack != NULL && th->bottom_of_stack != NULL && - th->top_of_stack > th->bottom_of_stack) - sz += (value *) th->top_of_stack - (value *) th->bottom_of_stack; -#else - sz += th->stack_high - th->sp; -#endif - } - if (prev_stack_usage_hook != NULL) - sz += prev_stack_usage_hook(); - return sz; -} - /* Create and setup a new thread info block. This block has no associated thread descriptor and is not inserted in the list of threads. */ @@ -343,44 +204,30 @@ static uintnat caml_thread_stack_usage(void) static caml_thread_t caml_thread_new_info(void) { caml_thread_t th; + struct domain *d; + + d = caml_domain_self(); + th = NULL; th = (caml_thread_t) caml_stat_alloc_noexc(sizeof(struct caml_thread_struct)); if (th == NULL) return NULL; - th->descr = Val_unit; /* filled later */ -#ifdef NATIVE_CODE - th->bottom_of_stack = NULL; - th->top_of_stack = NULL; - th->last_retaddr = 1; - th->exception_pointer = NULL; + + th->descr = Val_unit; + th->current_stack = caml_alloc_main_stack(Stack_size / sizeof(value));; + th->c_stack = NULL; + th->exn_handler = NULL; th->local_roots = NULL; th->exit_buf = NULL; -#ifdef WITH_SPACETIME - /* CR-someday mshinwell: The commented-out changes here are for multicore, - where we think we should have one trie per domain. */ - th->internal_spacetime_trie_root = Val_unit; - th->spacetime_trie_node_ptr = - &caml_spacetime_trie_root; /* &th->internal_spacetime_trie_root; */ - th->internal_spacetime_finaliser_trie_root = Val_unit; - th->spacetime_finaliser_trie_root - = caml_spacetime_finaliser_trie_root; - /* &th->internal_spacetime_finaliser_trie_root; */ - caml_spacetime_register_thread( - th->spacetime_trie_node_ptr, - th->spacetime_finaliser_trie_root); -#endif -#else - /* Allocate the stacks */ - th->stack_low = (value *) caml_stat_alloc(Thread_stack_size); - th->stack_high = th->stack_low + Thread_stack_size / sizeof(value); - th->stack_threshold = th->stack_low + Stack_threshold / sizeof(value); - th->sp = th->stack_high; - th->trapsp = th->stack_high; - th->local_roots = NULL; - th->external_raise = NULL; -#endif th->backtrace_pos = 0; th->backtrace_buffer = NULL; - th->backtrace_last_exn = Val_unit; - caml_memprof_init_th_ctx(&th->memprof_ctx); + th->backtrace_last_exn = caml_create_root(Val_unit); + th->domain_id = d->state->id; + + #ifndef NATIVE_CODE + th->trap_sp_off = 1; + th->trap_barrier_off = 2; + th->external_raise = NULL; + #endif + return th; } @@ -391,14 +238,12 @@ static value caml_thread_new_descriptor(value clos) value mu = Val_unit; value descr; Begin_roots2 (clos, mu) - /* Create and initialize the termination semaphore */ - mu = caml_threadstatus_new(); - /* Create a descriptor for the new thread */ + mu = caml_threadstatus_new(Val_unit); descr = caml_alloc_small(3, 0); - Ident(descr) = Val_long(thread_next_ident); - Start_closure(descr) = clos; + Ident(descr) = Val_long(atomic_load_acq(&thread_next_id)); + Clos(descr) = clos; Terminated(descr) = mu; - thread_next_ident++; + atomic_fetch_add(&thread_next_id, +1); End_roots(); return descr; } @@ -409,211 +254,195 @@ static value caml_thread_new_descriptor(value clos) static void caml_thread_remove_info(caml_thread_t th) { if (th->next == th) - all_threads = NULL; /* last OCaml thread exiting */ - else if (all_threads == th) - all_threads = th->next; /* PR#5295 */ + All_threads = NULL; + else if (All_threads == th) + All_threads = th->next; + th->next->prev = th->prev; th->prev->next = th->next; -#ifndef NATIVE_CODE - caml_stat_free(th->stack_low); -#endif - if (th->backtrace_buffer != NULL) caml_stat_free(th->backtrace_buffer); -#ifndef WITH_SPACETIME + caml_free_stack(th->current_stack); + caml_delete_root(th->backtrace_last_exn); caml_stat_free(th); - /* CR-soon mshinwell: consider what to do about the Spacetime trace. Could - perhaps have a hook to save a snapshot on thread termination. - For the moment we can't even free [th], since it contains the trie - roots. */ -#endif + return; } /* Reinitialize the thread machinery after a fork() (PR#4577) */ +/* TODO(engil): more work on the multicore fork machinery. */ static void caml_thread_reinitialize(void) { - caml_thread_t thr, next; - struct channel * chan; + caml_thread_t th, next; - /* Remove all other threads (now nonexistent) - from the doubly-linked list of threads */ - thr = curr_thread->next; - while (thr != curr_thread) { - next = thr->next; - caml_stat_free(thr); - thr = next; - } - curr_thread->next = curr_thread; - curr_thread->prev = curr_thread; - all_threads = curr_thread; - /* Reinitialize the master lock machinery, - just in case the fork happened while other threads were doing - caml_leave_blocking_section */ - st_masterlock_init(&caml_master_lock); - /* Tick thread is not currently running in child process, will be - re-created at next Thread.create */ - caml_tick_thread_running = 0; - /* Destroy all IO mutexes; will be reinitialized on demand */ - for (chan = caml_all_opened_channels; - chan != NULL; - chan = chan->next) { - if (chan->mutex != NULL) { - st_mutex_destroy(chan->mutex); - chan->mutex = NULL; - } + th = Current_thread->next; + while (th != Current_thread) { + next = th->next; + caml_free_stack(th->current_stack); + caml_delete_root(th->backtrace_last_exn); + caml_stat_free(th); + th = next; } + Current_thread->next = Current_thread; + Current_thread->prev = Current_thread; + All_threads = Current_thread; + + // within the child, the domain_lock needs to be reset + // and acquired. + caml_reset_domain_lock(); + caml_acquire_domain_lock(); + // master_lock needs to be initialized again. + // this process will also be the effective owner of the lock. + // so there is no need to run st_masterlock_acquire (busy = 1) + st_masterlock_init(&Thread_main_lock); +} + +CAMLprim value caml_thread_initialize(value unit); +static void caml_thread_initialize_domain(); + +/* To initialize the thread machinery on a newly created domain. */ +/* FIXME(engil): it may be better to just initialize the machinery for every */ +/* domain at startup */ +static void caml_thread_domain_start_hook(void) { + caml_thread_initialize_domain(); +} + +static void caml_thread_domain_stop_hook(void) { + // This hook will clean up the initial domain's thread descriptor. + // The assumption is that it is the only remaining link in the threading chain + // (as every other threads either go through caml_thread_stop or + // caml_c_thread_unregister.) + caml_stat_free(Current_thread); + Current_thread = NULL; } -/* Initialize the thread machinery */ +static void caml_thread_initialize_domain() +{ + caml_thread_t new_thread; + + st_masterlock_init(&Thread_main_lock); + + new_thread = + (caml_thread_t) caml_stat_alloc_noexc(sizeof(struct caml_thread_struct)); + + new_thread->descr = caml_thread_new_descriptor(Val_unit); + new_thread->next = new_thread; + new_thread->prev = new_thread; + + #ifdef NATIVE_CODE + new_thread->exit_buf = &caml_termination_jmpbuf; + #endif + st_tls_newkey(&Thread_key); + st_tls_set(Thread_key, (void *) new_thread); + + All_threads = new_thread; + Current_thread = new_thread; + + return; +} + +// This setup function is called as an entrypoint to the Thread module. +// This will setup the global variables and hooks for systhreads +// cooperate with the runtime system, after initializing +// the thread chaining. CAMLprim value caml_thread_initialize(value unit) /* ML */ { - /* Protect against repeated initialization (PR#3532) */ - if (curr_thread != NULL) return Val_unit; - /* OS-specific initialization */ - st_initialize(); - /* Initialize and acquire the master lock */ - st_masterlock_init(&caml_master_lock); - /* Initialize the keys */ - st_tls_newkey(&thread_descriptor_key); - st_tls_newkey(&last_channel_locked_key); - /* Set up a thread info block for the current thread */ - curr_thread = - (caml_thread_t) caml_stat_alloc(sizeof(struct caml_thread_struct)); - curr_thread->descr = caml_thread_new_descriptor(Val_unit); - curr_thread->next = curr_thread; - curr_thread->prev = curr_thread; - all_threads = curr_thread; - curr_thread->backtrace_last_exn = Val_unit; -#ifdef NATIVE_CODE - curr_thread->exit_buf = &caml_termination_jmpbuf; -#endif - /* The stack-related fields will be filled in at the next - caml_enter_blocking_section */ - /* Associate the thread descriptor with the thread */ - st_tls_set(thread_descriptor_key, (void *) curr_thread); - /* Set up the hooks */ + CAMLparam0(); + + // We first initialize the thread chaining. + caml_thread_initialize_domain(); + prev_scan_roots_hook = caml_scan_roots_hook; caml_scan_roots_hook = caml_thread_scan_roots; caml_enter_blocking_section_hook = caml_thread_enter_blocking_section; caml_leave_blocking_section_hook = caml_thread_leave_blocking_section; - caml_try_leave_blocking_section_hook = caml_thread_try_leave_blocking_section; -#ifdef NATIVE_CODE - caml_termination_hook = st_thread_exit; -#endif - caml_channel_mutex_free = caml_io_mutex_free; - caml_channel_mutex_lock = caml_io_mutex_lock; - caml_channel_mutex_unlock = caml_io_mutex_unlock; - caml_channel_mutex_unlock_exn = caml_io_mutex_unlock_exn; - prev_stack_usage_hook = caml_stack_usage_hook; - caml_stack_usage_hook = caml_thread_stack_usage; - /* Set up fork() to reinitialize the thread machinery in the child - (PR#4577) */ + caml_domain_start_hook = caml_thread_domain_start_hook; + caml_domain_stop_hook = caml_thread_domain_stop_hook; + st_atfork(caml_thread_reinitialize); - return Val_unit; -} -/* Cleanup the thread machinery when the runtime is shut down. Joining the tick - thread take 25ms on average / 50ms in the worst case, so we don't do it on - program exit. */ + + CAMLreturn(Val_unit); +} CAMLprim value caml_thread_cleanup(value unit) /* ML */ { - if (caml_tick_thread_running){ - caml_tick_thread_stop = 1; - st_thread_join(caml_tick_thread_id); - caml_tick_thread_stop = 0; - caml_tick_thread_running = 0; - } return Val_unit; } - /* Thread cleanup at termination */ static void caml_thread_stop(void) { - /* PR#5188, PR#7220: some of the global runtime state may have - changed as the thread was running, so we save it in the - curr_thread data to make sure that the cleanup logic - below uses accurate information. */ - caml_thread_save_runtime_state(); - /* Tell memprof that this thread is terminating. */ - caml_memprof_stop_th_ctx(&curr_thread->memprof_ctx); - /* Signal that the thread has terminated */ - caml_threadstatus_terminate(Terminated(curr_thread->descr)); - /* Remove th from the doubly-linked list of threads and free its info block */ - caml_thread_remove_info(curr_thread); - /* OS-specific cleanups */ - st_thread_cleanup(); - /* Release the runtime system */ - st_masterlock_release(&caml_master_lock); + caml_thread_t next = Current_thread->next; + + // The main domain thread does not go through caml_thread_stop. + // There is always one more thread in the chaining at this point in time. + Assert(next != Current_thread); + + caml_threadstatus_terminate(Terminated(Current_thread->descr)); + caml_thread_remove_info(Current_thread); + // FIXME: tricky bit with backup thread + // Normally we expect the next thread to kick in and resume operation + // by first setting Current_thread to the right TLS dec data. + // However it may very well be that there's no runnable dec next + // (eg: next dec is blocking.), so we set it to next for now to give a + // valid state to the backup thread. + Current_thread = next; + + caml_thread_restore_runtime_state(); + st_masterlock_release(&Thread_main_lock); } /* Create a thread */ -static ST_THREAD_FUNCTION caml_thread_start(void * arg) +static void * caml_thread_start(void * v) { - caml_thread_t th = (caml_thread_t) arg; + caml_thread_t th = (caml_thread_t) v; value clos; #ifdef NATIVE_CODE struct longjmp_buffer termination_buf; - char tos; - /* Record top of stack (approximative) */ - th->top_of_stack = &tos; #endif - /* Associate the thread descriptor with the thread */ - st_tls_set(thread_descriptor_key, (void *) th); - /* Acquire the global mutex */ - caml_leave_blocking_section(); - caml_setup_stack_overflow_detection(); + caml_init_domain_self(th->domain_id); + + st_tls_set(Thread_key, th); + + st_masterlock_acquire(&Thread_main_lock); + Current_thread = st_tls_get(Thread_key); + caml_thread_restore_runtime_state(); + #ifdef NATIVE_CODE /* Setup termination handler (for caml_thread_exit) */ if (sigsetjmp(termination_buf.buf, 0) == 0) { - th->exit_buf = &termination_buf; + Current_thread->exit_buf = &termination_buf; #endif - /* Callback the closure */ - clos = Start_closure(th->descr); - caml_modify(&(Start_closure(th->descr)), Val_unit); - caml_callback_exn(clos, Val_unit); - caml_thread_stop(); + clos = Clos(Current_thread->descr); + caml_modify(&(Clos(Current_thread->descr)), Val_unit); + caml_callback_exn(clos, Val_unit); + caml_thread_stop(); #ifdef NATIVE_CODE } #endif - /* The thread now stops running */ return 0; } CAMLprim value caml_thread_new(value clos) /* ML */ { + CAMLparam1(clos); caml_thread_t th; - st_retcode err; - /* Create a thread info block */ th = caml_thread_new_info(); - if (th == NULL) caml_raise_out_of_memory(); - /* Equip it with a thread descriptor */ th->descr = caml_thread_new_descriptor(clos); - /* Add thread info block to the list of threads */ - th->next = curr_thread->next; - th->prev = curr_thread; - curr_thread->next->prev = th; - curr_thread->next = th; - /* Create the new thread */ - err = st_thread_create(NULL, caml_thread_start, (void *) th); - if (err != 0) { - /* Creation failed, remove thread info block from list of threads */ - caml_thread_remove_info(th); - st_check_error(err, "Thread.create"); - } - /* Create the tick thread if not already done. - Because of PR#4666, we start the tick thread late, only when we create - the first additional thread in the current process*/ - if (! caml_tick_thread_running) { - err = st_thread_create(&caml_tick_thread_id, caml_thread_tick, NULL); - st_check_error(err, "Thread.create"); - caml_tick_thread_running = 1; - } - return th->descr; + + th->next = Current_thread->next; + th->prev = Current_thread; + + Current_thread->next->prev = th; + Current_thread->next = th; + + st_thread_create(NULL, caml_thread_start, (void *) th); + // FIXME: check return from create + + CAMLreturn(th->descr); } /* Register a thread already created from C */ @@ -621,43 +450,38 @@ CAMLprim value caml_thread_new(value clos) /* ML */ CAMLexport int caml_c_thread_register(void) { caml_thread_t th; - st_retcode err; /* Already registered? */ - if (st_tls_get(thread_descriptor_key) != NULL) return 0; + if (Caml_state == NULL) { + caml_init_domain_self(0); + }; + if (st_tls_get(Thread_key) != NULL) return 0; + /* Take master lock to protect access to the runtime */ + st_masterlock_acquire(&Thread_main_lock); /* Create a thread info block */ th = caml_thread_new_info(); - if (th == NULL) return 0; -#ifdef NATIVE_CODE - th->top_of_stack = (char *) &err; -#endif - /* Take master lock to protect access to the chaining of threads */ - st_masterlock_acquire(&caml_master_lock); + /* If it fails, we release the lock and return an error. */ + if (th == NULL) { + st_masterlock_release(&Thread_main_lock); + return 0; + } /* Add thread info block to the list of threads */ - if (all_threads == NULL) { + if (All_threads == NULL) { th->next = th; th->prev = th; - all_threads = th; + All_threads = th; } else { - th->next = all_threads->next; - th->prev = all_threads; - all_threads->next->prev = th; - all_threads->next = th; + th->next = All_threads->next; + th->prev = All_threads; + All_threads->next->prev = th; + All_threads->next = th; } /* Associate the thread descriptor with the thread */ - st_tls_set(thread_descriptor_key, (void *) th); - /* Release the master lock */ - st_masterlock_release(&caml_master_lock); - /* Now we can re-enter the run-time system and heap-allocate the descriptor */ - caml_leave_blocking_section(); + st_tls_set(Thread_key, (void *) th); + /* Allocate the thread descriptor on the heap */ th->descr = caml_thread_new_descriptor(Val_unit); /* no closure */ - /* Create the tick thread if not already done. */ - if (! caml_tick_thread_running) { - err = st_thread_create(&caml_tick_thread_id, caml_thread_tick, NULL); - if (err == 0) caml_tick_thread_running = 1; - } - /* Exit the run-time system */ - caml_enter_blocking_section(); + /* Release the master lock */ + st_masterlock_release(&Thread_main_lock); return 1; } @@ -666,17 +490,24 @@ CAMLexport int caml_c_thread_register(void) CAMLexport int caml_c_thread_unregister(void) { - caml_thread_t th = st_tls_get(thread_descriptor_key); + caml_thread_t th; + + /* If Caml_state is not set, this thread was likely not registered */ + if (Caml_state == NULL) return 0; + + th = st_tls_get(Thread_key); /* Not registered? */ if (th == NULL) return 0; /* Wait until the runtime is available */ - st_masterlock_acquire(&caml_master_lock); - /* Forget the thread descriptor */ - st_tls_set(thread_descriptor_key, NULL); + st_masterlock_acquire(&Thread_main_lock); + /* Forget the thread descriptor */ + st_tls_set(Thread_key, NULL); /* Remove thread info block from list of threads, and free it */ caml_thread_remove_info(th); + Current_thread = All_threads; + caml_thread_restore_runtime_state(); /* Release the runtime */ - st_masterlock_release(&caml_master_lock); + st_masterlock_release(&Thread_main_lock); return 1; } @@ -684,16 +515,14 @@ CAMLexport int caml_c_thread_unregister(void) CAMLprim value caml_thread_self(value unit) /* ML */ { - if (curr_thread == NULL) - caml_invalid_argument("Thread.self: not initialized"); - return curr_thread->descr; + return Current_thread->descr; } /* Return the identifier of a thread */ CAMLprim value caml_thread_id(value th) /* ML */ { - return Ident(th); + return Val_long(Ident(th)); } /* Print uncaught exception and backtrace */ @@ -702,7 +531,7 @@ CAMLprim value caml_thread_uncaught_exception(value exn) /* ML */ { char * msg = caml_format_exception(exn); fprintf(stderr, "Thread %d killed on uncaught exception %s\n", - Int_val(Ident(curr_thread->descr)), msg); + Int_val(Ident(Current_thread->descr)), msg); caml_stat_free(msg); if (Caml_state->backtrace_active) caml_print_exception_backtrace(); fflush(stderr); @@ -715,48 +544,35 @@ CAMLprim value caml_thread_exit(value unit) /* ML */ { struct longjmp_buffer * exit_buf = NULL; - if (curr_thread == NULL) + if (Current_thread == NULL) caml_invalid_argument("Thread.exit: not initialized"); - /* In native code, we cannot call pthread_exit here because on some - systems this raises a C++ exception, and ocamlopt-generated stack - frames cannot be unwound. Instead, we longjmp to the thread - creation point (in caml_thread_start) or to the point in - caml_main where caml_termination_hook will be called. - Note that threads created in C then registered do not have - a creation point (exit_buf == NULL). - */ -#ifdef NATIVE_CODE - exit_buf = curr_thread->exit_buf; -#endif - caml_thread_stop(); + #ifdef NATIVE_CODE + exit_buf = Current_thread->exit_buf; + #endif + + caml_thread_stop(); + if (exit_buf != NULL) { /* Native-code and (main thread or thread created by OCaml) */ siglongjmp(exit_buf->buf, 1); } else { - /* Bytecode, or thread created from C */ st_thread_exit(); - } - return Val_unit; /* not reached */ + }; + + return Val_unit; } /* Allow re-scheduling */ CAMLprim value caml_thread_yield(value unit) /* ML */ { - if (st_masterlock_waiters(&caml_master_lock) == 0) return Val_unit; + if (atomic_load_acq(&Thread_main_lock.waiters) == 0) return Val_unit; - /* Do all the parts of a blocking section enter/leave except lock - manipulation, which we'll do more efficiently in st_thread_yield. (Since - our blocking section doesn't contain anything interesting, don't bother - with saving errno.) - */ - caml_raise_if_exception(caml_process_pending_signals_exn()); caml_thread_save_runtime_state(); - st_thread_yield(&caml_master_lock); - curr_thread = st_tls_get(thread_descriptor_key); + st_thread_yield(&Thread_main_lock); + Current_thread = st_tls_get(Thread_key); caml_thread_restore_runtime_state(); - caml_raise_if_exception(caml_process_pending_signals_exn()); return Val_unit; } @@ -765,8 +581,7 @@ CAMLprim value caml_thread_yield(value unit) /* ML */ CAMLprim value caml_thread_join(value th) /* ML */ { - st_retcode rc = caml_threadstatus_wait(Terminated(th)); - st_check_error(rc, "Thread.join"); + caml_threadstatus_wait(Terminated(th)); return Val_unit; } @@ -791,7 +606,7 @@ static intnat caml_mutex_hash(value wrapper) return (intnat) (Mutex_val(wrapper)); } -static struct custom_operations caml_mutex_ops = { +static const struct custom_operations caml_mutex_ops = { "_mutex", caml_mutex_finalize, caml_mutex_compare, @@ -804,10 +619,11 @@ static struct custom_operations caml_mutex_ops = { CAMLprim value caml_mutex_new(value unit) /* ML */ { - st_mutex mut = NULL; /* suppress warning */ + st_mutex mut = NULL; value wrapper; - st_check_error(st_mutex_create(&mut), "Mutex.create"); - wrapper = caml_alloc_custom(&caml_mutex_ops, sizeof(st_mutex *), + + st_mutex_create(&mut); + wrapper = caml_alloc_custom(&caml_mutex_ops, sizeof(caml_plat_mutex *), 0, 1); Mutex_val(wrapper) = mut; return wrapper; @@ -816,42 +632,43 @@ CAMLprim value caml_mutex_new(value unit) /* ML */ CAMLprim value caml_mutex_lock(value wrapper) /* ML */ { st_mutex mut = Mutex_val(wrapper); - st_retcode retcode; /* PR#4351: first try to acquire mutex without releasing the master lock */ - if (st_mutex_trylock(mut) == PREVIOUSLY_UNLOCKED) return Val_unit; + if (caml_plat_try_lock(mut) == MUTEX_PREVIOUSLY_UNLOCKED) return Val_unit; /* If unsuccessful, block on mutex */ - Begin_root(wrapper) /* prevent the deallocation of mutex */ + Begin_root(wrapper) caml_enter_blocking_section(); - retcode = st_mutex_lock(mut); + st_mutex_lock(mut); caml_leave_blocking_section(); End_roots(); - st_check_error(retcode, "Mutex.lock"); return Val_unit; } CAMLprim value caml_mutex_unlock(value wrapper) /* ML */ { st_mutex mut = Mutex_val(wrapper); - st_retcode retcode; /* PR#4351: no need to release and reacquire master lock */ - retcode = st_mutex_unlock(mut); - st_check_error(retcode, "Mutex.unlock"); + st_mutex_unlock(mut); return Val_unit; } CAMLprim value caml_mutex_try_lock(value wrapper) /* ML */ { st_mutex mut = Mutex_val(wrapper); - st_retcode retcode; - retcode = st_mutex_trylock(mut); - if (retcode == ALREADY_LOCKED) return Val_false; - st_check_error(retcode, "Mutex.try_lock"); + int retcode = st_mutex_trylock(mut); + if (retcode == MUTEX_ALREADY_LOCKED) return Val_false; return Val_true; } /* Conditions operations */ +// TODO: refactor the condition part in a way that makes the Condition module +// and platform code cohabit. +// st_cond_broadcast and st_cond_signal are borrowed from platform +// but do not assert on the mutex. +// The main issue is that platform conditions do rely on explicitly binding a +// mutex to the cond, which is not how Condition work. + #define Condition_val(v) (* (st_condvar *) Data_custom_val(v)) static void caml_condition_finalize(value wrapper) @@ -884,9 +701,10 @@ static struct custom_operations caml_condition_ops = { CAMLprim value caml_condition_new(value unit) /* ML */ { - st_condvar cond = NULL; /* suppress warning */ value wrapper; - st_check_error(st_condvar_create(&cond), "Condition.create"); + st_condvar cond; + + st_condvar_create(&cond); wrapper = caml_alloc_custom(&caml_condition_ops, sizeof(st_condvar *), 0, 1); Condition_val(wrapper) = cond; @@ -897,28 +715,25 @@ CAMLprim value caml_condition_wait(value wcond, value wmut) /* ML */ { st_condvar cond = Condition_val(wcond); st_mutex mut = Mutex_val(wmut); - st_retcode retcode; - Begin_roots2(wcond, wmut) /* prevent deallocation of cond and mutex */ + Begin_roots2(wcond, wmut) caml_enter_blocking_section(); - retcode = st_condvar_wait(cond, mut); + st_condvar_wait(cond, mut); caml_leave_blocking_section(); End_roots(); - st_check_error(retcode, "Condition.wait"); + return Val_unit; } CAMLprim value caml_condition_signal(value wrapper) /* ML */ { - st_check_error(st_condvar_signal(Condition_val(wrapper)), - "Condition.signal"); + st_condvar_signal(Condition_val(wrapper)); return Val_unit; } CAMLprim value caml_condition_broadcast(value wrapper) /* ML */ { - st_check_error(st_condvar_broadcast(Condition_val(wrapper)), - "Condition.broadcast"); + st_condvar_broadcast(Condition_val(wrapper)); return Val_unit; } @@ -949,15 +764,19 @@ static struct custom_operations caml_threadstatus_ops = { custom_fixed_length_default }; -static value caml_threadstatus_new (void) +static value caml_threadstatus_new (value unit) { + CAMLparam0(); + CAMLlocal1(wrapper); + + st_event ts = NULL; /* suppress warning */ - value wrapper; - st_check_error(st_event_create(&ts), "Thread.create"); + st_event_create(&ts); wrapper = caml_alloc_custom(&caml_threadstatus_ops, sizeof(st_event *), 0, 1); Threadstatus_val(wrapper) = ts; - return wrapper; + + CAMLreturn (wrapper); } static void caml_threadstatus_terminate (value wrapper) @@ -965,15 +784,15 @@ static void caml_threadstatus_terminate (value wrapper) st_event_trigger(Threadstatus_val(wrapper)); } -static st_retcode caml_threadstatus_wait (value wrapper) +static void caml_threadstatus_wait (value wrapper) { st_event ts = Threadstatus_val(wrapper); - st_retcode retcode; Begin_roots1(wrapper) /* prevent deallocation of ts */ caml_enter_blocking_section(); - retcode = st_event_wait(ts); + st_event_wait(ts); caml_leave_blocking_section(); End_roots(); - return retcode; + + return; } diff --git a/otherlibs/systhreads/st_win32.h b/otherlibs/systhreads/st_win32.h deleted file mode 100644 index ab4e2b5915..0000000000 --- a/otherlibs/systhreads/st_win32.h +++ /dev/null @@ -1,432 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 2009 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* Win32 implementation of the "st" interface */ - -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0400 -#include <windows.h> -#include <winerror.h> -#include <stdio.h> -#include <signal.h> - -#include <caml/osdeps.h> - -#if 1 -#define TRACE(x) -#define TRACE1(x,y) -#else -#include <stdio.h> -#define TRACE(x) printf("%d: %s\n", GetCurrentThreadId(), x); fflush(stdout) -#define TRACE1(x,y) printf("%d: %s %p\n", GetCurrentThreadId(), x, (void *)y); \ - fflush(stdout) -#endif - -typedef DWORD st_retcode; - -#define SIGPREEMPTION SIGTERM - -/* Thread-local storage associating a Win32 event to every thread. */ -static DWORD st_thread_sem_key; - -/* OS-specific initialization */ - -static DWORD st_initialize(void) -{ - st_thread_sem_key = TlsAlloc(); - if (st_thread_sem_key == TLS_OUT_OF_INDEXES) - return GetLastError(); - else - return 0; -} - -/* Thread creation. Created in detached mode if [res] is NULL. */ - -typedef HANDLE st_thread_id; - -static DWORD st_thread_create(st_thread_id * res, - LPTHREAD_START_ROUTINE fn, void * arg) -{ - HANDLE h = CreateThread(NULL, 0, fn, arg, 0, NULL); - TRACE1("st_thread_create", h); - if (h == NULL) return GetLastError(); - if (res == NULL) - CloseHandle(h); - else - *res = h; - return 0; -} - -#define ST_THREAD_FUNCTION DWORD WINAPI - -/* Cleanup at thread exit */ - -static void st_thread_cleanup(void) -{ - HANDLE ev = (HANDLE) TlsGetValue(st_thread_sem_key); - if (ev != NULL) CloseHandle(ev); -} - -/* Thread termination */ - -CAMLnoreturn_start -static void st_thread_exit(void) -CAMLnoreturn_end; - -static void st_thread_exit(void) -{ - TRACE("st_thread_exit"); - ExitThread(0); -} - -static void st_thread_join(st_thread_id thr) -{ - TRACE1("st_thread_join", h); - WaitForSingleObject(thr, INFINITE); -} - -/* Thread-specific state */ - -typedef DWORD st_tlskey; - -static DWORD st_tls_newkey(st_tlskey * res) -{ - *res = TlsAlloc(); - if (*res == TLS_OUT_OF_INDEXES) - return GetLastError(); - else - return 0; -} - -Caml_inline void * st_tls_get(st_tlskey k) -{ - return TlsGetValue(k); -} - -Caml_inline void st_tls_set(st_tlskey k, void * v) -{ - TlsSetValue(k, v); -} - -/* The master lock. */ - -typedef CRITICAL_SECTION st_masterlock; - -static void st_masterlock_init(st_masterlock * m) -{ - TRACE("st_masterlock_init"); - InitializeCriticalSection(m); - EnterCriticalSection(m); -} - -Caml_inline void st_masterlock_acquire(st_masterlock * m) -{ - TRACE("st_masterlock_acquire"); - EnterCriticalSection(m); - TRACE("st_masterlock_acquire (done)"); -} - -Caml_inline void st_masterlock_release(st_masterlock * m) -{ - LeaveCriticalSection(m); - TRACE("st_masterlock_released"); -} - -Caml_inline int st_masterlock_waiters(st_masterlock * m) -{ - return 1; /* info not maintained */ -} - -/* Scheduling hints */ - -Caml_inline void st_thread_yield(st_masterlock * m) -{ - LeaveCriticalSection(m); - Sleep(0); - EnterCriticalSection(m); -} - -/* Mutexes */ - -typedef CRITICAL_SECTION * st_mutex; - -static DWORD st_mutex_create(st_mutex * res) -{ - st_mutex m = caml_stat_alloc_noexc(sizeof(CRITICAL_SECTION)); - if (m == NULL) return ERROR_NOT_ENOUGH_MEMORY; - InitializeCriticalSection(m); - *res = m; - return 0; -} - -static DWORD st_mutex_destroy(st_mutex m) -{ - DeleteCriticalSection(m); - caml_stat_free(m); - return 0; -} - -Caml_inline DWORD st_mutex_lock(st_mutex m) -{ - TRACE1("st_mutex_lock", m); - EnterCriticalSection(m); - TRACE1("st_mutex_lock (done)", m); - return 0; -} - -/* Error codes with the 29th bit set are reserved for the application */ - -#define PREVIOUSLY_UNLOCKED 0 -#define ALREADY_LOCKED (1<<29) - -Caml_inline DWORD st_mutex_trylock(st_mutex m) -{ - TRACE1("st_mutex_trylock", m); - if (TryEnterCriticalSection(m)) { - TRACE1("st_mutex_trylock (success)", m); - return PREVIOUSLY_UNLOCKED; - } else { - TRACE1("st_mutex_trylock (failure)", m); - return ALREADY_LOCKED; - } -} - -Caml_inline DWORD st_mutex_unlock(st_mutex m) -{ - TRACE1("st_mutex_unlock", m); - LeaveCriticalSection(m); - return 0; -} - -/* Condition variables */ - -/* A condition variable is just a list of threads currently - waiting on this c.v. Each thread is represented by its - associated event. */ - -struct st_wait_list { - HANDLE event; /* event of the first waiting thread */ - struct st_wait_list * next; -}; - -typedef struct st_condvar_struct { - CRITICAL_SECTION lock; /* protect the data structure */ - struct st_wait_list * waiters; /* list of threads waiting */ -} * st_condvar; - -static DWORD st_condvar_create(st_condvar * res) -{ - st_condvar c = caml_stat_alloc_noexc(sizeof(struct st_condvar_struct)); - if (c == NULL) return ERROR_NOT_ENOUGH_MEMORY; - InitializeCriticalSection(&c->lock); - c->waiters = NULL; - *res = c; - return 0; -} - -static DWORD st_condvar_destroy(st_condvar c) -{ - TRACE1("st_condvar_destroy", c); - DeleteCriticalSection(&c->lock); - caml_stat_free(c); - return 0; -} - -static DWORD st_condvar_signal(st_condvar c) -{ - DWORD rc = 0; - struct st_wait_list * curr, * next; - - TRACE1("st_condvar_signal", c); - EnterCriticalSection(&c->lock); - curr = c->waiters; - if (curr != NULL) { - next = curr->next; - /* Wake up the first waiting thread */ - TRACE1("st_condvar_signal: waking up", curr->event); - if (! SetEvent(curr->event)) rc = GetLastError(); - /* Remove it from the waiting list */ - c->waiters = next; - } - LeaveCriticalSection(&c->lock); - return rc; -} - -static DWORD st_condvar_broadcast(st_condvar c) -{ - DWORD rc = 0; - struct st_wait_list * curr, * next; - - TRACE1("st_condvar_broadcast", c); - EnterCriticalSection(&c->lock); - /* Wake up all waiting threads */ - curr = c->waiters; - while (curr != NULL) { - next = curr->next; - TRACE1("st_condvar_signal: waking up", curr->event); - if (! SetEvent(curr->event)) rc = GetLastError(); - curr = next; - } - /* Remove them all from the waiting list */ - c->waiters = NULL; - LeaveCriticalSection(&c->lock); - return rc; -} - -static DWORD st_condvar_wait(st_condvar c, st_mutex m) -{ - HANDLE ev; - struct st_wait_list wait; - - TRACE1("st_condvar_wait", c); - /* Recover (or create) the event associated with the calling thread */ - ev = (HANDLE) TlsGetValue(st_thread_sem_key); - if (ev == 0) { - ev = CreateEvent(NULL, - FALSE /*auto reset*/, - FALSE /*initially unset*/, - NULL); - if (ev == NULL) return GetLastError(); - TlsSetValue(st_thread_sem_key, (void *) ev); - } - EnterCriticalSection(&c->lock); - /* Insert the current thread in the waiting list (atomically) */ - wait.event = ev; - wait.next = c->waiters; - c->waiters = &wait; - LeaveCriticalSection(&c->lock); - /* Release the mutex m */ - LeaveCriticalSection(m); - /* Wait for our event to be signaled. There is no risk of lost - wakeup, since we inserted ourselves on the waiting list of c - before releasing m */ - TRACE1("st_condvar_wait: blocking on event", ev); - if (WaitForSingleObject(ev, INFINITE) == WAIT_FAILED) - return GetLastError(); - /* Reacquire the mutex m */ - TRACE1("st_condvar_wait: restarted, acquiring mutex", m); - EnterCriticalSection(m); - TRACE1("st_condvar_wait: acquired mutex", m); - return 0; -} - -/* Triggered events */ - -typedef HANDLE st_event; - -static DWORD st_event_create(st_event * res) -{ - st_event m = - CreateEvent(NULL, TRUE/*manual reset*/, FALSE/*initially unset*/, NULL); - TRACE1("st_event_create", m); - if (m == NULL) return GetLastError(); - *res = m; - return 0; -} - -static DWORD st_event_destroy(st_event e) -{ - TRACE1("st_event_destroy", e); - if (CloseHandle(e)) - return 0; - else - return GetLastError(); -} - -static DWORD st_event_trigger(st_event e) -{ - TRACE1("st_event_trigger", e); - if (SetEvent(e)) - return 0; - else - return GetLastError(); -} - -static DWORD st_event_wait(st_event e) -{ - TRACE1("st_event_wait", e); - if (WaitForSingleObject(e, INFINITE) == WAIT_FAILED) - return GetLastError(); - else - return 0; -} - -/* Reporting errors */ - -static void st_check_error(DWORD retcode, char * msg) -{ - wchar_t err[1024]; - int errlen, msglen, ret; - value str; - - if (retcode == 0) return; - if (retcode == ERROR_NOT_ENOUGH_MEMORY) caml_raise_out_of_memory(); - ret = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - retcode, - 0, - err, - sizeof(err)/sizeof(wchar_t), - NULL); - if (! ret) { - ret = - swprintf(err, sizeof(err)/sizeof(wchar_t), L"error code %lx", retcode); - } - msglen = strlen(msg); - errlen = win_wide_char_to_multi_byte(err, ret, NULL, 0); - str = caml_alloc_string(msglen + 2 + errlen); - memmove (&Byte(str, 0), msg, msglen); - memmove (&Byte(str, msglen), ": ", 2); - win_wide_char_to_multi_byte(err, ret, &Byte(str, msglen + 2), errlen); - caml_raise_sys_error(str); -} - -/* Variable used to stop the "tick" thread */ -static volatile int caml_tick_thread_stop = 0; - -/* The tick thread: posts a SIGPREEMPTION signal periodically */ - -static DWORD WINAPI caml_thread_tick(void * arg) -{ - while(! caml_tick_thread_stop) { - Sleep(Thread_timeout); - /* The preemption signal should never cause a callback, so don't - go through caml_handle_signal(), just record signal delivery via - caml_record_signal(). */ - caml_record_signal(SIGPREEMPTION); - } - return 0; -} - -/* "At fork" processing -- none under Win32 */ - -static DWORD st_atfork(void (*fn)(void)) -{ - return 0; -} - -/* Signal handling -- none under Win32 */ - -value caml_thread_sigmask(value cmd, value sigs) /* ML */ -{ - caml_invalid_argument("Thread.sigmask not implemented"); - return Val_int(0); /* not reached */ -} - -value caml_wait_signal(value sigs) /* ML */ -{ - caml_invalid_argument("Thread.wait_signal not implemented"); - return Val_int(0); /* not reached */ -} diff --git a/otherlibs/systhreads/threads.h b/otherlibs/systhreads/threads.h index 97fd1b2746..8b2a99767f 100644 --- a/otherlibs/systhreads/threads.h +++ b/otherlibs/systhreads/threads.h @@ -59,6 +59,8 @@ CAMLextern int caml_c_thread_unregister(void); functions. Just call [caml_c_thread_register] once. Before the thread finishes, it must call [caml_c_thread_unregister]. Both functions return 1 on success, 0 on error. + In multicore OCaml, note that threads created by C code will be registered + to the domain 0 threads chaining. */ #ifdef __cplusplus diff --git a/otherlibs/unix/accept.c b/otherlibs/unix/accept.c index d02cc09a71..40ac5ed857 100644 --- a/otherlibs/unix/accept.c +++ b/otherlibs/unix/accept.c @@ -27,9 +27,9 @@ CAMLprim value unix_accept(value cloexec, value sock) { + CAMLparam1(sock); + CAMLlocal1(a); int retcode; - value res; - value a; union sock_addr_union addr; socklen_param_type addr_len; int clo = unix_cloexec_p(cloexec); @@ -48,12 +48,7 @@ CAMLprim value unix_accept(value cloexec, value sock) if (clo) unix_set_cloexec(retcode, "accept", Nothing); #endif a = alloc_sockaddr(&addr, addr_len, retcode); - Begin_root (a); - res = caml_alloc_small(2, 0); - Field(res, 0) = Val_int(retcode); - Field(res, 1) = a; - End_roots(); - return res; + CAMLreturn (caml_alloc_2(0, Val_int(retcode), a)); } #else diff --git a/otherlibs/unix/cstringv.c b/otherlibs/unix/cstringv.c index cb5eb59691..72e0d48a2d 100644 --- a/otherlibs/unix/cstringv.c +++ b/otherlibs/unix/cstringv.c @@ -23,6 +23,8 @@ char_os ** cstringvect(value arg, char * cmdname) { + CAMLparam1 (arg); + CAMLlocal1 (x); char_os ** res; mlsize_t size, i; @@ -31,10 +33,12 @@ char_os ** cstringvect(value arg, char * cmdname) if (! caml_string_is_c_safe(Field(arg, i))) unix_error(EINVAL, cmdname, Field(arg, i)); res = (char_os **) caml_stat_alloc((size + 1) * sizeof(char_os *)); - for (i = 0; i < size; i++) - res[i] = caml_stat_strdup_to_os(String_val(Field(arg, i))); + for (i = 0; i < size; i++) { + caml_read_field(arg, i, &x); + res[i] = caml_stat_strdup_to_os(String_val(x)); + } res[size] = NULL; - return res; + CAMLreturnT (char**, res); } void cstringvect_free(char_os ** v) diff --git a/otherlibs/unix/errmsg.c b/otherlibs/unix/errmsg.c index fef473ea51..73c0f112db 100644 --- a/otherlibs/unix/errmsg.c +++ b/otherlibs/unix/errmsg.c @@ -23,6 +23,6 @@ extern int error_table[]; CAMLprim value unix_error_message(value err) { int errnum; - errnum = Is_block(err) ? Int_val(Field(err, 0)) : error_table[Int_val(err)]; + errnum = Is_block(err) ? Int_field(err, 0) : error_table[Int_val(err)]; return caml_copy_string(strerror(errnum)); } diff --git a/otherlibs/unix/fork.c b/otherlibs/unix/fork.c index a244a5cf83..fc6479d01c 100644 --- a/otherlibs/unix/fork.c +++ b/otherlibs/unix/fork.c @@ -19,10 +19,15 @@ #include <caml/debugger.h> #include <caml/eventlog.h> #include "unixsupport.h" +#include <caml/domain.h> +#include <caml/fail.h> CAMLprim value unix_fork(value unit) { int ret; + if (!caml_domain_alone()) { + caml_failwith("Unix.fork may not be called while multiple domains are running"); + } CAML_EV_FLUSH(); diff --git a/otherlibs/unix/getaddrinfo.c b/otherlibs/unix/getaddrinfo.c index 4b2cd6e3a4..77a419c8dc 100644 --- a/otherlibs/unix/getaddrinfo.c +++ b/otherlibs/unix/getaddrinfo.c @@ -46,12 +46,12 @@ static value convert_addrinfo(struct addrinfo * a) memcpy(&sa.s_gen, a->ai_addr, len); vaddr = alloc_sockaddr(&sa, len, -1); vcanonname = caml_copy_string(a->ai_canonname == NULL ? "" : a->ai_canonname); - vres = caml_alloc_small(5, 0); - Field(vres, 0) = cst_to_constr(a->ai_family, socket_domain_table, 3, 0); - Field(vres, 1) = cst_to_constr(a->ai_socktype, socket_type_table, 4, 0); - Field(vres, 2) = Val_int(a->ai_protocol); - Field(vres, 3) = vaddr; - Field(vres, 4) = vcanonname; + vres = caml_alloc_5(0, + cst_to_constr(a->ai_family, socket_domain_table, 3, 0), + cst_to_constr(a->ai_socktype, socket_type_table, 4, 0), + Val_int(a->ai_protocol), + vaddr, + vcanonname); CAMLreturn(vres); } @@ -117,9 +117,7 @@ CAMLprim value unix_getaddrinfo(value vnode, value vserv, value vopts) if (retcode == 0) { for (r = res; r != NULL; r = r->ai_next) { e = convert_addrinfo(r); - v = caml_alloc_small(2, 0); - Field(v, 0) = e; - Field(v, 1) = vres; + v = caml_alloc_2(0, e, vres); vres = v; } freeaddrinfo(res); diff --git a/otherlibs/unix/getgr.c b/otherlibs/unix/getgr.c index 7d120aa5ad..a2f3b18b54 100644 --- a/otherlibs/unix/getgr.c +++ b/otherlibs/unix/getgr.c @@ -33,11 +33,8 @@ static value alloc_group_entry(struct group *entry) hence this workaround */ pass = caml_copy_string(entry->gr_passwd ? entry->gr_passwd : ""); mem = caml_copy_string_array((const char**)entry->gr_mem); - res = caml_alloc_small(4, 0); - Field(res,0) = name; - Field(res,1) = pass; - Field(res,2) = Val_int(entry->gr_gid); - Field(res,3) = mem; + res = caml_alloc_4(0, name, pass, + Val_int(entry->gr_gid), mem); End_roots(); return res; } diff --git a/otherlibs/unix/getgroups.c b/otherlibs/unix/getgroups.c index 4bccd69dca..4397963829 100644 --- a/otherlibs/unix/getgroups.c +++ b/otherlibs/unix/getgroups.c @@ -14,6 +14,7 @@ /**************************************************************************/ #include <caml/mlvalues.h> +#include <caml/memory.h> #include <caml/alloc.h> #include <caml/fail.h> diff --git a/otherlibs/unix/getnameinfo.c b/otherlibs/unix/getnameinfo.c index d3721d8c32..f5a31c886c 100644 --- a/otherlibs/unix/getnameinfo.c +++ b/otherlibs/unix/getnameinfo.c @@ -54,9 +54,7 @@ CAMLprim value unix_getnameinfo(value vaddr, value vopts) if (retcode != 0) caml_raise_not_found(); vhost = caml_copy_string(host); vserv = caml_copy_string(serv); - vres = caml_alloc_small(2, 0); - Field(vres, 0) = vhost; - Field(vres, 1) = vserv; + vres = caml_alloc_2(0, vhost, vserv); CAMLreturn(vres); } diff --git a/otherlibs/unix/getproto.c b/otherlibs/unix/getproto.c index d50c2d4a10..54d67676d1 100644 --- a/otherlibs/unix/getproto.c +++ b/otherlibs/unix/getproto.c @@ -33,10 +33,8 @@ static value alloc_proto_entry(struct protoent *entry) Begin_roots2 (name, aliases); name = caml_copy_string(entry->p_name); aliases = caml_copy_string_array((const char**)entry->p_aliases); - res = caml_alloc_small(3, 0); - Field(res,0) = name; - Field(res,1) = aliases; - Field(res,2) = Val_int(entry->p_proto); + res = caml_alloc_3(0, name, aliases, + Val_int(entry->p_proto)); End_roots(); return res; } diff --git a/otherlibs/unix/getpw.c b/otherlibs/unix/getpw.c index 0c0ec80d2d..ec5c3a7887 100644 --- a/otherlibs/unix/getpw.c +++ b/otherlibs/unix/getpw.c @@ -37,14 +37,14 @@ static value alloc_passwd_entry(struct passwd *entry) #endif dir = caml_copy_string(entry->pw_dir); shell = caml_copy_string(entry->pw_shell); - res = caml_alloc_small(7, 0); - Field(res,0) = name; - Field(res,1) = passwd; - Field(res,2) = Val_int(entry->pw_uid); - Field(res,3) = Val_int(entry->pw_gid); - Field(res,4) = gecos; - Field(res,5) = dir; - Field(res,6) = shell; + res = caml_alloc_7(0, + name, + passwd, + Val_int(entry->pw_uid), + Val_int(entry->pw_gid), + gecos, + dir, + shell); End_roots(); return res; } diff --git a/otherlibs/unix/getserv.c b/otherlibs/unix/getserv.c index 9edfa8798c..d3eb6224f4 100644 --- a/otherlibs/unix/getserv.c +++ b/otherlibs/unix/getserv.c @@ -38,11 +38,11 @@ static value alloc_service_entry(struct servent *entry) name = caml_copy_string(entry->s_name); aliases = caml_copy_string_array((const char**)entry->s_aliases); proto = caml_copy_string(entry->s_proto); - res = caml_alloc_small(4, 0); - Field(res,0) = name; - Field(res,1) = aliases; - Field(res,2) = Val_int(ntohs(entry->s_port)); - Field(res,3) = proto; + res = caml_alloc_4(0, + name, + aliases, + Val_int(ntohs(entry->s_port)), + proto); End_roots(); return res; } diff --git a/otherlibs/unix/gmtime.c b/otherlibs/unix/gmtime.c index b0c2711ab3..10eca1d7d4 100644 --- a/otherlibs/unix/gmtime.c +++ b/otherlibs/unix/gmtime.c @@ -24,16 +24,16 @@ static value alloc_tm(struct tm *tm) { value res; - res = caml_alloc_small(9, 0); - Field(res,0) = Val_int(tm->tm_sec); - Field(res,1) = Val_int(tm->tm_min); - Field(res,2) = Val_int(tm->tm_hour); - Field(res,3) = Val_int(tm->tm_mday); - Field(res,4) = Val_int(tm->tm_mon); - Field(res,5) = Val_int(tm->tm_year); - Field(res,6) = Val_int(tm->tm_wday); - Field(res,7) = Val_int(tm->tm_yday); - Field(res,8) = tm->tm_isdst ? Val_true : Val_false; + res = caml_alloc_9(0, + Val_int(tm->tm_sec), + Val_int(tm->tm_min), + Val_int(tm->tm_hour), + Val_int(tm->tm_mday), + Val_int(tm->tm_mon), + Val_int(tm->tm_year), + Val_int(tm->tm_wday), + Val_int(tm->tm_yday), + tm->tm_isdst ? Val_true : Val_false); return res; } @@ -67,22 +67,20 @@ CAMLprim value unix_mktime(value t) value tmval = Val_unit, clkval = Val_unit; Begin_roots2(tmval, clkval); - tm.tm_sec = Int_val(Field(t, 0)); - tm.tm_min = Int_val(Field(t, 1)); - tm.tm_hour = Int_val(Field(t, 2)); - tm.tm_mday = Int_val(Field(t, 3)); - tm.tm_mon = Int_val(Field(t, 4)); - tm.tm_year = Int_val(Field(t, 5)); - tm.tm_wday = Int_val(Field(t, 6)); - tm.tm_yday = Int_val(Field(t, 7)); + tm.tm_sec = Int_field(t, 0); + tm.tm_min = Int_field(t, 1); + tm.tm_hour = Int_field(t, 2); + tm.tm_mday = Int_field(t, 3); + tm.tm_mon = Int_field(t, 4); + tm.tm_year = Int_field(t, 5); + tm.tm_wday = Int_field(t, 6); + tm.tm_yday = Int_field(t, 7); tm.tm_isdst = -1; /* tm.tm_isdst = Bool_val(Field(t, 8)); */ clock = mktime(&tm); if (clock == (time_t) -1) unix_error(ERANGE, "mktime", Nothing); tmval = alloc_tm(&tm); clkval = caml_copy_double((double) clock); - res = caml_alloc_small(2, 0); - Field(res, 0) = clkval; - Field(res, 1) = tmval; + res = caml_alloc_2(0, clkval, tmval); End_roots (); return res; } diff --git a/otherlibs/unix/mmap.c b/otherlibs/unix/mmap.c index 15465ddc62..5f51a80b1e 100644 --- a/otherlibs/unix/mmap.c +++ b/otherlibs/unix/mmap.c @@ -115,7 +115,7 @@ CAMLprim value caml_unix_map_file(value vfd, value vkind, value vlayout, if (num_dims < 1 || num_dims > CAML_BA_MAX_NUM_DIMS) caml_invalid_argument("Unix.map_file: bad number of dimensions"); for (i = 0; i < num_dims; i++) { - dim[i] = Long_val(Field(vdim, i)); + dim[i] = Long_field(vdim, i); if (dim[i] == -1 && i == major_dim) continue; if (dim[i] < 0) caml_invalid_argument("Unix.map_file: negative dimension"); diff --git a/otherlibs/unix/nanosecond_stat.h b/otherlibs/unix/nanosecond_stat.h index 6abeb57e40..c1a648ef12 100644 --- a/otherlibs/unix/nanosecond_stat.h +++ b/otherlibs/unix/nanosecond_stat.h @@ -1,17 +1,15 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Jeremie Dimino, 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 Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ +/***********************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Jeremie Dimino, 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. */ +/* */ +/***********************************************************************/ /* This file is used by the configure test program nanosecond_stat.c and stat.c in this directory */ diff --git a/otherlibs/unix/pipe.c b/otherlibs/unix/pipe.c index 103f826c1c..5a3af95f1b 100644 --- a/otherlibs/unix/pipe.c +++ b/otherlibs/unix/pipe.c @@ -33,8 +33,8 @@ CAMLprim value unix_pipe(value cloexec, value vunit) unix_set_cloexec(fd[1], "pipe", Nothing); } #endif - res = caml_alloc_small(2, 0); - Field(res, 0) = Val_int(fd[0]); - Field(res, 1) = Val_int(fd[1]); + res = caml_alloc_2(0, + Val_int(fd[0]), + Val_int(fd[1])); return res; } diff --git a/otherlibs/unix/select.c b/otherlibs/unix/select.c index aaf3ddc76e..974b081325 100644 --- a/otherlibs/unix/select.c +++ b/otherlibs/unix/select.c @@ -36,7 +36,7 @@ static int fdlist_to_fdset(value fdlist, fd_set *fdset, int *maxfd) value l; FD_ZERO(fdset); for (l = fdlist; l != Val_int(0); l = Field(l, 1)) { - long fd = Long_val(Field(l, 0)); + long fd = Long_field(l, 0); /* PR#5563: harden against bad fds */ if (fd < 0 || fd >= FD_SETSIZE) return -1; FD_SET((int) fd, fdset); @@ -54,9 +54,9 @@ static value fdset_to_fdlist(value fdlist, fd_set *fdset) for (l = fdlist; l != Val_int(0); l = Field(l, 1)) { int fd = Int_val(Field(l, 0)); if (FD_ISSET(fd, fdset)) { - value newres = caml_alloc_small(2, 0); - Field(newres, 0) = Val_int(fd); - Field(newres, 1) = res; + value newres = caml_alloc_2(0, + Val_int(fd), + res); res = newres; } } @@ -97,10 +97,10 @@ CAMLprim value unix_select(value readfds, value writefds, value exceptfds, readfds = fdset_to_fdlist(readfds, &read); writefds = fdset_to_fdlist(writefds, &write); exceptfds = fdset_to_fdlist(exceptfds, &except); - res = caml_alloc_small(3, 0); - Field(res, 0) = readfds; - Field(res, 1) = writefds; - Field(res, 2) = exceptfds; + res = caml_alloc_3(0, + readfds, + writefds, + exceptfds); End_roots(); return res; } diff --git a/otherlibs/unix/sendrecv.c b/otherlibs/unix/sendrecv.c index 4b8e755461..a3149a2ed1 100644 --- a/otherlibs/unix/sendrecv.c +++ b/otherlibs/unix/sendrecv.c @@ -71,9 +71,9 @@ CAMLprim value unix_recvfrom(value sock, value buff, value ofs, value len, if (ret == -1) uerror("recvfrom", Nothing); memmove (&Byte(buff, Long_val(ofs)), iobuf, ret); adr = alloc_sockaddr(&addr, addr_len, -1); - res = caml_alloc_small(2, 0); - Field(res, 0) = Val_int(ret); - Field(res, 1) = adr; + res = caml_alloc_2(0, + Val_int(ret), + adr); End_roots(); return res; } diff --git a/otherlibs/unix/setgroups.c b/otherlibs/unix/setgroups.c index 6c63cce015..d4c1c70e6b 100644 --- a/otherlibs/unix/setgroups.c +++ b/otherlibs/unix/setgroups.c @@ -36,7 +36,7 @@ CAMLprim value unix_setgroups(value groups) size = Wosize_val(groups); gidset = (gid_t *) caml_stat_alloc(size * sizeof(gid_t)); - for (i = 0; i < size; i++) gidset[i] = Int_val(Field(groups, i)); + for (i = 0; i < size; i++) gidset[i] = Int_field(groups, i); n = setgroups(size, gidset); diff --git a/otherlibs/unix/signals.c b/otherlibs/unix/signals.c index ff59a72676..59b642f0f2 100644 --- a/otherlibs/unix/signals.c +++ b/otherlibs/unix/signals.c @@ -35,7 +35,7 @@ static void decode_sigset(value vset, sigset_t * set) { sigemptyset(set); while (vset != Val_int(0)) { - int sig = caml_convert_signal_number(Int_val(Field(vset, 0))); + int sig = caml_convert_signal_number(Int_field(vset, 0)); sigaddset(set, sig); vset = Field(vset, 1); } @@ -49,9 +49,9 @@ static value encode_sigset(sigset_t * set) Begin_root(res) for (i = 1; i < NSIG; i++) if (sigismember(set, i) > 0) { - value newcons = caml_alloc_small(2, 0); - Field(newcons, 0) = Val_int(caml_rev_convert_signal_number(i)); - Field(newcons, 1) = res; + value newcons = caml_alloc_2(0, + Val_int(caml_rev_convert_signal_number(i)), + res); res = newcons; } End_roots(); @@ -69,20 +69,16 @@ CAMLprim value unix_sigprocmask(value vaction, value vset) how = sigprocmask_cmd[Int_val(vaction)]; decode_sigset(vset, &set); caml_enter_blocking_section(); - retcode = caml_sigmask_hook(how, &set, &oldset); + retcode = sigprocmask(how, &set, &oldset); caml_leave_blocking_section(); - if (retcode != 0) unix_error(retcode, "sigprocmask", Nothing); + if (retcode == -1) uerror("sigprocmask", Nothing); return encode_sigset(&oldset); } CAMLprim value unix_sigpending(value unit) { sigset_t pending; - int i; if (sigpending(&pending) == -1) uerror("sigpending", Nothing); - for (i = 1; i < NSIG; i++) - if(caml_pending_signals[i]) - sigaddset(&pending, i); return encode_sigset(&pending); } diff --git a/otherlibs/unix/socketaddr.c b/otherlibs/unix/socketaddr.c index 3e05324669..dd4b0e3572 100644 --- a/otherlibs/unix/socketaddr.c +++ b/otherlibs/unix/socketaddr.c @@ -151,9 +151,9 @@ value alloc_sockaddr(union sock_addr_union * adr /*in*/, case AF_INET: { value a = alloc_inet_addr(&adr->s_inet.sin_addr); Begin_root (a); - res = caml_alloc_small(2, 1); - Field(res,0) = a; - Field(res,1) = Val_int(ntohs(adr->s_inet.sin_port)); + res = caml_alloc_2(1, + a, + Val_int(ntohs(adr->s_inet.sin_port))); End_roots(); break; } @@ -161,9 +161,9 @@ value alloc_sockaddr(union sock_addr_union * adr /*in*/, case AF_INET6: { value a = alloc_inet6_addr(&adr->s_inet6.sin6_addr); Begin_root (a); - res = caml_alloc_small(2, 1); - Field(res,0) = a; - Field(res,1) = Val_int(ntohs(adr->s_inet6.sin6_port)); + res = caml_alloc_2(1, + a, + Val_int(ntohs(adr->s_inet6.sin6_port))); End_roots(); break; } diff --git a/otherlibs/unix/socketpair.c b/otherlibs/unix/socketpair.c index 15cc82b245..03a0dc98ec 100644 --- a/otherlibs/unix/socketpair.c +++ b/otherlibs/unix/socketpair.c @@ -42,9 +42,9 @@ CAMLprim value unix_socketpair(value cloexec, value domain, unix_set_cloexec(sv[1], "socketpair", Nothing); } #endif - res = caml_alloc_small(2, 0); - Field(res,0) = Val_int(sv[0]); - Field(res,1) = Val_int(sv[1]); + res = caml_alloc_2(0, + Val_int(sv[0]), + Val_int(sv[1])); return res; } diff --git a/otherlibs/unix/sockopt.c b/otherlibs/unix/sockopt.c index d2961d09e9..84cc07fb70 100644 --- a/otherlibs/unix/sockopt.c +++ b/otherlibs/unix/sockopt.c @@ -203,9 +203,7 @@ unix_getsockopt_aux(char * name, if (optval.lg.l_onoff == 0) { return Val_int(0); /* None */ } else { - value res = caml_alloc_small(1, 0); /* Some */ - Field(res, 0) = Val_int(optval.lg.l_linger); - return res; + return caml_alloc_1(0, Val_int(optval.lg.l_linger)); /* Some */ } case TYPE_TIMEVAL: return caml_copy_double((double) optval.tv.tv_sec @@ -214,13 +212,9 @@ unix_getsockopt_aux(char * name, if (optval.i == 0) { return Val_int(0); /* None */ } else { - value err, res; + value err; err = unix_error_of_code(optval.i); - Begin_root(err); - res = caml_alloc_small(1, 0); /* Some */ - Field(res, 0) = err; - End_roots(); - return res; + return caml_alloc_1(0, err); /* Some */ } default: unix_error(EINVAL, name, Nothing); @@ -246,7 +240,7 @@ unix_setsockopt_aux(char * name, optsize = sizeof(optval.lg); optval.lg.l_onoff = Is_block (val); if (optval.lg.l_onoff) - optval.lg.l_linger = Int_val (Field (val, 0)); + optval.lg.l_linger = Int_field (val, 0); break; case TYPE_TIMEVAL: f = Double_val(val); diff --git a/otherlibs/unix/stat.c b/otherlibs/unix/stat.c index 69ad96ea2d..e5382640b8 100644 --- a/otherlibs/unix/stat.c +++ b/otherlibs/unix/stat.c @@ -80,7 +80,7 @@ static value stat_aux(int use_64, struct stat *buf) ctime = caml_copy_double(stat_timestamp(buf->st_ctime, NSEC(buf, c))); #undef NSEC offset = use_64 ? Val_file_offset(buf->st_size) : Val_int (buf->st_size); - v = caml_alloc_small(12, 0); + v = caml_alloc(12, 0); Field (v, 0) = Val_int (buf->st_dev); Field (v, 1) = Val_int (buf->st_ino); Field (v, 2) = cst_to_constr(buf->st_mode & S_IFMT, file_kind_table, diff --git a/otherlibs/unix/termios.c b/otherlibs/unix/termios.c index b6a221ff46..6a6f2d12d6 100644 --- a/otherlibs/unix/termios.c +++ b/otherlibs/unix/termios.c @@ -14,6 +14,7 @@ /**************************************************************************/ #include <caml/mlvalues.h> +#include <caml/memory.h> #include <caml/alloc.h> #include <caml/fail.h> #include "unixsupport.h" @@ -192,17 +193,18 @@ static struct { #define NSPEEDS (sizeof(speedtable) / sizeof(speedtable[0])) -static void encode_terminal_status(value *dst) +static void encode_terminal_status(value res, int field) { + CAMLparam1(res); long * pc; int i; - for(pc = terminal_io_descr; *pc != End; dst++) { + for(pc = terminal_io_descr; *pc != End; field++) { switch(*pc++) { case Bool: { int * src = (int *) (*pc++); int msk = *pc++; - *dst = Val_bool(*src & msk); + caml_initialize_field(res, field, Val_bool(*src & msk)); break; } case Enum: { int * src = (int *) (*pc++); @@ -211,7 +213,7 @@ static void encode_terminal_status(value *dst) int msk = *pc++; for (i = 0; i < num; i++) { if ((*src & msk) == pc[i]) { - *dst = Val_int(i + ofs); + caml_initialize_field(res, field, Val_int(i + ofs)); break; } } @@ -220,7 +222,7 @@ static void encode_terminal_status(value *dst) case Speed: { int which = *pc++; speed_t speed = 0; - *dst = Val_int(9600); /* in case no speed in speedtable matches */ + caml_initialize_field(res, field, Val_int(9600)); /* in case no speed in speedtable matches */ switch (which) { case Output: speed = cfgetospeed(&terminal_status); break; @@ -229,30 +231,31 @@ static void encode_terminal_status(value *dst) } for (i = 0; i < NSPEEDS; i++) { if (speed == speedtable[i].speed) { - *dst = Val_int(speedtable[i].baud); + caml_initialize_field(res, field, Val_int(speedtable[i].baud)); break; } } break; } case Char: { int which = *pc++; - *dst = Val_int(terminal_status.c_cc[which]); + caml_initialize_field(res, field, Val_int(terminal_status.c_cc[which])); break; } } } + CAMLreturn0; } -static void decode_terminal_status(value *src) +static void decode_terminal_status(value v, int field) { long * pc; int i; - for (pc = terminal_io_descr; *pc != End; src++) { + for (pc = terminal_io_descr; *pc != End; field++) { switch(*pc++) { case Bool: { int * dst = (int *) (*pc++); int msk = *pc++; - if (Bool_val(*src)) + if (Bool_field(v, field)) *dst |= msk; else *dst &= ~msk; @@ -262,7 +265,7 @@ static void decode_terminal_status(value *src) int ofs = *pc++; int num = *pc++; int msk = *pc++; - i = Int_val(*src) - ofs; + i = Int_field(v, field) - ofs; if (i >= 0 && i < num) { *dst = (*dst & ~msk) | pc[i]; } else { @@ -272,7 +275,7 @@ static void decode_terminal_status(value *src) break; } case Speed: { int which = *pc++; - int baud = Int_val(*src); + int baud = Int_field(v, field); int res = 0; for (i = 0; i < NSPEEDS; i++) { if (baud == speedtable[i].baud) { @@ -291,7 +294,7 @@ static void decode_terminal_status(value *src) break; } case Char: { int which = *pc++; - terminal_status.c_cc[which] = Int_val(*src); + terminal_status.c_cc[which] = Int_field(v, field); break; } } } @@ -304,7 +307,7 @@ CAMLprim value unix_tcgetattr(value fd) if (tcgetattr(Int_val(fd), &terminal_status) == -1) uerror("tcgetattr", Nothing); res = caml_alloc_tuple(NFIELDS); - encode_terminal_status(&Field(res, 0)); + encode_terminal_status(res, 0); return res; } @@ -316,7 +319,7 @@ CAMLprim value unix_tcsetattr(value fd, value when, value arg) { if (tcgetattr(Int_val(fd), &terminal_status) == -1) uerror("tcsetattr", Nothing); - decode_terminal_status(&Field(arg, 0)); + decode_terminal_status(arg, 0); if (tcsetattr(Int_val(fd), when_flag_table[Int_val(when)], &terminal_status) == -1) diff --git a/otherlibs/unix/unix.mli b/otherlibs/unix/unix.mli index 2cdb2643e5..a624fdedfc 100644 --- a/otherlibs/unix/unix.mli +++ b/otherlibs/unix/unix.mli @@ -1036,10 +1036,6 @@ val sigprocmask : sigprocmask_command -> int list -> int list from the set of blocked signals. [sigprocmask] returns the set of previously blocked signals. - When the systhreads version of the [Thread] module is loaded, this - function redirects to [Thread.sigmask]. I.e., [sigprocmask] only - changes the mask of the current thread. - On Windows: not implemented (no inter-process signals on Windows). *) val sigpending : unit -> int list diff --git a/otherlibs/unix/unixsupport.c b/otherlibs/unix/unixsupport.c index 937146b21d..9ed48571ba 100644 --- a/otherlibs/unix/unixsupport.c +++ b/otherlibs/unix/unixsupport.c @@ -253,8 +253,6 @@ int error_table[] = { EHOSTUNREACH, ELOOP, EOVERFLOW /*, EUNKNOWNERR */ }; -static const value * unix_error_exn = NULL; - value unix_error_of_code (int errcode) { int errconstr; @@ -268,8 +266,7 @@ value unix_error_of_code (int errcode) errconstr = cst_to_constr(errcode, error_table, sizeof(error_table)/sizeof(int), -1); if (errconstr == Val_int(-1)) { - err = caml_alloc_small(1, 0); - Field(err, 0) = Val_int(errcode); + err = caml_alloc_1(0, Val_int(errcode)); } else { err = errconstr; } @@ -279,7 +276,7 @@ value unix_error_of_code (int errcode) extern int code_of_unix_error (value error) { if (Is_block(error)) { - return Int_val(Field(error, 0)); + return Int_field(error, 0); } else { return error_table[Int_val(error)]; } @@ -289,22 +286,21 @@ void unix_error(int errcode, const char *cmdname, value cmdarg) { value res; value name = Val_unit, err = Val_unit, arg = Val_unit; + const value* unix_error_exn; Begin_roots3 (name, err, arg); arg = cmdarg == Nothing ? caml_copy_string("") : cmdarg; name = caml_copy_string(cmdname); err = unix_error_of_code (errcode); - if (unix_error_exn == NULL) { - unix_error_exn = caml_named_value("Unix.Unix_error"); - if (unix_error_exn == NULL) - caml_invalid_argument("Exception Unix.Unix_error not initialized," - " please link unix.cma"); - } - res = caml_alloc_small(4, 0); - Field(res, 0) = *unix_error_exn; - Field(res, 1) = err; - Field(res, 2) = name; - Field(res, 3) = arg; + unix_error_exn = caml_named_value("Unix.Unix_error"); + if (!unix_error_exn) + caml_invalid_argument("Exception Unix.Unix_error not initialized," + " please link unix.cma"); + res = caml_alloc_4(0, + *unix_error_exn, + err, + name, + arg); End_roots(); caml_raise(res); } diff --git a/otherlibs/unix/unixsupport.h b/otherlibs/unix/unixsupport.h index fe345466de..2f9280d40f 100644 --- a/otherlibs/unix/unixsupport.h +++ b/otherlibs/unix/unixsupport.h @@ -41,7 +41,7 @@ extern void caml_unix_check_path(value path, const char * cmdname); #define UNIX_BUFFER_SIZE 65536 -#define DIR_Val(v) *((DIR **) &Field(v, 0)) +#define DIR_Val(v) *((DIR **) Data_abstract_val(v)) extern char ** cstringvect(value arg, char * cmdname); extern void cstringvect_free(char **); diff --git a/otherlibs/unix/wait.c b/otherlibs/unix/wait.c index d0f06bfcbc..0ef38830f8 100644 --- a/otherlibs/unix/wait.c +++ b/otherlibs/unix/wait.c @@ -41,29 +41,24 @@ static value alloc_process_status(int pid, int status) { - value st, res; + value st; // status is undefined when pid is zero so we set a default value. if (pid == 0) status = 0; if (WIFEXITED(status)) { - st = caml_alloc_small(1, TAG_WEXITED); - Field(st, 0) = Val_int(WEXITSTATUS(status)); + st = caml_alloc_1(TAG_WEXITED, + Val_int(WEXITSTATUS(status))); } else if (WIFSTOPPED(status)) { - st = caml_alloc_small(1, TAG_WSTOPPED); - Field(st, 0) = Val_int(caml_rev_convert_signal_number(WSTOPSIG(status))); + st = caml_alloc_1(TAG_WSTOPPED, + Val_int(caml_rev_convert_signal_number(WSTOPSIG(status)))); } else { - st = caml_alloc_small(1, TAG_WSIGNALED); - Field(st, 0) = Val_int(caml_rev_convert_signal_number(WTERMSIG(status))); + st = caml_alloc_1(TAG_WSIGNALED, + Val_int(caml_rev_convert_signal_number(WTERMSIG(status)))); } - Begin_root (st); - res = caml_alloc_small(2, 0); - Field(res, 0) = Val_int(pid); - Field(res, 1) = st; - End_roots(); - return res; + return caml_alloc_2(0, Val_int(pid), st); } CAMLprim value unix_wait(value unit) diff --git a/otherlibs/win32unix/.depend b/otherlibs/win32unix/.depend index 70c377d241..0495449fbb 100644 --- a/otherlibs/win32unix/.depend +++ b/otherlibs/win32unix/.depend @@ -1,3 +1,21 @@ +windbug.$(O): windbug.c windbug.h +cst2constr.$(O): cst2constr.c ../../runtime/caml/mlvalues.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/misc.h \ + ../../runtime/caml/camlatomic.h ../../runtime/caml/domain_state.h \ + ../../runtime/caml/domain_state.tbl \ + ../../runtime/caml/byte_domain_state.tbl ../../runtime/caml/fail.h \ + ../unix/cst2constr.h +mmap_ba.$(O): mmap_ba.c ../../runtime/caml/alloc.h ../../runtime/caml/misc.h \ + ../../runtime/caml/config.h ../../runtime/caml/m.h \ + ../../runtime/caml/s.h ../../runtime/caml/camlatomic.h \ + ../../runtime/caml/mlvalues.h ../../runtime/caml/domain_state.h \ + ../../runtime/caml/domain_state.tbl \ + ../../runtime/caml/byte_domain_state.tbl ../../runtime/caml/bigarray.h \ + ../../runtime/caml/custom.h ../../runtime/caml/memory.h \ + ../../runtime/caml/gc.h ../../runtime/caml/major_gc.h \ + ../../runtime/caml/minor_gc.h ../../runtime/caml/addrmap.h \ + ../../runtime/caml/domain.h ../../runtime/caml/platform.h unix.cmo : \ unix.cmi unix.cmx : \ diff --git a/otherlibs/win32unix/accept.c b/otherlibs/win32unix/accept.c index 0a15673e0b..771a5f7448 100644 --- a/otherlibs/win32unix/accept.c +++ b/otherlibs/win32unix/accept.c @@ -45,9 +45,7 @@ CAMLprim value unix_accept(value cloexec, value sock) Begin_roots2 (fd, adr) fd = win_alloc_socket(snew); adr = alloc_sockaddr(&addr, addr_len, snew); - res = caml_alloc_small(2, 0); - Field(res, 0) = fd; - Field(res, 1) = adr; + res = caml_alloc_2(0, fd, adr); End_roots(); return res; } diff --git a/otherlibs/win32unix/errmsg.c b/otherlibs/win32unix/errmsg.c index d910df5599..75b5654f60 100644 --- a/otherlibs/win32unix/errmsg.c +++ b/otherlibs/win32unix/errmsg.c @@ -30,7 +30,7 @@ CAMLprim value unix_error_message(value err) int errnum; wchar_t buffer[512]; - errnum = Is_block(err) ? Int_val(Field(err, 0)) : error_table[Int_val(err)]; + errnum = Is_block(err) ? Int_field(err, 0) : error_table[Int_val(err)]; if (errnum > 0) return caml_copy_string(strerror(errnum)); if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, diff --git a/otherlibs/win32unix/mmap.c b/otherlibs/win32unix/mmap.c index da08a19fde..cf8416beb6 100644 --- a/otherlibs/win32unix/mmap.c +++ b/otherlibs/win32unix/mmap.c @@ -72,7 +72,7 @@ CAMLprim value caml_unix_map_file(value vfd, value vkind, value vlayout, if (num_dims < 1 || num_dims > CAML_BA_MAX_NUM_DIMS) caml_invalid_argument("Unix.map_file: bad number of dimensions"); for (i = 0; i < num_dims; i++) { - dim[i] = Long_val(Field(vdim, i)); + dim[i] = Long_field(vdim, i); if (dim[i] == -1 && i == major_dim) continue; if (dim[i] < 0) caml_invalid_argument("Unix.map_file: negative dimension"); diff --git a/otherlibs/win32unix/pipe.c b/otherlibs/win32unix/pipe.c index a48c686ab3..f21d0be367 100644 --- a/otherlibs/win32unix/pipe.c +++ b/otherlibs/win32unix/pipe.c @@ -38,9 +38,7 @@ CAMLprim value unix_pipe(value cloexec, value unit) Begin_roots2(readfd, writefd) readfd = win_alloc_handle(readh); writefd = win_alloc_handle(writeh); - res = caml_alloc_small(2, 0); - Field(res, 0) = readfd; - Field(res, 1) = writefd; + res = caml_alloc_2(0, readfd, writefd); End_roots(); return res; } diff --git a/otherlibs/win32unix/sendrecv.c b/otherlibs/win32unix/sendrecv.c index 1daa8e9954..c7f751040c 100644 --- a/otherlibs/win32unix/sendrecv.c +++ b/otherlibs/win32unix/sendrecv.c @@ -78,9 +78,9 @@ CAMLprim value unix_recvfrom(value sock, value buff, value ofs, value len, } memmove (&Byte(buff, Long_val(ofs)), iobuf, ret); adr = alloc_sockaddr(&addr, addr_len, -1); - res = caml_alloc_small(2, 0); - Field(res, 0) = Val_int(ret); - Field(res, 1) = adr; + res = caml_alloc_2(0, + Val_int(ret), + adr); End_roots(); return res; } diff --git a/otherlibs/win32unix/sockopt.c b/otherlibs/win32unix/sockopt.c index 6035556f72..a0c2f58b7e 100644 --- a/otherlibs/win32unix/sockopt.c +++ b/otherlibs/win32unix/sockopt.c @@ -140,9 +140,7 @@ unix_getsockopt_aux(char * name, if (optval.lg.l_onoff == 0) { return Val_int(0); /* None */ } else { - value res = caml_alloc_small(1, 0); /* Some */ - Field(res, 0) = Val_int(optval.lg.l_linger); - return res; + return caml_alloc_1(0, Val_int(optval.lg.l_linger)); /* Some */ } case TYPE_TIMEVAL: return caml_copy_double((double) optval.tv.tv_sec @@ -151,13 +149,9 @@ unix_getsockopt_aux(char * name, if (optval.i == 0) { return Val_int(0); /* None */ } else { - value err, res; + value err; err = unix_error_of_code(optval.i); - Begin_root(err); - res = caml_alloc_small(1, 0); /* Some */ - Field(res, 0) = err; - End_roots(); - return res; + return caml_alloc_1(0, err); } default: unix_error(EINVAL, name, Nothing); @@ -184,7 +178,7 @@ unix_setsockopt_aux(char * name, optsize = sizeof(optval.lg); optval.lg.l_onoff = Is_block (val); if (optval.lg.l_onoff) - optval.lg.l_linger = Int_val (Field (val, 0)); + optval.lg.l_linger = Int_field (val, 0); break; case TYPE_TIMEVAL: f = Double_val(val); diff --git a/otherlibs/win32unix/system.c b/otherlibs/win32unix/system.c index 39a47582a2..fa40ae3216 100644 --- a/otherlibs/win32unix/system.c +++ b/otherlibs/win32unix/system.c @@ -39,7 +39,6 @@ CAMLprim value win_system(cmd) caml_leave_blocking_section(); caml_stat_free(buf); if (ret == -1) uerror("system", Nothing); - st = caml_alloc_small(1, 0); /* Tag 0: Exited */ - Field(st, 0) = Val_int(ret); + st = caml_alloc_1(0, Val_int(ret)); /* Tag 0: Exited */ return st; } diff --git a/otherlibs/win32unix/unixsupport.c b/otherlibs/win32unix/unixsupport.c index 50d27ab381..d548f43806 100644 --- a/otherlibs/win32unix/unixsupport.c +++ b/otherlibs/win32unix/unixsupport.c @@ -276,8 +276,7 @@ value unix_error_of_code (int errcode) errconstr = cst_to_constr(errcode, error_table, sizeof(error_table)/sizeof(int), -1); if (errconstr == Val_int(-1)) { - err = caml_alloc_small(1, 0); - Field(err, 0) = Val_int(errcode); + err = caml_alloc_1(0, Val_int(errcode)); } else { err = errconstr; } @@ -296,15 +295,15 @@ void unix_error(int errcode, const char *cmdname, value cmdarg) err = unix_error_of_code (errcode); if (unix_error_exn == NULL) { unix_error_exn = caml_named_value("Unix.Unix_error"); - if (unix_error_exn == NULL) + if (!unix_error_exn) caml_invalid_argument("Exception Unix.Unix_error not initialized," - " please link unix.cma"); + " please link unix.cma"); } - res = caml_alloc_small(4, 0); - Field(res, 0) = *unix_error_exn; - Field(res, 1) = err; - Field(res, 2) = name; - Field(res, 3) = arg; + res = caml_alloc_4(0, + *unix_error_exn, + err, + name, + arg); End_roots(); caml_raise(res); } diff --git a/otherlibs/win32unix/windir.c b/otherlibs/win32unix/windir.c index b287a8ea5d..6e79fca20f 100644 --- a/otherlibs/win32unix/windir.c +++ b/otherlibs/win32unix/windir.c @@ -48,9 +48,7 @@ CAMLprim value win_findfirst(value name) } valname = caml_copy_string_of_utf16(fileinfo.cFileName); valh = win_alloc_handle(h); - v = caml_alloc_small(2, 0); - Field(v,0) = valname; - Field(v,1) = valh; + v = caml_alloc_2(0, valname, valh); End_roots(); return v; } diff --git a/otherlibs/win32unix/winwait.c b/otherlibs/win32unix/winwait.c index 90cc6db6d0..71836451f4 100644 --- a/otherlibs/win32unix/winwait.c +++ b/otherlibs/win32unix/winwait.c @@ -23,16 +23,10 @@ static value alloc_process_status(HANDLE pid, int status) { - value res, st; + value st; - st = caml_alloc(1, 0); - Field(st, 0) = Val_int(status); - Begin_root (st); - res = caml_alloc_small(2, 0); - Field(res, 0) = Val_long((intnat) pid); - Field(res, 1) = st; - End_roots(); - return res; + st = caml_alloc_1(0, Val_int(status)); + return caml_alloc_2(0, Val_long((intnat) pid), st); } enum { CAML_WNOHANG = 1, CAML_WUNTRACED = 2 }; diff --git a/parsing/ast_helper.ml b/parsing/ast_helper.ml index 2d51dda743..d8cee64a61 100644 --- a/parsing/ast_helper.ml +++ b/parsing/ast_helper.ml @@ -164,6 +164,7 @@ module Pat = struct let unpack ?loc ?attrs a = mk ?loc ?attrs (Ppat_unpack a) let open_ ?loc ?attrs a b = mk ?loc ?attrs (Ppat_open (a, b)) let exception_ ?loc ?attrs a = mk ?loc ?attrs (Ppat_exception a) + let effect_ ?loc ?attrs a b = mk ?loc ?attrs (Ppat_effect(a, b)) let extension ?loc ?attrs a = mk ?loc ?attrs (Ppat_extension a) end @@ -267,6 +268,7 @@ module Sig = struct let type_subst ?loc a = mk ?loc (Psig_typesubst a) let type_extension ?loc a = mk ?loc (Psig_typext a) let exception_ ?loc a = mk ?loc (Psig_exception a) + let effect_ ?loc a = mk ?loc (Psig_effect a) let module_ ?loc a = mk ?loc (Psig_module a) let mod_subst ?loc a = mk ?loc (Psig_modsubst a) let rec_module ?loc a = mk ?loc (Psig_recmodule a) @@ -293,6 +295,7 @@ module Str = struct let type_ ?loc rec_flag a = mk ?loc (Pstr_type (rec_flag, a)) let type_extension ?loc a = mk ?loc (Pstr_typext a) let exception_ ?loc a = mk ?loc (Pstr_exception a) + let effect_ ?loc a = mk ?loc (Pstr_effect a) let module_ ?loc a = mk ?loc (Pstr_module a) let rec_module ?loc a = mk ?loc (Pstr_recmodule a) let modtype ?loc a = mk ?loc (Pstr_modtype a) @@ -597,6 +600,30 @@ module Te = struct pext_attributes = add_docs_attrs docs (add_info_attrs info attrs); } + let effect_constructor ?(loc = !default_loc) ?(attrs = []) name kind = + { + peff_name = name; + peff_kind = kind; + peff_loc = loc; + peff_attributes = attrs; + } + + let effect_decl ?(loc = !default_loc) ?(attrs = []) ?(args = []) name res = + { + peff_name = name; + peff_kind = Peff_decl(args, res); + peff_loc = loc; + peff_attributes = attrs; + } + + let effect_rebind ?(loc = !default_loc) ?(attrs = []) name lid = + { + peff_name = name; + peff_kind = Peff_rebind lid; + peff_loc = loc; + peff_attributes = attrs; + } + end module Csig = struct diff --git a/parsing/ast_helper.mli b/parsing/ast_helper.mli index 8182e5ddf0..49a5f7b97f 100644 --- a/parsing/ast_helper.mli +++ b/parsing/ast_helper.mli @@ -121,6 +121,7 @@ module Pat: val unpack: ?loc:loc -> ?attrs:attrs -> str_opt -> pattern val open_: ?loc:loc -> ?attrs:attrs -> lid -> pattern -> pattern val exception_: ?loc:loc -> ?attrs:attrs -> pattern -> pattern + val effect_: ?loc:loc -> ?attrs:attrs -> pattern -> pattern -> pattern val extension: ?loc:loc -> ?attrs:attrs -> extension -> pattern end @@ -234,6 +235,10 @@ module Te: extension_constructor val rebind: ?loc:loc -> ?attrs:attrs -> ?docs:docs -> ?info:info -> str -> lid -> extension_constructor + + val effect_constructor: ?loc:loc -> ?attrs:attrs -> str -> effect_constructor_kind -> effect_constructor + val effect_decl: ?loc:loc -> ?attrs:attrs -> ?args:core_type list -> str -> core_type -> effect_constructor + val effect_rebind: ?loc:loc -> ?attrs:attrs -> str -> lid -> effect_constructor end (** {1 Module language} *) @@ -282,6 +287,7 @@ module Sig: val type_: ?loc:loc -> rec_flag -> type_declaration list -> signature_item val type_subst: ?loc:loc -> type_declaration list -> signature_item val type_extension: ?loc:loc -> type_extension -> signature_item + val effect_: ?loc:loc -> effect_constructor -> signature_item val exception_: ?loc:loc -> type_exception -> signature_item val module_: ?loc:loc -> module_declaration -> signature_item val mod_subst: ?loc:loc -> module_substitution -> signature_item @@ -306,6 +312,7 @@ module Str: val primitive: ?loc:loc -> value_description -> structure_item val type_: ?loc:loc -> rec_flag -> type_declaration list -> structure_item val type_extension: ?loc:loc -> type_extension -> structure_item + val effect_: ?loc:loc -> effect_constructor -> structure_item val exception_: ?loc:loc -> type_exception -> structure_item val module_: ?loc:loc -> module_binding -> structure_item val rec_module: ?loc:loc -> module_binding list -> structure_item diff --git a/parsing/ast_iterator.ml b/parsing/ast_iterator.ml index 5f016c0089..c6a99b26aa 100644 --- a/parsing/ast_iterator.ml +++ b/parsing/ast_iterator.ml @@ -43,6 +43,7 @@ type iterator = { expr: iterator -> expression -> unit; extension: iterator -> extension -> unit; extension_constructor: iterator -> extension_constructor -> unit; + effect_constructor: iterator -> effect_constructor -> unit; include_declaration: iterator -> include_declaration -> unit; include_description: iterator -> include_description -> unit; label_declaration: iterator -> label_declaration -> unit; @@ -197,6 +198,21 @@ module T = struct sub.location sub pext_loc; sub.attributes sub pext_attributes + let iter_effect_constructor_kind sub = function + Peff_decl(ctl, cto) -> + List.iter (sub.typ sub) ctl; sub.typ sub cto + | Peff_rebind li -> + iter_loc sub li + + let iter_effect_constructor sub + {peff_name; + peff_kind; + peff_loc; + peff_attributes} = + iter_loc sub peff_name; + iter_effect_constructor_kind sub peff_kind; + sub.location sub peff_loc; + sub.attributes sub peff_attributes end module CT = struct @@ -276,6 +292,7 @@ module MT = struct | Psig_typesubst l -> List.iter (sub.type_declaration sub) l | Psig_typext te -> sub.type_extension sub te + | Psig_effect ed -> sub.effect_constructor sub ed | Psig_exception ed -> sub.type_exception sub ed | Psig_module x -> sub.module_declaration sub x | Psig_modsubst x -> sub.module_substitution sub x @@ -322,6 +339,7 @@ module M = struct | Pstr_primitive vd -> sub.value_description sub vd | Pstr_type (_rf, l) -> List.iter (sub.type_declaration sub) l | Pstr_typext te -> sub.type_extension sub te + | Pstr_effect ed -> sub.effect_constructor sub ed | Pstr_exception ed -> sub.type_exception sub ed | Pstr_module x -> sub.module_binding sub x | Pstr_recmodule l -> List.iter (sub.module_binding sub) l @@ -449,6 +467,7 @@ module P = struct | Ppat_lazy p -> sub.pat sub p | Ppat_unpack s -> iter_loc sub s | Ppat_exception p -> sub.pat sub p + | Ppat_effect (p1,p2) -> sub.pat sub p1; sub.pat sub p2 | Ppat_extension x -> sub.extension sub x | Ppat_open (lid, p) -> iter_loc sub lid; sub.pat sub p @@ -546,6 +565,7 @@ let default_iterator = type_extension = T.iter_type_extension; type_exception = T.iter_type_exception; extension_constructor = T.iter_extension_constructor; + effect_constructor = T.iter_effect_constructor; value_description = (fun this {pval_name; pval_type; pval_prim = _; pval_loc; pval_attributes} -> diff --git a/parsing/ast_iterator.mli b/parsing/ast_iterator.mli index 26308d20de..4e9f1d436a 100644 --- a/parsing/ast_iterator.mli +++ b/parsing/ast_iterator.mli @@ -45,6 +45,7 @@ type iterator = { expr: iterator -> expression -> unit; extension: iterator -> extension -> unit; extension_constructor: iterator -> extension_constructor -> unit; + effect_constructor: iterator -> effect_constructor -> unit; include_declaration: iterator -> include_declaration -> unit; include_description: iterator -> include_description -> unit; label_declaration: iterator -> label_declaration -> unit; diff --git a/parsing/ast_mapper.ml b/parsing/ast_mapper.ml index dadf5eaa4e..97d62985d5 100644 --- a/parsing/ast_mapper.ml +++ b/parsing/ast_mapper.ml @@ -45,6 +45,8 @@ type mapper = { constant: mapper -> constant -> constant; constructor_declaration: mapper -> constructor_declaration -> constructor_declaration; + effect_constructor: mapper -> effect_constructor + -> effect_constructor; expr: mapper -> expression -> expression; extension: mapper -> extension -> extension; extension_constructor: mapper -> extension_constructor @@ -222,6 +224,23 @@ module T = struct (map_loc sub pext_name) (map_extension_constructor_kind sub pext_kind) + let map_effect_constructor_kind sub = function + Peff_decl(ctl, cto) -> + Peff_decl(List.map (sub.typ sub) ctl, sub.typ sub cto) + | Peff_rebind li -> + Peff_rebind (map_loc sub li) + + let map_effect_constructor sub + {peff_name; + peff_kind; + peff_loc; + peff_attributes} = + Te.effect_constructor + (map_loc sub peff_name) + (map_effect_constructor_kind sub peff_kind) + ~loc:(sub.location sub peff_loc) + ~attrs:(sub.attributes sub peff_attributes) + end module CT = struct @@ -308,6 +327,7 @@ module MT = struct | Psig_typesubst l -> type_subst ~loc (List.map (sub.type_declaration sub) l) | Psig_typext te -> type_extension ~loc (sub.type_extension sub te) + | Psig_effect ed -> effect_ ~loc (sub.effect_constructor sub ed) | Psig_exception ed -> exception_ ~loc (sub.type_exception sub ed) | Psig_module x -> module_ ~loc (sub.module_declaration sub x) | Psig_modsubst x -> mod_subst ~loc (sub.module_substitution sub x) @@ -359,6 +379,7 @@ module M = struct | Pstr_primitive vd -> primitive ~loc (sub.value_description sub vd) | Pstr_type (rf, l) -> type_ ~loc rf (List.map (sub.type_declaration sub) l) | Pstr_typext te -> type_extension ~loc (sub.type_extension sub te) + | Pstr_effect ed -> effect_ ~loc (sub.effect_constructor sub ed) | Pstr_exception ed -> exception_ ~loc (sub.type_exception sub ed) | Pstr_module x -> module_ ~loc (sub.module_binding sub x) | Pstr_recmodule l -> rec_module ~loc (List.map (sub.module_binding sub) l) @@ -495,6 +516,7 @@ module P = struct | Ppat_unpack s -> unpack ~loc ~attrs (map_loc sub s) | Ppat_open (lid,p) -> open_ ~loc ~attrs (map_loc sub lid) (sub.pat sub p) | Ppat_exception p -> exception_ ~loc ~attrs (sub.pat sub p) + | Ppat_effect(p1, p2) -> effect_ ~loc ~attrs (sub.pat sub p1) (sub.pat sub p2) | Ppat_extension x -> extension ~loc ~attrs (sub.extension sub x) end @@ -597,6 +619,7 @@ let default_mapper = type_extension = T.map_type_extension; type_exception = T.map_type_exception; extension_constructor = T.map_extension_constructor; + effect_constructor = T.map_effect_constructor; value_description = (fun this {pval_name; pval_type; pval_prim; pval_loc; pval_attributes} -> diff --git a/parsing/ast_mapper.mli b/parsing/ast_mapper.mli index 69f6b017ab..462a374b19 100644 --- a/parsing/ast_mapper.mli +++ b/parsing/ast_mapper.mli @@ -74,6 +74,8 @@ type mapper = { constant: mapper -> constant -> constant; constructor_declaration: mapper -> constructor_declaration -> constructor_declaration; + effect_constructor: mapper -> effect_constructor + -> effect_constructor; expr: mapper -> expression -> expression; extension: mapper -> extension -> extension; extension_constructor: mapper -> extension_constructor diff --git a/parsing/depend.ml b/parsing/depend.ml index f513144b02..c2d965c450 100644 --- a/parsing/depend.ml +++ b/parsing/depend.ml @@ -156,6 +156,12 @@ let add_extension_constructor bv ext = Option.iter (add_type bv) rty | Pext_rebind lid -> add bv lid +let add_effect_constructor bv eff = + match eff.peff_kind with + Peff_decl(args, rty) -> + List.iter (add_type bv) args; add_type bv rty + | Peff_rebind lid -> add bv lid + let add_type_extension bv te = add bv te.ptyext_path; List.iter (add_extension_constructor bv) te.ptyext_constructors @@ -187,6 +193,7 @@ let rec add_pattern bv pat = (fun name -> pattern_bv := String.Map.add name bound !pattern_bv) id.txt | Ppat_open ( m, p) -> let bv = open_module bv m.txt in add_pattern bv p | Ppat_exception p -> add_pattern bv p + | Ppat_effect(p1, p2) -> add_pattern bv p1; add_pattern bv p2 | Ppat_extension e -> handle_extension e let add_pattern bv pat = @@ -351,6 +358,8 @@ and add_sig_item (bv, m) item = List.iter (add_type_declaration bv) dcls; (bv, m) | Psig_typext te -> add_type_extension bv te; (bv, m) + | Psig_effect peff -> + add_effect_constructor bv peff; (bv, m) | Psig_exception te -> add_type_exception bv te; (bv, m) | Psig_module pmd -> @@ -488,6 +497,9 @@ and add_struct_item (bv, m) item : _ String.Map.t * _ String.Map.t = | Pstr_typext te -> add_type_extension bv te; (bv, m) + | Pstr_effect peff -> + add_effect_constructor bv peff; + (bv, m) | Pstr_exception te -> add_type_exception bv te; (bv, m) diff --git a/parsing/lexer.mll b/parsing/lexer.mll index 6d68b59e33..0fa3b83c99 100644 --- a/parsing/lexer.mll +++ b/parsing/lexer.mll @@ -47,6 +47,7 @@ let keyword_table = "do", DO; "done", DONE; "downto", DOWNTO; + "effect", EFFECT; "else", ELSE; "end", END; "exception", EXCEPTION; diff --git a/parsing/location.ml b/parsing/location.ml index fa31feafd4..78ce5c01f7 100644 --- a/parsing/location.ml +++ b/parsing/location.ml @@ -910,6 +910,7 @@ let error_of_exn exn = in loop !error_of_exn + let () = register_error_of_exn (function diff --git a/parsing/parser.mly b/parsing/parser.mly index 5ef2957a76..26330bce46 100644 --- a/parsing/parser.mly +++ b/parsing/parser.mly @@ -602,6 +602,7 @@ let mk_directive ~loc name arg = %token DOT %token DOTDOT %token DOWNTO +%token EFFECT %token ELSE %token END %token EOF @@ -1317,6 +1318,8 @@ structure: structure_item: let_bindings(ext) { val_of_let_bindings ~loc:$sloc $1 } + | EFFECT effect_declaration + { mkstr ~loc:$sloc (Pstr_effect $2) } | mkstr( item_extension post_item_attributes { let docs = symbol_docs $sloc in @@ -1556,6 +1559,8 @@ signature_item: | item_extension post_item_attributes { let docs = symbol_docs $sloc in mksig ~loc:$sloc (Psig_extension ($1, (add_docs_attrs docs $2))) } + | EFFECT effect_constructor_declaration + { mksig ~loc:$sloc (Psig_effect $2) } | mksig( floating_attribute { Psig_attribute $1 } @@ -2619,6 +2624,8 @@ pattern: { $1 } | EXCEPTION ext_attributes pattern %prec prec_constr_appl { mkpat_attrs ~loc:$sloc (Ppat_exception $3) $2} + | EFFECT simple_pattern simple_pattern + { mkpat ~loc:$sloc (Ppat_effect($2,$3)) } ; pattern_no_exn: @@ -3030,6 +3037,40 @@ sig_exception_declaration: { let args, res = $2 in Te.decl $1 ~args ?res ~attrs:$3 ~loc:(make_loc $sloc) } ; + +effect_core_type_list: + inline_separated_nonempty_llist(STAR, atomic_type) + { $1 } +; + +effect_constructor_arguments: + | COLON effect_core_type_list MINUSGREATER atomic_type %prec below_HASH + { ($2, $4) } + | COLON atomic_type %prec below_HASH + { ([], $2) } +; + +effect_declaration: + | effect_constructor_declaration { $1 } + | effect_constructor_rebind { $1 } +; + +effect_constructor_declaration: + id = mkrhs(constr_ident) + attrs1 = attributes + args_res = effect_constructor_arguments + attrs2 = post_item_attributes + { let args, res = args_res in + Te.effect_decl id res ~args ~loc:(make_loc $sloc) ~attrs:(attrs2@attrs1) + } + +effect_constructor_rebind: + | mkrhs(constr_ident) attributes + EQUAL mkrhs(constr_longident) post_item_attributes + { Te.effect_rebind $1 $4 + ~loc:(make_loc $sloc) ~attrs:($5 @ $2) } +; + generalized_constructor_arguments: /*empty*/ { (Pcstr_tuple [],None) } | OF constructor_arguments { ($2,None) } diff --git a/parsing/parsetree.mli b/parsing/parsetree.mli index 8e50995ecd..89f77b3360 100644 --- a/parsing/parsetree.mli +++ b/parsing/parsetree.mli @@ -249,6 +249,8 @@ and pattern_desc = *) | Ppat_exception of pattern (* exception P *) + | Ppat_effect of pattern * pattern + (* effect P P *) | Ppat_extension of extension (* [%id] *) | Ppat_open of Longident.t loc * pattern @@ -535,6 +537,26 @@ and extension_constructor_kind = | C = D *) +and effect_constructor = + { + peff_name: string loc; + peff_kind : effect_constructor_kind; + peff_loc : Location.t; + peff_attributes: attributes; (* C [@id1] [@id2] of ... *) + } + +and effect_constructor_kind = + Peff_decl of core_type list * core_type + (* + | C of T1 * ... * Tn ([T1; ...; Tn], None) + | C: T0 ([], Some T0) + | C: T1 * ... * Tn -> T0 ([T1; ...; Tn], Some T0) + *) + | Peff_rebind of Longident.t loc + (* + | C = D + *) + (** {1 Class language} *) (* Type expressions for the class language *) @@ -757,6 +779,8 @@ and signature_item_desc = (* type t1 += ... *) | Psig_exception of type_exception (* exception C of T *) + | Psig_effect of effect_constructor + (* effect C : T -> T *) | Psig_module of module_declaration (* module X = M module X : MT *) @@ -905,6 +929,9 @@ and structure_item_desc = | Pstr_exception of type_exception (* exception C of T exception C = M.X *) + | Pstr_effect of effect_constructor + (* effect C : T -> T + effect C = M.X *) | Pstr_module of module_binding (* module X = ME *) | Pstr_recmodule of module_binding list diff --git a/parsing/pprintast.ml b/parsing/pprintast.ml index 9b8f1839e0..904a02dd08 100644 --- a/parsing/pprintast.ml +++ b/parsing/pprintast.ml @@ -480,6 +480,8 @@ and simple_pattern ctxt (f:Format.formatter) (x:pattern) : unit = pp f "@[<2>(lazy@;%a)@]" (simple_pattern ctxt) p | Ppat_exception p -> pp f "@[<2>exception@;%a@]" (pattern1 ctxt) p + | Ppat_effect(p1, p2) -> + pp f "@[<2>effect@;%a@;%a@]" (pattern1 ctxt) p1 (pattern1 ctxt) p2 | Ppat_extension e -> extension ctxt f e | Ppat_open (lid, p) -> let with_paren = @@ -849,6 +851,9 @@ and exception_declaration ctxt f x = (extension_constructor ctxt) x.ptyexn_constructor (item_attributes ctxt) x.ptyexn_attributes +and effect_declaration ctxt f ext = + pp f "@[<hov2>effect@ %a@]" (effect_constructor ctxt) ext + and class_signature ctxt f { pcsig_self = ct; pcsig_fields = l ;_} = let class_type_field f x = match x.pctf_desc with @@ -1098,6 +1103,8 @@ and signature_item ctxt f x : unit = type_extension ctxt f te | Psig_exception ed -> exception_declaration ctxt f ed + | Psig_effect ed -> + effect_declaration ctxt f ed | Psig_class l -> let class_description kwd f ({pci_params=ls;pci_name={txt;_};_} as x) = pp f "@[<2>%s %a%a%s@;:@;%a@]%a" kwd @@ -1323,6 +1330,7 @@ and structure_item ctxt f x = pp f "@[<2>%a@]" (bindings ctxt) (rf,l) | Pstr_typext te -> type_extension ctxt f te | Pstr_exception ed -> exception_declaration ctxt f ed + | Pstr_effect ed -> effect_declaration ctxt f ed | Pstr_module x -> let rec module_helper = function | {pmod_desc=Pmod_functor(arg_opt,me'); pmod_attributes = []} -> @@ -1588,6 +1596,20 @@ and extension_constructor ctxt f x = (attributes ctxt) x.pext_attributes longident_loc li +and effect_constructor ctxt f x = + match x.peff_kind with + | Peff_decl(l, r) -> + pp f "%s%a:@;%a" x.peff_name.txt (attributes ctxt) x.peff_attributes + (fun f -> function + | [] -> (core_type1 ctxt) f r + | l -> pp f "%a@;->@;%a" (list (core_type1 ctxt) ~sep:"*@;") l + (core_type1 ctxt) r) + l + | Peff_rebind li -> + pp f "%s%a@;=@;%a" x.peff_name.txt (attributes ctxt) + x.peff_attributes longident_loc li + + and case_list ctxt f l : unit = let aux f {pc_lhs; pc_guard; pc_rhs} = pp f "@;| @[<2>%a%a@;->@;%a@]" diff --git a/parsing/printast.ml b/parsing/printast.ml index 4e3ef2b2cc..c5413b0953 100644 --- a/parsing/printast.ml +++ b/parsing/printast.ml @@ -253,6 +253,10 @@ and pattern i ppf x = | Ppat_exception p -> line i ppf "Ppat_exception\n"; pattern i ppf p + | Ppat_effect(p1, p2) -> + line i ppf "Ppat_effect\n"; + pattern i ppf p1; + pattern i ppf p2 | Ppat_open (m,p) -> line i ppf "Ppat_open \"%a\"\n" fmt_longident_loc m; pattern i ppf p @@ -493,6 +497,24 @@ and extension_constructor_kind i ppf x = line i ppf "Pext_rebind\n"; line (i+1) ppf "%a\n" fmt_longident_loc li; +and effect_constructor i ppf x = + line i ppf "effect_constructor %a\n" fmt_location x.peff_loc; + attributes i ppf x.peff_attributes; + let i = i + 1 in + line i ppf "peff_name = \"%s\"\n" x.peff_name.txt; + line i ppf "peff_kind =\n"; + effect_constructor_kind (i + 1) ppf x.peff_kind; + +and effect_constructor_kind i ppf x = + match x with + Peff_decl(a, r) -> + line i ppf "Peff_decl\n"; + list (i+1) core_type ppf a; + core_type (i + 1) ppf r; + | Peff_rebind li -> + line i ppf "Peff_rebind\n"; + line (i+1) ppf "%a\n" fmt_longident_loc li; + and class_type i ppf x = line i ppf "class_type %a\n" fmt_location x.pcty_loc; attributes i ppf x.pcty_attributes; @@ -707,6 +729,9 @@ and signature_item i ppf x = | Psig_typext te -> line i ppf "Psig_typext\n"; type_extension i ppf te + | Psig_effect ext -> + line i ppf "Psig_effect\n"; + effect_constructor i ppf ext; | Psig_exception te -> line i ppf "Psig_exception\n"; type_exception i ppf te @@ -821,6 +846,9 @@ and structure_item i ppf x = | Pstr_typext te -> line i ppf "Pstr_typext\n"; type_extension i ppf te + | Pstr_effect ext -> + line i ppf "Pstr_effect\n"; + effect_constructor i ppf ext; | Pstr_exception te -> line i ppf "Pstr_exception\n"; type_exception i ppf te diff --git a/runtime/Makefile b/runtime/Makefile index aa7853430a..f908a32df2 100644 --- a/runtime/Makefile +++ b/runtime/Makefile @@ -20,22 +20,24 @@ include $(ROOTDIR)/Makefile.common # Lists of source files BYTECODE_C_SOURCES := $(addsuffix .c, \ - interp misc stacks fix_code startup_aux startup_byt freelist major_gc \ - minor_gc memory alloc roots_byt globroots fail_byt signals \ - signals_byt printexc backtrace_byt backtrace compare ints eventlog \ + interp misc fix_code startup_aux startup_byt major_gc \ + minor_gc memory alloc roots globroots fail_byt signals \ + signals_byt printexc backtrace_byt backtrace compare ints \ floats str array io extern intern hash sys meta parsing gc_ctrl md5 obj \ - lexing callback debugger weak compact finalise custom dynlink \ - spacetime_byt afl $(UNIX_OR_WIN32) bigarray main memprof domain \ + lexing callback debugger weak finalise custom dynlink \ + platform eventlog fiber shared_heap addrmap \ + spacetime_byt afl $(UNIX_OR_WIN32) bigarray main domain \ skiplist codefrag) NATIVE_C_SOURCES := $(addsuffix .c, \ - startup_aux startup_nat main fail_nat roots_nat signals \ - signals_nat misc freelist major_gc minor_gc memory alloc compare ints \ - floats str array io extern intern hash sys parsing gc_ctrl eventlog md5 obj \ - lexing $(UNIX_OR_WIN32) printexc callback weak compact finalise custom \ + startup_aux startup_nat main fail_nat roots signals \ + signals_nat misc major_gc minor_gc memory alloc compare ints \ + floats str array io extern intern hash sys parsing gc_ctrl md5 obj \ + lexing $(UNIX_OR_WIN32) printexc callback weak finalise custom \ globroots backtrace_nat backtrace dynlink_nat debugger meta \ + platform eventlog fiber shared_heap addrmap frame_descriptors \ dynlink clambda_checks spacetime_nat spacetime_snapshot afl bigarray \ - memprof domain skiplist codefrag) + domain skiplist codefrag) GENERATED_HEADERS := caml/opnames.h caml/version.h caml/jumptbl.h CONFIG_HEADERS := caml/m.h caml/s.h @@ -189,7 +191,7 @@ ifneq "$(BYTECODE_SHARED_LIBRARIES)" "" $(INSTALL_PROG) $(BYTECODE_SHARED_LIBRARIES) "$(INSTALL_LIBDIR)" endif mkdir -p "$(INSTALL_INCDIR)" - $(INSTALL_DATA) caml/domain_state.tbl caml/*.h "$(INSTALL_INCDIR)" + $(INSTALL_DATA) caml/domain_state.tbl caml/byte_domain_state.tbl caml/*.h "$(INSTALL_INCDIR)" .PHONY: installopt installopt: diff --git a/runtime/addrmap.c b/runtime/addrmap.c new file mode 100644 index 0000000000..a46ee3a822 --- /dev/null +++ b/runtime/addrmap.c @@ -0,0 +1,120 @@ +#include "caml/config.h" +#include "caml/memory.h" +#include "caml/addrmap.h" + +#define MAX_CHAIN 100 + +static uintnat pos_initial(struct addrmap* t, value key) +{ + uintnat pos = (uintnat)key; + pos *= 0xcc9e2d51; + pos ^= (pos >> 17); + + Assert(Is_power_of_2(t->size)); + return pos & (t->size - 1); +} + +static uintnat pos_next(struct addrmap* t, uintnat pos) +{ + return (pos + 1) & (t->size - 1); +} + +int caml_addrmap_contains(struct addrmap* t, value key) +{ + uintnat pos, i; + + Assert(Is_block(key)); + if (!t->entries) return 0; + + for (i = 0, pos = pos_initial(t, key); + i < MAX_CHAIN; + i++, pos = pos_next(t, pos)) { + if (t->entries[pos].key == ADDRMAP_INVALID_KEY) break; + if (t->entries[pos].key == key) return 1; + } + return 0; +} + +value caml_addrmap_lookup(struct addrmap* t, value key) +{ + uintnat pos; + + Assert(Is_block(key)); + Assert(t->entries); + + for (pos = pos_initial(t, key); ; pos = pos_next(t, pos)) { + Assert(t->entries[pos].key != ADDRMAP_INVALID_KEY); + if (t->entries[pos].key == key) + return t->entries[pos].value; + } +} + +static void addrmap_alloc(struct addrmap* t, uintnat sz) +{ + uintnat i; + Assert(sz > 0 && (sz & (sz - 1)) == 0); /* sz must be a power of 2 */ + t->entries = caml_stat_alloc(sizeof(struct addrmap_entry) * sz); + t->size = sz; + for (i = 0; i < sz; i++) { + t->entries[i].key = ADDRMAP_INVALID_KEY; + t->entries[i].value = ADDRMAP_NOT_PRESENT; + } +} + +void caml_addrmap_clear(struct addrmap* t) { + caml_stat_free(t->entries); + t->entries = 0; + t->size = 0; +} + + + +value* caml_addrmap_insert_pos(struct addrmap* t, value key) { + uintnat i, pos; + Assert(Is_block(key)); + if (!t->entries) { + /* first call, initialise table with a small initial size */ + addrmap_alloc(t, 256); + } + for (i = 0, pos = pos_initial(t, key); + i < MAX_CHAIN; + i++, pos = pos_next(t, pos)) { + if (t->entries[pos].key == ADDRMAP_INVALID_KEY) { + t->entries[pos].key = key; + } + if (t->entries[pos].key == key) { + return &t->entries[pos].value; + } + } + /* failed to insert, rehash and try again */ + { + struct addrmap_entry* old_table = t->entries; + uintnat old_size = t->size; + addrmap_alloc(t, old_size * 2); + for (i = 0; i < old_size; i++) { + if (old_table[i].key != ADDRMAP_INVALID_KEY) { + value* p = caml_addrmap_insert_pos(t, old_table[i].key); + Assert(*p == ADDRMAP_NOT_PRESENT); + *p = old_table[i].value; + } + } + caml_stat_free(old_table); + } + return caml_addrmap_insert_pos(t, key); +} + +void caml_addrmap_insert(struct addrmap* t, value k, value v) { + value* p = caml_addrmap_insert_pos(t, k); + Assert(*p == ADDRMAP_NOT_PRESENT); + *p = v; +} + +void caml_addrmap_iter(struct addrmap* t, void (*f)(value, value)) { + addrmap_iterator i; + for (i = caml_addrmap_iterator(t); + caml_addrmap_iter_ok(t, i); + i = caml_addrmap_next(t, i)) { + f(caml_addrmap_iter_key(t, i), + caml_addrmap_iter_value(t, i)); + } +} diff --git a/runtime/alloc.c b/runtime/alloc.c index 73a8f01b13..239dba0881 100644 --- a/runtime/alloc.c +++ b/runtime/alloc.c @@ -21,16 +21,14 @@ */ #include <string.h> +#include <stdarg.h> #include "caml/alloc.h" #include "caml/custom.h" #include "caml/major_gc.h" #include "caml/memory.h" #include "caml/mlvalues.h" -#include "caml/stacks.h" -#include "caml/signals.h" - -#define Setup_for_gc -#define Restore_after_gc +#include "caml/fiber.h" +#include "caml/domain.h" CAMLexport value caml_alloc (mlsize_t wosize, tag_t tag) { @@ -39,34 +37,128 @@ CAMLexport value caml_alloc (mlsize_t wosize, tag_t tag) CAMLassert (tag < 256); CAMLassert (tag != Infix_tag); - if (wosize <= Max_young_wosize){ - if (wosize == 0){ - result = Atom (tag); - }else{ - Alloc_small (result, wosize, tag); - if (tag < No_scan_tag){ - for (i = 0; i < wosize; i++) Field (result, i) = Val_unit; + if (wosize == 0){ + result = Atom (tag); + } else if (wosize <= Max_young_wosize) { + Alloc_small (result, wosize, tag, { caml_handle_gc_interrupt(); }); + if (tag < No_scan_tag){ + for (i = 0; i < wosize; i++) { + Op_val(result)[i] = Val_unit; } } - }else{ + } else { result = caml_alloc_shr (wosize, tag); - if (tag < No_scan_tag){ - for (i = 0; i < wosize; i++) Field (result, i) = Val_unit; - } - result = caml_check_urgent_gc (result); + result = caml_check_urgent_gc(result); } + return result; } -CAMLexport value caml_alloc_small (mlsize_t wosize, tag_t tag) +static inline void enter_gc_preserving_vals(mlsize_t wosize, value* vals) { - value result; + mlsize_t i; + CAMLparam0(); + /* Copy the values to be preserved to a different array. + The original vals array never escapes, generating better code in + the fast path. */ + CAMLlocalN(vals_copy, wosize); + for (i = 0; i < wosize; i++) vals_copy[i] = vals[i]; + caml_handle_gc_interrupt(); + for (i = 0; i < wosize; i++) vals[i] = vals_copy[i]; + CAMLreturn0; +} - CAMLassert (wosize > 0); - CAMLassert (wosize <= Max_young_wosize); +static inline value do_alloc_small(mlsize_t wosize, tag_t tag, value* vals) +{ + value v; + mlsize_t i; CAMLassert (tag < 256); - Alloc_small (result, wosize, tag); - return result; + Alloc_small(v, wosize, tag, + { enter_gc_preserving_vals(wosize, vals); }); + for (i = 0; i < wosize; i++) { + Op_val(v)[i] = vals[i]; + } + return v; +} + + +CAMLexport value caml_alloc_1 (tag_t tag, value a) +{ + value v[1] = {a}; + return do_alloc_small(1, tag, v); +} + +CAMLexport value caml_alloc_2 (tag_t tag, value a, value b) +{ + value v[2] = {a, b}; + return do_alloc_small(2, tag, v); +} + +CAMLexport value caml_alloc_3 (tag_t tag, value a, value b, value c) +{ + value v[3] = {a, b, c}; + return do_alloc_small(3, tag, v); +} + +CAMLexport value caml_alloc_4 (tag_t tag, value a, value b, value c, value d) +{ + value v[4] = {a, b, c, d}; + return do_alloc_small(4, tag, v); +} + +CAMLexport value caml_alloc_5 (tag_t tag, value a, value b, value c, value d, + value e) +{ + value v[5] = {a, b, c, d, e}; + return do_alloc_small(5, tag, v); +} + +CAMLexport value caml_alloc_6 (tag_t tag, value a, value b, value c, value d, + value e, value f) +{ + value v[6] = {a, b, c, d, e, f}; + return do_alloc_small(6, tag, v); +} + +CAMLexport value caml_alloc_7 (tag_t tag, value a, value b, value c, value d, + value e, value f, value g) +{ + value v[7] = {a, b, c, d, e, f, g}; + return do_alloc_small(7, tag, v); +} + +CAMLexport value caml_alloc_8 (tag_t tag, value a, value b, value c, value d, + value e, value f, value g, value h) +{ + value v[8] = {a, b, c, d, e, f, g, h}; + return do_alloc_small(8, tag, v); +} + +CAMLexport value caml_alloc_9 (tag_t tag, value a, value b, value c, value d, + value e, value f, value g, value h, value i) +{ + value v[9] = {a, b, c, d, e, f, g, h, i}; + return do_alloc_small(9, tag, v); +} + +CAMLexport value caml_alloc_N (mlsize_t wosize, tag_t tag, ...) +{ + va_list args; + mlsize_t i; + value vals[wosize]; + value ret; + va_start(args, tag); + for (i = 0; i < wosize; i++) + vals[i] = va_arg(args, value); + ret = do_alloc_small(wosize, tag, vals); + va_end(args); + return ret; +} + + +CAMLexport value caml_alloc_small (mlsize_t wosize, tag_t tag) +{ + return caml_alloc(wosize, tag); } CAMLexport value caml_alloc_small_with_my_or_given_profinfo (mlsize_t wosize, @@ -81,7 +173,8 @@ CAMLexport value caml_alloc_small_with_my_or_given_profinfo (mlsize_t wosize, CAMLassert (wosize > 0); CAMLassert (wosize <= Max_young_wosize); CAMLassert (tag < 256); - Alloc_small_with_profinfo (result, wosize, tag, profinfo); + Alloc_small_with_profinfo (result, wosize, tag, + { caml_handle_gc_interrupt(); }, profinfo); return result; } } @@ -95,17 +188,11 @@ CAMLexport value caml_alloc_tuple(mlsize_t n) /* [len] is a number of bytes (chars) */ CAMLexport value caml_alloc_string (mlsize_t len) { - value result; mlsize_t offset_index; mlsize_t wosize = (len + sizeof (value)) / sizeof (value); + value result = caml_alloc(wosize, String_tag); - if (wosize <= Max_young_wosize) { - Alloc_small (result, wosize, String_tag); - }else{ - result = caml_alloc_shr (wosize, String_tag); - result = caml_check_urgent_gc (result); - } - Field (result, wosize - 1) = 0; + Op_val (result) [wosize - 1] = 0; offset_index = Bsize_wsize (wosize) - 1; Byte (result, offset_index) = offset_index - len; return result; @@ -140,7 +227,7 @@ CAMLexport value caml_copy_string(char const *s) } CAMLexport value caml_alloc_array(value (*funct)(char const *), - char const ** arr) + char const * const* arr) { CAMLparam0 (); mlsize_t nbr, n; @@ -148,13 +235,14 @@ CAMLexport value caml_alloc_array(value (*funct)(char const *), nbr = 0; while (arr[nbr] != 0) nbr++; - result = caml_alloc (nbr, 0); - for (n = 0; n < nbr; n++) { - /* The two statements below must be separate because of evaluation - order (don't take the address &Field(result, n) before - calling funct, which may cause a GC and move result). */ - v = funct(arr[n]); - caml_modify(&Field(result, n), v); + if (nbr == 0) { + CAMLreturn (Atom(0)); + } else { + result = caml_alloc (nbr, 0); + for (n = 0; n < nbr; n++) { + Store_field(result, n, funct(arr[n])); + } + CAMLreturn (result); } CAMLreturn (result); } @@ -168,12 +256,11 @@ value caml_alloc_float_array(mlsize_t len) /* For consistency with [caml_make_vect], which can't tell whether it should create a float array or not when the size is zero, the tag is set to zero when the size is zero. */ - if (wosize <= Max_young_wosize){ - if (wosize == 0) - return Atom(0); - else - Alloc_small (result, wosize, Double_array_tag); - }else { + if (wosize == 0) { + return Atom(0); + } else if (wosize <= Max_young_wosize) { + Alloc_small (result, wosize, Double_array_tag, { caml_handle_gc_interrupt(); }); + } else { result = caml_alloc_shr (wosize, Double_array_tag); result = caml_check_urgent_gc (result); } @@ -184,17 +271,17 @@ value caml_alloc_float_array(mlsize_t len) } -CAMLexport value caml_copy_string_array(char const ** arr) +CAMLexport value caml_copy_string_array(char const * const * arr) { return caml_alloc_array(caml_copy_string, arr); } -CAMLexport int caml_convert_flag_list(value list, int *flags) +CAMLexport int caml_convert_flag_list(value list, const int *flags) { int res; res = 0; while (list != Val_int(0)) { - res |= flags[Int_val(Field(list, 0))]; + res |= flags[Int_field(list, 0)]; list = Field(list, 1); } return res; @@ -235,7 +322,7 @@ CAMLprim value caml_alloc_dummy_infix(value vsize, value voffset) Closinfo_val(v) = Make_closinfo(0, wosize); if (offset > 0) { v += Bsize_wsize(offset); - Hd_val(v) = Make_header(offset, Infix_tag, Caml_white); + (((header_t *) (v)) [-1]) = Make_header(offset, Infix_tag, 0); } return v; } diff --git a/runtime/amd64.S b/runtime/amd64.S index 056b39cd44..b775989578 100644 --- a/runtime/amd64.S +++ b/runtime/amd64.S @@ -86,31 +86,41 @@ #define CFI_ENDPROC .cfi_endproc #define CFI_ADJUST(n) .cfi_adjust_cfa_offset n #define CFI_OFFSET(r, n) .cfi_offset r, n +#define CFI_DEF_CFA_OFFSET(n) .cfi_def_cfa_offset n +#define CFI_DEF_CFA_REGISTER(r) .cfi_def_cfa_register r #define CFI_SAME_VALUE(r) .cfi_same_value r +#define CFI_SIGNAL_FRAME .cfi_signal_frame +#define CFI_REMEMBER_STATE .cfi_remember_state +#define CFI_RESTORE_STATE .cfi_restore_state #else #define CFI_STARTPROC #define CFI_ENDPROC #define CFI_ADJUST(n) #define CFI_OFFSET(r, n) +#define CFI_DEF_CFA_OFFSET(n) +#define CFI_DEF_CFA_REGISTER(r) #define CFI_SAME_VALUE(r) -#endif - -#ifdef WITH_FRAME_POINTERS +#define CFI_SIGNAL_FRAME +#define CFI_REMEMBER_STATE +#define CFI_RESTORE_STATE -#define ENTER_FUNCTION \ - pushq %rbp; CFI_ADJUST(8); \ - movq %rsp, %rbp -#define LEAVE_FUNCTION \ - popq %rbp; CFI_ADJUST(-8); +#endif +#ifdef DEBUG +#define CHECK_STACK_ALIGNMENT \ + test $0xf, %rsp; jz 9f; int3; 9: +#define IF_DEBUG(...) __VA_ARGS__ #else +#define CHECK_STACK_ALIGNMENT +#define IF_DEBUG(...) +#endif -#define ENTER_FUNCTION \ - subq $8, %rsp; CFI_ADJUST (8); -#define LEAVE_FUNCTION \ - addq $8, %rsp; CFI_ADJUST (-8); +/******************************************************************************/ +/* Access to the current domain state block. */ +/******************************************************************************/ -#endif +#define CAML_CONFIG_H_NO_TYPEDEFS +#include "../runtime/caml/config.h" .set domain_curr_field, 0 #define DOMAIN_STATE(c_type, name) \ @@ -121,79 +131,89 @@ #define Caml_state(var) (8*domain_field_caml_##var)(%r14) -#if defined(__PIC__) && !defined(SYS_mingw64) && !defined(SYS_cygwin) - -/* Position-independent operations on global variables. */ - -/* Store [srcreg] in global [dstlabel]. Clobbers %r11. */ -#define STORE_VAR(srcreg,dstlabel) \ - movq GREL(dstlabel)(%rip), %r11 ; \ - movq srcreg, (%r11) - -#define STORE_VAR32(srcreg,dstlabel) \ - movq GREL(dstlabel)(%rip), %r11 ; \ - movl srcreg, (%r11) - -/* Load global [srclabel] in register [dstreg]. Clobbers %r11. */ -#define LOAD_VAR(srclabel,dstreg) \ - movq GREL(srclabel)(%rip), %r11 ; \ - movq (%r11), dstreg - -/* Compare global [label] with register [reg]. Clobbers %rax. */ -#define CMP_VAR(label,reg) \ - movq GREL(label)(%rip), %rax ; \ - cmpq (%rax), reg - -/* Test 32-bit global [label] against mask [imm]. Clobbers %r11. */ -#define TESTL_VAR(imm,label) \ - movq GREL(label)(%rip), %r11 ; \ - testl imm, (%r11) - -/* Push global [label] on stack. Clobbers %r11. */ -#define PUSH_VAR(srclabel) \ - movq GREL(srclabel)(%rip), %r11 ; \ - pushq (%r11); CFI_ADJUST (8) - -/* Pop global [label] off stack. Clobbers %r11. */ -#define POP_VAR(dstlabel) \ - movq GREL(dstlabel)(%rip), %r11 ; \ - popq (%r11); CFI_ADJUST (-8) - /* Load address of global [label] in register [dst]. */ +#if defined(__PIC__) && !defined(SYS_mingw64) && !defined(SYS_cygwin) #define LEA_VAR(label,dst) \ movq GREL(label)(%rip), dst - #else +#define LEA_VAR(label,dst) \ + leaq G(label)(%rip), dst +#endif -/* Non-PIC operations on global variables. Slightly faster. */ - -#define STORE_VAR(srcreg,dstlabel) \ - movq srcreg, G(dstlabel)(%rip) - -#define STORE_VAR32(srcreg,dstlabel) \ - movl srcreg, G(dstlabel)(%rip) - -#define LOAD_VAR(srclabel,dstreg) \ - movq G(srclabel)(%rip), dstreg - -#define CMP_VAR(label,reg) \ - cmpq G(label)(%rip), %r15 - -#define TESTL_VAR(imm,label) \ - testl imm, G(label)(%rip) +/* Push the current exception handler. Clobbers %r11 */ +#define PUSH_EXN_HANDLER \ + movq Caml_state(exn_handler), %r11; \ + pushq %r11; CFI_ADJUST(8); -#define PUSH_VAR(srclabel) \ - pushq G(srclabel)(%rip) ; CFI_ADJUST(8) +/* Pop the current exception handler. Undoes PUSH_EXN_HANDLER. Clobbers %r11 */ +#define POP_EXN_HANDLER \ + leaq Caml_state(exn_handler), %r11; \ + popq (%r11); CFI_ADJUST(-8) -#define POP_VAR(dstlabel) \ - popq G(dstlabel)(%rip); CFI_ADJUST(-8) +/******************************************************************************/ +/* Stack switching operations */ +/******************************************************************************/ -#define LEA_VAR(label,dst) \ - leaq G(label)(%rip), dst +/* Switch from OCaml to C stack. Clobbers %r10, %r11. + * PUSHED is the number of bytes already pushed by this function. + * It is used to compute the backtrace. */ +#ifdef ASM_CFI_SUPPORTED +#define SWITCH_OCAML_TO_C_NO_CTXT_CFI(PUSHED) \ + CFI_REMEMBER_STATE; \ + .cfi_escape DW_CFA_def_cfa_expression, 5, \ + DW_OP_breg + DW_REG_rsp, Cstack_sp, DW_OP_deref, \ + DW_OP_plus_uconst, (PUSHED) + 8 /* retaddr */ +#else +#define SWITCH_OCAML_TO_C_NO_CTXT_CFI(PUSHED) #endif - +#define SWITCH_OCAML_TO_C_NO_CTXT(PUSHED) \ + /* Fill in Caml_state->current_stack->sp */ \ + movq Caml_state(current_stack), %r10; \ + movq %rsp, Stack_sp(%r10); \ + /* Fill in Caml_state->c_stack */ \ + movq Caml_state(c_stack), %r11; \ + movq %rsp, Cstack_sp(%r11); \ + movq %r10, Cstack_stack(%r11); \ + /* Switch to C stack */ \ + movq %r11, %rsp; \ + SWITCH_OCAML_TO_C_NO_CTXT_CFI(PUSHED) + +/* Switch from C to OCaml stack. Clobbers %r11. */ +#define SWITCH_C_TO_OCAML_NO_CTXT \ + /* Assert that %rsp == Caml_state->c_stack && + Caml_state->c_stack->sp == Caml_state->current_stack->sp */ \ + IF_DEBUG(cmpq %rsp, Caml_state(c_stack); je 8f; int3; 8:\ + movq Caml_state(current_stack), %r11; movq Stack_sp(%r11), %r11; \ + cmpq %r11, Cstack_sp(%rsp); je 8f; int3; 8:) \ + movq Cstack_sp(%rsp), %rsp; \ + CFI_RESTORE_STATE + +/* Load Caml_state->exn_handler into %rsp and restores prior exn_handler. Clobbers %r10 and %r11. */ +#define RESTORE_EXN_HANDLER_OCAML \ + movq Caml_state(exn_handler), %rsp; \ + CFI_DEF_CFA_OFFSET(16); \ + POP_EXN_HANDLER + +/* Switch between OCaml stacks. Clobbers %r12. + Expects old stack in %rsi and target stack in %r10. + Leaves old stack in %rsi and target stack in %r10. */ +#define SWITCH_OCAML_STACKS \ + /* Save OCaml SP and exn_handler in the stack info */ \ + movq %rsp, Stack_sp(%rsi); \ + movq Caml_state(exn_handler), %r12; \ + movq %r12, Stack_exception(%rsi); \ + /* switch stacks */ \ + movq %r10, Caml_state(current_stack); \ + movq Stack_sp(%r10), %rsp; \ + CFI_DEF_CFA_OFFSET(8); \ + /* restore exn_handler for new stack */ \ + movq Stack_exception(%r10), %r12; \ + movq %r12, Caml_state(exn_handler) + +/******************************************************************************/ /* Save and restore all callee-save registers on stack. Keep the stack 16-aligned. */ +/******************************************************************************/ #if defined(SYS_mingw64) || defined(SYS_cygwin) @@ -252,11 +272,9 @@ pushq %r12; CFI_ADJUST(8); CFI_OFFSET(r12, -32); \ pushq %r13; CFI_ADJUST(8); CFI_OFFSET(r13, -40); \ pushq %r14; CFI_ADJUST(8); CFI_OFFSET(r14, -48); \ - pushq %r15; CFI_ADJUST(8); CFI_OFFSET(r15, -56); \ - subq $8, %rsp; CFI_ADJUST(8) + pushq %r15; CFI_ADJUST(8); CFI_OFFSET(r15, -56) #define POP_CALLEE_SAVE_REGS \ - addq $8, %rsp; CFI_ADJUST(-8); \ popq %r15; CFI_ADJUST(-8); CFI_SAME_VALUE(r15); \ popq %r14; CFI_ADJUST(-8); CFI_SAME_VALUE(r14); \ popq %r13; CFI_ADJUST(-8); CFI_SAME_VALUE(r13); \ @@ -278,7 +296,12 @@ # define STACK_PROBE_SIZE 4096 #endif +#define C_call(target) \ + PREPARE_FOR_C_CALL; CHECK_STACK_ALIGNMENT; call target; CLEANUP_AFTER_C_CALL + +/******************************************************************************/ /* Registers holding arguments of C functions. */ +/******************************************************************************/ #if defined(SYS_mingw64) || defined(SYS_cygwin) #define C_ARG_1 %rcx @@ -302,6 +325,26 @@ G(caml_hot__code_begin): G(caml_hot__code_end): #endif +/* struct stack_info */ +#define Stack_sp 0 +#define Stack_exception 8 +#define Stack_handler 16 + +/* struct stack_handler */ +#define Handler_value(REG) 0(REG) +#define Handler_exception(REG) 8(REG) +#define Handler_effect(REG) 16(REG) +#define Handler_parent 24 + +/* struct c_stack_link */ +#define Cstack_stack 0 +#define Cstack_sp 8 +#define Cstack_prev 16 + +/******************************************************************************/ +/* text section */ +/******************************************************************************/ + .text .globl G(caml_system__code_begin) @@ -309,339 +352,453 @@ G(caml_system__code_begin): ret /* just one instruction, so that debuggers don't display caml_system__code_begin instead of caml_call_gc */ -/* Allocation */ -FUNCTION(G(caml_call_gc)) - CFI_STARTPROC -LBL(caml_call_gc): - /* Record lowest stack address and return address. */ - movq (%rsp), %r11 - movq %r11, Caml_state(last_return_address) - leaq 8(%rsp), %r11 - movq %r11, Caml_state(bottom_of_stack) - /* Touch the stack to trigger a recoverable segfault - if insufficient space remains */ - subq $(STACK_PROBE_SIZE), %rsp; CFI_ADJUST(STACK_PROBE_SIZE); - movq %r11, 0(%rsp) - addq $(STACK_PROBE_SIZE), %rsp; CFI_ADJUST(-STACK_PROBE_SIZE); - /* Build array of registers, save it into Caml_state->gc_regs */ -#ifdef WITH_FRAME_POINTERS - ENTER_FUNCTION ; -#else - pushq %rbp; CFI_ADJUST(8); -#endif - pushq %r11; CFI_ADJUST (8); - pushq %r10; CFI_ADJUST (8); - pushq %r13; CFI_ADJUST (8); - pushq %r12; CFI_ADJUST (8); - pushq %r9; CFI_ADJUST (8); - pushq %r8; CFI_ADJUST (8); - pushq %rcx; CFI_ADJUST (8); - pushq %rdx; CFI_ADJUST (8); - pushq %rsi; CFI_ADJUST (8); - pushq %rdi; CFI_ADJUST (8); - pushq %rbx; CFI_ADJUST (8); - pushq %rax; CFI_ADJUST (8); - movq %rsp, Caml_state(gc_regs) - /* Save young_ptr */ - movq %r15, Caml_state(young_ptr) -#ifdef WITH_SPACETIME - STORE_VAR(%r13, caml_spacetime_trie_node_ptr) -#endif - /* Save floating-point registers */ - subq $(16*8), %rsp; CFI_ADJUST (16*8); - movsd %xmm0, 0*8(%rsp) - movsd %xmm1, 1*8(%rsp) - movsd %xmm2, 2*8(%rsp) - movsd %xmm3, 3*8(%rsp) - movsd %xmm4, 4*8(%rsp) - movsd %xmm5, 5*8(%rsp) - movsd %xmm6, 6*8(%rsp) - movsd %xmm7, 7*8(%rsp) - movsd %xmm8, 8*8(%rsp) - movsd %xmm9, 9*8(%rsp) - movsd %xmm10, 10*8(%rsp) - movsd %xmm11, 11*8(%rsp) - movsd %xmm12, 12*8(%rsp) - movsd %xmm13, 13*8(%rsp) - movsd %xmm14, 14*8(%rsp) - movsd %xmm15, 15*8(%rsp) - /* Call the garbage collector */ - PREPARE_FOR_C_CALL - call GCALL(caml_garbage_collection) - CLEANUP_AFTER_C_CALL - /* Restore young_ptr */ +/******************************************************************************/ +/* DWARF */ +/******************************************************************************/ + +/* These constants are taken from: + + DWARF Debugging Information Format, Version 3 + http://dwarfstd.org/doc/Dwarf3.pdf + + with the amd64-specific register numbers coming from + Fig. 3.36 ("DWARF Register Number Mapping") of: + + System V Application Binary Interface + AMD64 Architecture Processor Supplement + Version 1.0 + https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf */ + +#define DW_CFA_def_cfa_expression 0x0f +#define DW_CFA_val_offset 0x14 +#define DW_REG_rbp 6 +#define DW_REG_rsp 7 +#define DW_REG_r13 13 +#define DW_OP_breg 0x70 +#define DW_OP_deref 0x06 +#define DW_OP_plus_uconst 0x23 + +/******************************************************************************/ +/* Allocation */ +/******************************************************************************/ + +/* Save all of the registers that may be in use to a free gc_regs bucket. + Returns: bucket in %r15. Clobbers %r11 (after saving it) */ +#define SAVE_ALL_REGS \ + /* First, save the young_ptr. */ \ + movq %r15, Caml_state(young_ptr); \ + /* Now, use %r15 to point to the gc_regs bucket */ \ + /* We save %r11 first to allow it to be scratch */ \ + movq Caml_state(gc_regs_buckets), %r15; \ + movq %r11, 11*8(%r15); \ + movq 0(%r15), %r11; /* next ptr */ \ + movq %r11, Caml_state(gc_regs_buckets); \ + movq %rax, 0*8(%r15); \ + movq %rbx, 1*8(%r15); \ + movq %rdi, 2*8(%r15); \ + movq %rsi, 3*8(%r15); \ + movq %rdx, 4*8(%r15); \ + movq %rcx, 5*8(%r15); \ + movq %r8, 6*8(%r15); \ + movq %r9, 7*8(%r15); \ + movq %r12, 8*8(%r15); \ + movq %r13, 9*8(%r15); \ + movq %r10, 10*8(%r15); \ + /* %r11 is at 11*8(%r15); */ \ + movq %rbp, 12*8(%r15); \ + movsd %xmm0, (0+13)*8(%r15); \ + movsd %xmm1, (1+13)*8(%r15); \ + movsd %xmm2, (2+13)*8(%r15); \ + movsd %xmm3, (3+13)*8(%r15); \ + movsd %xmm4, (4+13)*8(%r15); \ + movsd %xmm5, (5+13)*8(%r15); \ + movsd %xmm6, (6+13)*8(%r15); \ + movsd %xmm7, (7+13)*8(%r15); \ + movsd %xmm8, (8+13)*8(%r15); \ + movsd %xmm9, (9+13)*8(%r15); \ + movsd %xmm10, (10+13)*8(%r15); \ + movsd %xmm11, (11+13)*8(%r15); \ + movsd %xmm12, (12+13)*8(%r15); \ + movsd %xmm13, (13+13)*8(%r15); \ + movsd %xmm14, (14+13)*8(%r15); \ + movsd %xmm15, (15+13)*8(%r15) + +/* Undo SAVE_ALL_REGS. Expects gc_regs bucket in %r15 */ +#define RESTORE_ALL_REGS \ + /* Restore %rax, freeing up the next ptr slot */ \ + movq 0*8(%r15), %rax; \ + movq Caml_state(gc_regs_buckets), %r11; \ + movq %r11, 0(%r15); /* next ptr */ \ + movq %r15, Caml_state(gc_regs_buckets); \ + /* above: 0*8(%r15),%rax; */ \ + movq 1*8(%r15),%rbx; \ + movq 2*8(%r15),%rdi; \ + movq 3*8(%r15),%rsi; \ + movq 4*8(%r15),%rdx; \ + movq 5*8(%r15),%rcx; \ + movq 6*8(%r15),%r8; \ + movq 7*8(%r15),%r9; \ + movq 8*8(%r15),%r12; \ + movq 9*8(%r15),%r13; \ + movq 10*8(%r15),%r10; \ + movq 11*8(%r15),%r11; \ + movq 12*8(%r15),%rbp; \ + movsd (0+13)*8(%r15),%xmm0; \ + movsd (1+13)*8(%r15),%xmm1; \ + movsd (2+13)*8(%r15),%xmm2; \ + movsd (3+13)*8(%r15),%xmm3; \ + movsd (4+13)*8(%r15),%xmm4; \ + movsd (5+13)*8(%r15),%xmm5; \ + movsd (6+13)*8(%r15),%xmm6; \ + movsd (7+13)*8(%r15),%xmm7; \ + movsd (8+13)*8(%r15),%xmm8; \ + movsd (9+13)*8(%r15),%xmm9; \ + movsd (10+13)*8(%r15),%xmm10; \ + movsd (11+13)*8(%r15),%xmm11; \ + movsd (12+13)*8(%r15),%xmm12; \ + movsd (13+13)*8(%r15),%xmm13; \ + movsd (14+13)*8(%r15),%xmm14; \ + movsd (15+13)*8(%r15),%xmm15; \ movq Caml_state(young_ptr), %r15 - /* Restore all regs used by the code generator */ - movsd 0*8(%rsp), %xmm0 - movsd 1*8(%rsp), %xmm1 - movsd 2*8(%rsp), %xmm2 - movsd 3*8(%rsp), %xmm3 - movsd 4*8(%rsp), %xmm4 - movsd 5*8(%rsp), %xmm5 - movsd 6*8(%rsp), %xmm6 - movsd 7*8(%rsp), %xmm7 - movsd 8*8(%rsp), %xmm8 - movsd 9*8(%rsp), %xmm9 - movsd 10*8(%rsp), %xmm10 - movsd 11*8(%rsp), %xmm11 - movsd 12*8(%rsp), %xmm12 - movsd 13*8(%rsp), %xmm13 - movsd 14*8(%rsp), %xmm14 - movsd 15*8(%rsp), %xmm15 - addq $(16*8), %rsp; CFI_ADJUST(-16*8) - popq %rax; CFI_ADJUST(-8) - popq %rbx; CFI_ADJUST(-8) - popq %rdi; CFI_ADJUST(-8) - popq %rsi; CFI_ADJUST(-8) - popq %rdx; CFI_ADJUST(-8) - popq %rcx; CFI_ADJUST(-8) - popq %r8; CFI_ADJUST(-8) - popq %r9; CFI_ADJUST(-8) - popq %r12; CFI_ADJUST(-8) - popq %r13; CFI_ADJUST(-8) - popq %r10; CFI_ADJUST(-8) - popq %r11; CFI_ADJUST(-8) -#ifdef WITH_FRAME_POINTERS - LEAVE_FUNCTION -#else - popq %rbp; CFI_ADJUST(-8); -#endif - /* Return to caller */ + +FUNCTION(G(caml_call_realloc_stack)) +CFI_STARTPROC + CFI_SIGNAL_FRAME + SAVE_ALL_REGS + movq 8(%rsp), C_ARG_1 /* argument */ + SWITCH_OCAML_TO_C_NO_CTXT(0) + C_call (GCALL(caml_try_realloc_stack)) + SWITCH_C_TO_OCAML_NO_CTXT + cmpq $0, %rax + jz 1f + RESTORE_ALL_REGS ret +1: RESTORE_ALL_REGS + LEA_VAR(caml_exn_Stack_overflow, %rax) + add $16, %rsp /* pop argument, retaddr */ + jmp GCALL(caml_raise_exn) +CFI_ENDPROC +ENDFUNCTION(G(caml_call_realloc_stack)) + +FUNCTION(G(caml_call_gc)) +CFI_STARTPROC + movq $0, %rax + jmp LBL(call_gc_and_retry_alloc) CFI_ENDPROC ENDFUNCTION(G(caml_call_gc)) +FUNCTION(G(caml_call_gc1)) +CFI_STARTPROC + addq $16, %r15 + movq $0, %rax + jmp LBL(call_gc_and_retry_alloc) +CFI_ENDPROC +ENDFUNCTION(G(caml_call_gc1)) + +FUNCTION(G(caml_call_gc2)) +CFI_STARTPROC + addq $24, %r15 + movq $0, %rax + jmp LBL(call_gc_and_retry_alloc) +CFI_ENDPROC +ENDFUNCTION(G(caml_call_gc2)) + +FUNCTION(G(caml_call_gc3)) +CFI_STARTPROC + addq $32, %r15 + movq $0, %rax + jmp LBL(call_gc_and_retry_alloc) +CFI_ENDPROC +ENDFUNCTION(G(caml_call_gc3)) + FUNCTION(G(caml_alloc1)) CFI_STARTPROC +LBL(caml_alloc1): subq $16, %r15 cmpq Caml_state(young_limit), %r15 - jb LBL(caml_call_gc) + jb LBL(100) ret +LBL(100): + movq $16, %rax + jmp LBL(call_gc_and_retry_alloc) CFI_ENDPROC ENDFUNCTION(G(caml_alloc1)) FUNCTION(G(caml_alloc2)) CFI_STARTPROC +LBL(caml_alloc2): subq $24, %r15 cmpq Caml_state(young_limit), %r15 - jb LBL(caml_call_gc) + jb LBL(101) ret +LBL(101): + movq $24, %rax + jmp LBL(call_gc_and_retry_alloc) CFI_ENDPROC ENDFUNCTION(G(caml_alloc2)) FUNCTION(G(caml_alloc3)) CFI_STARTPROC +LBL(caml_alloc3): subq $32, %r15 cmpq Caml_state(young_limit), %r15 - jb LBL(caml_call_gc) + jb LBL(102) ret +LBL(102): + movq $32, %rax + jmp LBL(call_gc_and_retry_alloc) CFI_ENDPROC ENDFUNCTION(G(caml_alloc3)) FUNCTION(G(caml_allocN)) CFI_STARTPROC + CFI_SIGNAL_FRAME +LBL(caml_allocN): + subq %rax, %r15 cmpq Caml_state(young_limit), %r15 - jb LBL(caml_call_gc) + jb LBL(call_gc_and_retry_alloc) ret +LBL(call_gc_and_retry_alloc): + addq %rax, %r15 + SAVE_ALL_REGS + movq %r15, Caml_state(gc_regs) + SWITCH_OCAML_TO_C_NO_CTXT(0) + C_call (GCALL(caml_garbage_collection)) + SWITCH_C_TO_OCAML_NO_CTXT + movq Caml_state(gc_regs), %r15 + RESTORE_ALL_REGS + jmp LBL(caml_allocN) CFI_ENDPROC ENDFUNCTION(G(caml_allocN)) +FUNCTION(G(caml_call_poll)) +CFI_STARTPROC +LBL(caml_call_poll): + SAVE_ALL_REGS + movq %r15, Caml_state(gc_regs) + SWITCH_OCAML_TO_C_NO_CTXT(0) + C_call (GCALL(caml_garbage_collection)) + SWITCH_C_TO_OCAML_NO_CTXT + movq Caml_state(gc_regs), %r15 + RESTORE_ALL_REGS + ret +CFI_ENDPROC +ENDFUNCTION(G(caml_call_poll)) + +/******************************************************************************/ /* Call a C function from OCaml */ +/******************************************************************************/ FUNCTION(G(caml_c_call)) CFI_STARTPROC + CFI_SIGNAL_FRAME LBL(caml_c_call): - /* Record lowest stack address and return address */ - popq Caml_state(last_return_address); CFI_ADJUST(-8) - movq %rsp, Caml_state(bottom_of_stack) - /* equivalent to pushing last return address */ - subq $8, %rsp; CFI_ADJUST(8) -#ifdef WITH_SPACETIME - /* Record the trie node hole pointer that corresponds to - [Caml_state->last_return_address] */ - STORE_VAR(%r13, caml_spacetime_trie_node_ptr) -#endif - /* Touch the stack to trigger a recoverable segfault - if insufficient space remains */ - subq $(STACK_PROBE_SIZE), %rsp; CFI_ADJUST(STACK_PROBE_SIZE); - movq %rax, 0(%rsp) - addq $(STACK_PROBE_SIZE), %rsp; CFI_ADJUST(-STACK_PROBE_SIZE); + /* Arguments: + C arguments : %rdi, %rsi, %rdx, %rcx, %r8, and %r9 + C function : %rax */ + /* Switch from OCaml to C */ + SWITCH_OCAML_TO_C_NO_CTXT(0) /* Make the alloc ptr available to the C code */ movq %r15, Caml_state(young_ptr) /* Call the function (address in %rax) */ - /* No need to PREPARE_FOR_C_CALL since the caller already - reserved the stack space if needed (cf. amd64/proc.ml) */ - jmp *%rax + C_call (*%rax) + /* Prepare for return to OCaml */ + movq Caml_state(young_ptr), %r15 + /* Load ocaml stack and restore global variables */ + SWITCH_C_TO_OCAML_NO_CTXT + /* Return to OCaml caller */ + ret CFI_ENDPROC ENDFUNCTION(G(caml_c_call)) +FUNCTION(G(caml_c_call_stack_args)) +CFI_STARTPROC + CFI_SIGNAL_FRAME + /* Arguments: + C arguments : %rdi, %rsi, %rdx, %rcx, %r8, and %r9 + C function : %rax + C stack args : begin=%r13 end=%r12 */ + /* Switch from OCaml to C */ + SWITCH_OCAML_TO_C_NO_CTXT(0) + /* we use %rbp (otherwise unused) to enable backtraces */ + movq %rsp, %rbp +#ifdef ASM_CFI_SUPPORTED + .cfi_escape DW_CFA_def_cfa_expression, 5, \ + DW_OP_breg + DW_REG_rbp, Cstack_sp, DW_OP_deref, \ + DW_OP_plus_uconst, 8 /* ret addr */ +#endif + /* Make the alloc ptr available to the C code */ + movq %r15, Caml_state(young_ptr) + /* Copy arguments from OCaml to C stack */ +LBL(105): + subq $8, %r12 + cmpq %r13,%r12 + jl LBL(106) + push (%r12); CFI_ADJUST(8) + jmp LBL(105) +LBL(106): + /* Call the function (address in %rax) */ + C_call (*%rax) + /* Pop arguments back off the stack */ + movq Caml_state(c_stack), %rsp + /* Prepare for return to OCaml */ + movq Caml_state(young_ptr), %r15 + /* Load ocaml stack and restore global variables */ + SWITCH_C_TO_OCAML_NO_CTXT + /* Return to OCaml caller */ + ret +CFI_ENDPROC +ENDFUNCTION(G(caml_c_call_stack_args)) + +/******************************************************************************/ /* Start the OCaml program */ +/******************************************************************************/ FUNCTION(G(caml_start_program)) - CFI_STARTPROC +CFI_STARTPROC + CFI_SIGNAL_FRAME /* Save callee-save registers */ PUSH_CALLEE_SAVE_REGS /* Load Caml_state into r14 (was passed as an argument from C) */ movq C_ARG_1, %r14 /* Initial entry point is G(caml_program) */ LEA_VAR(caml_program, %r12) + movq $0, %rax /* dummy */ + movq $0, %rbx /* dummy */ + movq $0, %rdi /* dummy */ + movq $0, %rsi /* dummy */ /* Common code for caml_start_program and caml_callback* */ LBL(caml_start_program): - /* Build a callback link */ -#ifdef WITH_SPACETIME - PUSH_VAR(caml_spacetime_trie_node_ptr) -#else - subq $8, %rsp; CFI_ADJUST (8) /* stack 16-aligned */ -#endif - pushq Caml_state(gc_regs); CFI_ADJUST(8) - pushq Caml_state(last_return_address); CFI_ADJUST(8) - pushq Caml_state(bottom_of_stack); CFI_ADJUST(8) -#ifdef WITH_SPACETIME - /* Save arguments to caml_callback* */ - pushq %rax; CFI_ADJUST (8) - pushq %rbx; CFI_ADJUST (8) - pushq %rdi; CFI_ADJUST (8) - pushq %rsi; CFI_ADJUST (8) - /* No need to push %r12: it's callee-save. */ - movq %r12, C_ARG_1 - LEA_VAR(caml_start_program, C_ARG_2) - call GCALL(caml_spacetime_c_to_ocaml) - popq %rsi; CFI_ADJUST (-8) - popq %rdi; CFI_ADJUST (-8) - popq %rbx; CFI_ADJUST (-8) - popq %rax; CFI_ADJUST (-8) -#endif - /* Setup alloc ptr */ + /* Load young_ptr into %r15 */ movq Caml_state(young_ptr), %r15 - /* Build an exception handler */ - lea LBL(108)(%rip), %r13 - pushq %r13; CFI_ADJUST(8) - pushq Caml_state(exception_pointer); CFI_ADJUST(8) - movq %rsp, Caml_state(exception_pointer) -#ifdef WITH_SPACETIME - LOAD_VAR(caml_spacetime_trie_node_ptr, %r13) + /* Build struct c_stack_link on the C stack */ + subq $24 /* sizeof struct c_stack_link */, %rsp; CFI_ADJUST(24) + movq $0, Cstack_stack(%rsp) + movq $0, Cstack_sp(%rsp) + movq Caml_state(c_stack), %r10 + movq %r10, Cstack_prev(%rsp) + movq %rsp, Caml_state(c_stack) + CHECK_STACK_ALIGNMENT + /* Load the OCaml stack. */ + movq Caml_state(current_stack), %r11 + movq Stack_sp(%r11), %r10 + /* Store the stack pointer to allow DWARF unwind and + gc_regs for callbacks during a GC */ + subq $16, %r10 + movq %rsp, 0(%r10) + movq Caml_state(gc_regs), %r11 + movq %r11, 8(%r10) + /* Build a handler for exceptions raised in OCaml on the OCaml stack. */ + subq $16, %r10 + lea LBL(109)(%rip), %r11 + movq %r11, 8(%r10) + /* link in the previous exn_handler so that copying stacks works */ + movq Caml_state(exn_handler), %r11 + movq %r11, 0(%r10) + movq %r10, Caml_state(exn_handler) + /* Switch stacks and call the OCaml code */ + movq %r10, %rsp +#ifdef ASM_CFI_SUPPORTED + CFI_REMEMBER_STATE + .cfi_escape DW_CFA_def_cfa_expression, 3 + 2, \ + DW_OP_breg + DW_REG_rsp, 16, DW_OP_deref,\ + DW_OP_plus_uconst, \ + 24 /* struct c_stack_link */ + 6*8 /* callee save regs */ + 8 /* ret addr */ #endif - /* Call the OCaml code */ call *%r12 -LBL(107): - /* Pop the exception handler */ - popq Caml_state(exception_pointer); CFI_ADJUST(-8) - popq %r12; CFI_ADJUST(-8) /* dummy register */ -LBL(109): +LBL(108): + /* pop exn handler */ + movq 0(%rsp), %r11 + movq %r11, Caml_state(exn_handler) + leaq 16(%rsp), %r10 +1: /* restore GC regs */ + movq 8(%r10), %r11 + movq %r11, Caml_state(gc_regs) + addq $16, %r10 /* Update alloc ptr */ movq %r15, Caml_state(young_ptr) - /* Pop the callback link, restoring the global variables */ - popq Caml_state(bottom_of_stack); CFI_ADJUST(-8) - popq Caml_state(last_return_address); CFI_ADJUST(-8) - popq Caml_state(gc_regs); CFI_ADJUST(-8) -#ifdef WITH_SPACETIME - POP_VAR(caml_spacetime_trie_node_ptr) -#else - addq $8, %rsp; CFI_ADJUST (-8); -#endif + /* Return to C stack. */ + movq Caml_state(current_stack), %r11 + movq %r10, Stack_sp(%r11) + movq Caml_state(c_stack), %rsp + CFI_RESTORE_STATE + /* Pop the struct c_stack_link */ + movq Cstack_prev(%rsp), %r10 + movq %r10, Caml_state(c_stack) + addq $24, %rsp; CFI_ADJUST(-24) /* Restore callee-save registers. */ POP_CALLEE_SAVE_REGS /* Return to caller. */ ret -LBL(108): +LBL(109): /* Exception handler*/ /* Mark the bucket as an exception result and return it */ orq $2, %rax - jmp LBL(109) + /* exn handler already popped here */ + movq %rsp, %r10 + jmp 1b CFI_ENDPROC ENDFUNCTION(G(caml_start_program)) +/******************************************************************************/ +/* Exceptions */ +/******************************************************************************/ + /* Raise an exception from OCaml */ FUNCTION(G(caml_raise_exn)) CFI_STARTPROC +LBL(caml_raise_exn): testq $1, Caml_state(backtrace_active) - jne LBL(110) - movq Caml_state(exception_pointer), %rsp - popq Caml_state(exception_pointer); CFI_ADJUST(-8) + jne LBL(116) + RESTORE_EXN_HANDLER_OCAML ret -LBL(110): - movq %rax, %r12 /* Save exception bucket */ - movq %rax, C_ARG_1 /* arg 1: exception bucket */ -#ifdef WITH_FRAME_POINTERS - ENTER_FUNCTION - movq 8(%rsp), C_ARG_2 /* arg 2: pc of raise */ - leaq 16(%rsp), C_ARG_3 /* arg 3: sp at raise */ -#else - popq C_ARG_2 /* arg 2: pc of raise */ - movq %rsp, C_ARG_3 /* arg 3: sp at raise */ -#endif - /* arg 4: sp of handler */ - movq Caml_state(exception_pointer), C_ARG_4 - /* PR#5700: thanks to popq above, stack is now 16-aligned */ - /* Thanks to ENTER_FUNCTION, stack is now 16-aligned */ - PREPARE_FOR_C_CALL /* no need to cleanup after */ - call GCALL(caml_stash_backtrace) - movq %r12, %rax /* Recover exception bucket */ - movq Caml_state(exception_pointer), %rsp - popq Caml_state(exception_pointer); CFI_ADJUST(-8) +LBL(116): + movq $0, Caml_state(backtrace_pos) +LBL(117): + movq %rsp, %r10 /* Save OCaml stack pointer */ + movq %rax, %r12 /* Save exception bucket */ + movq Caml_state(c_stack), %rsp + movq %rax, C_ARG_1 /* arg 1: exception bucket */ + movq (%r10), C_ARG_2 /* arg 2: pc of raise */ + leaq 8(%r10), C_ARG_3 /* arg 3: sp at raise */ + movq Caml_state(exn_handler), C_ARG_4 + /* arg 4: sp of handler */ + C_call (GCALL(caml_stash_backtrace)) + movq %r12, %rax /* Recover exception bucket */ + RESTORE_EXN_HANDLER_OCAML ret CFI_ENDPROC ENDFUNCTION(G(caml_raise_exn)) +FUNCTION(G(caml_reraise_exn)) +CFI_STARTPROC + testq $1, Caml_state(backtrace_active) + jne LBL(117) + RESTORE_EXN_HANDLER_OCAML + ret +CFI_ENDPROC +ENDFUNCTION(G(caml_reraise_exn)) + /* Raise an exception from C */ FUNCTION(G(caml_raise_exception)) CFI_STARTPROC - movq C_ARG_1, %r14 /* Caml_state */ - testq $1, Caml_state(backtrace_active) - jne LBL(112) + movq C_ARG_1, %r14 /* Caml_state */ movq C_ARG_2, %rax - movq Caml_state(exception_pointer), %rsp /* Cut stack */ - /* Recover previous exception handler */ - popq Caml_state(exception_pointer); CFI_ADJUST(-8) - movq Caml_state(young_ptr), %r15 /* Reload alloc ptr */ - ret -LBL(112): -#ifdef WITH_FRAME_POINTERS - ENTER_FUNCTION ; -#endif - /* Save exception bucket. Caml_state in r14 saved across C calls. */ - movq C_ARG_2, %r12 - /* arg 1: exception bucket */ - movq C_ARG_2, C_ARG_1 - /* arg 2: pc of raise */ - movq Caml_state(last_return_address), C_ARG_2 - /* arg 3: sp of raise */ - movq Caml_state(bottom_of_stack), C_ARG_3 - /* arg 4: sp of handler */ - movq Caml_state(exception_pointer), C_ARG_4 -#ifndef WITH_FRAME_POINTERS - subq $8, %rsp /* PR#5700: maintain stack alignment */ -#endif - PREPARE_FOR_C_CALL /* no need to cleanup after */ - call GCALL(caml_stash_backtrace) - movq %r12, %rax /* Recover exception bucket */ - movq Caml_state(exception_pointer), %rsp - /* Recover previous exception handler */ - popq Caml_state(exception_pointer); CFI_ADJUST(-8) - movq Caml_state(young_ptr), %r15 /* Reload alloc ptr */ - ret + /* Load young_ptr into %r15 */ + movq Caml_state(young_ptr), %r15 + /* Discard the C stack pointer and reset to ocaml stack */ + movq Caml_state(current_stack), %r10 + movq Stack_sp(%r10), %rsp /* FIXME: CFI */ + jmp LBL(caml_raise_exn) CFI_ENDPROC ENDFUNCTION(G(caml_raise_exception)) -/* Raise a Stack_overflow exception on return from segv_handler() - (in runtime/signals_nat.c). On entry, the stack is full, so we - cannot record a backtrace. - No CFI information here since this function disrupts the stack - backtrace anyway. */ - -FUNCTION(G(caml_stack_overflow)) - movq C_ARG_1, %r14 /* Caml_state */ - LEA_VAR(caml_exn_Stack_overflow, %rax) - movq Caml_state(exception_pointer), %rsp /* cut the stack */ - /* Recover previous exn handler */ - popq Caml_state(exception_pointer) - ret /* jump to handler's code */ -ENDFUNCTION(G(caml_stack_overflow)) - +/******************************************************************************/ /* Callback from C to OCaml */ +/******************************************************************************/ FUNCTION(G(caml_callback_asm)) CFI_STARTPROC @@ -652,6 +809,8 @@ CFI_STARTPROC movq C_ARG_2, %rbx /* closure */ movq 0(C_ARG_3), %rax /* argument */ movq 0(%rbx), %r12 /* code pointer */ + movq $0, %rdi /* dummy */ + movq $0, %rsi /* dummy */ jmp LBL(caml_start_program) CFI_ENDPROC ENDFUNCTION(G(caml_callback_asm)) @@ -666,6 +825,7 @@ CFI_STARTPROC movq 0(C_ARG_3), %rax /* first argument */ movq 8(C_ARG_3), %rbx /* second argument */ LEA_VAR(caml_apply2, %r12) /* code pointer */ + movq $0, %rsi /* dummy */ jmp LBL(caml_start_program) CFI_ENDPROC ENDFUNCTION(G(caml_callback2_asm)) @@ -685,6 +845,147 @@ CFI_STARTPROC CFI_ENDPROC ENDFUNCTION(G(caml_callback3_asm)) +/******************************************************************************/ +/* Fibers */ +/******************************************************************************/ + +FUNCTION(G(caml_perform)) +CFI_STARTPROC + /* %rax: effect to perform + %rbx: freshly allocated continuation */ + movq Caml_state(current_stack), %rsi /* %rsi := old stack */ + leaq 1(%rsi), %rdi /* %rdi (cont_tail) := Val_ptr(old stack) */ + movq %rdi, 0(%rbx) /* Initialise continuation */ +LBL(do_perform): + /* %rsi: old stack + %rdi: cont_tail */ + movq Stack_handler(%rsi), %r11 /* %r11 := old stack -> handler */ + movq Handler_parent(%r11), %r10 /* %r10 := parent stack */ + cmpq $0, %r10 /* parent is NULL? */ + je LBL(112) + SWITCH_OCAML_STACKS /* preserves r11 and rsi */ + /* we have to null the Handler_parent after the switch because + the Handler_parent is needed to unwind the stack for backtraces */ + movq $0, Handler_parent(%r11) /* Set parent stack of performer to NULL */ + movq Handler_effect(%r11), %rsi /* %rsi := effect handler */ + jmp GCALL(caml_apply3) +LBL(112): + /* switch back to original performer before raising Unhandled + (no-op unless this is a reperform) */ + movq 0(%rbx), %r10 /* load performer stack from continuation */ + subq $1, %r10 /* r10 := Ptr_val(r10) */ + movq Caml_state(current_stack), %rsi + SWITCH_OCAML_STACKS + /* No parent stack. Raise Unhandled. */ + LEA_VAR(caml_exn_Unhandled, %rax) + jmp LBL(caml_raise_exn) +CFI_ENDPROC +ENDFUNCTION(G(caml_perform)) + +FUNCTION(G(caml_reperform)) +CFI_STARTPROC + /* %rax: effect to reperform + %rbx: continuation + %rdi: continuation tail */ + movq Caml_state(current_stack), %rsi /* %rsi := old stack */ + movq (Stack_handler-1)(%rdi), %r10 + movq %rsi, Handler_parent(%r10) /* Append to cont_tail */ + leaq 1(%rsi), %rdi /* %rdi (cont_tail) := Val_ptr(old stack) */ + jmp LBL(do_perform) +CFI_ENDPROC +ENDFUNCTION(G(caml_reperform)) + +FUNCTION(G(caml_resume)) +CFI_STARTPROC + /* %rax -> stack, %rbx -> fun, %rdi -> arg */ + leaq -1(%rax), %r10 /* %r10 (new stack) = Ptr_val(%rax) */ + movq %rdi, %rax /* %rax := argument to function in %rbx */ + /* check if stack null, then already used */ + testq %r10, %r10 + jz 2f + /* Find end of list of stacks and add current */ + movq %r10, %rsi +1: movq Stack_handler(%rsi), %rcx + movq Handler_parent(%rcx), %rsi + testq %rsi, %rsi + jnz 1b + movq Caml_state(current_stack), %rsi + movq %rsi, Handler_parent(%rcx) + SWITCH_OCAML_STACKS + jmp *(%rbx) +2: LEA_VAR(caml_exn_Continuation_already_taken, %rax) + jmp LBL(caml_raise_exn) +CFI_ENDPROC +ENDFUNCTION(G(caml_resume)) + +/* Run a function on a new stack, + then invoke either the value or exception handler */ +FUNCTION(G(caml_runstack)) +CFI_STARTPROC + CFI_SIGNAL_FRAME + /* %rax -> stack, %rbx -> fun, %rdi -> arg */ + andq $-2, %rax /* %rax = Ptr_val(%rax) */ + /* save old stack pointer and exception handler */ + movq Caml_state(current_stack), %rcx + movq Caml_state(exn_handler), %r10 + movq %rsp, Stack_sp(%rcx) + movq %r10, Stack_exception(%rcx) + /* Load new stack pointer and set parent */ + movq Stack_handler(%rax), %r11 + movq %rcx, Handler_parent(%r11) + movq %rax, Caml_state(current_stack) + movq Stack_sp(%rax), %r11 + /* Create an exception handler on the target stack + after 16byte DWARF & gc_regs block (which is unused here) */ + subq $32, %r11 + leaq LBL(fiber_exn_handler)(%rip), %r10 + movq %r10, 8(%r11) + /* link the previous exn_handler so that copying stacks works */ + movq Stack_exception(%rax), %r10 + movq %r10, 0(%r11) + movq %r11, Caml_state(exn_handler) + /* Switch to the new stack */ + movq %r11, %rsp +#ifdef ASM_CFI_SUPPORTED + CFI_REMEMBER_STATE + .cfi_escape DW_CFA_def_cfa_expression, 3+3+2, \ + DW_OP_breg + DW_REG_rsp, 32 /* exn */ + Handler_parent, DW_OP_deref,\ + DW_OP_plus_uconst, Stack_sp, DW_OP_deref,\ + DW_OP_plus_uconst, 8 /* ret addr */ +#endif + movq %rdi, %rax /* first argument */ + callq *(%rbx) /* closure in %rbx (second argument) */ +LBL(frame_runstack): + leaq 32(%rsp), %r11 /* SP with exn handler popped */ + movq Handler_value(%r11), %rbx +1: movq Caml_state(current_stack), %rdi /* arg to caml_free_stack */ + /* restore parent stack and exn_handler into Caml_state */ + movq Handler_parent(%r11), %r10 + movq Stack_exception(%r10), %r11 + movq %r10, Caml_state(current_stack) + movq %r11, Caml_state(exn_handler) + /* free old stack by switching directly to c_stack; is a no-alloc call */ + movq Stack_sp(%r10), %r13 /* saved across C call */ + CFI_RESTORE_STATE + CFI_REMEMBER_STATE + CFI_DEF_CFA_REGISTER(DW_REG_r13) + movq %rax, %r12 /* save %rax across C call */ + movq Caml_state(c_stack), %rsp + call GCALL(caml_free_stack) + /* switch directly to parent stack with correct return */ + movq %r13, %rsp + CFI_RESTORE_STATE + movq %r12, %rax + + /* Invoke handle_value (or handle_exn) */ + jmp *(%rbx) +LBL(fiber_exn_handler): + leaq 16(%rsp), %r11 + movq Handler_exception(%r11), %rbx + jmp 1b +CFI_ENDPROC +ENDFUNCTION(G(caml_runstack)) + FUNCTION(G(caml_ml_array_bound_error)) CFI_STARTPROC LEA_VAR(caml_array_bound_error, %rax) @@ -692,6 +993,20 @@ CFI_STARTPROC CFI_ENDPROC ENDFUNCTION(G(caml_ml_array_bound_error)) +FUNCTION(G(caml_assert_stack_invariants)) +CFI_STARTPROC +/* CHECK_STACK_ALIGNMENT */ + movq Caml_state(current_stack), %r11 + movq %rsp, %r10 + subq %r11, %r10 /* %r10: number of bytes left on stack */ + /* can be two words over: the return addresses */ + cmp $((Stack_threshold_words + Stack_ctx_words - 2)*8), %r10 + jge 1f + int3 +1: ret +CFI_ENDPROC +ENDFUNCTION(G(caml_assert_stack_invariants)) + .globl G(caml_system__code_end) G(caml_system__code_end): @@ -699,27 +1014,14 @@ G(caml_system__code_end): .globl G(caml_system__frametable) .align EIGHT_ALIGN G(caml_system__frametable): - .quad 1 /* one descriptor */ - .quad LBL(107) /* return address into callback */ + .quad 2 /* three descriptors */ + .quad LBL(108) /* return address into callback */ .value -1 /* negative frame size => use callback link */ .value 0 /* no roots here */ .align EIGHT_ALIGN - .quad 16 - .quad 0 - .string "amd64.S" - -#ifdef WITH_SPACETIME - .data - .globl G(caml_system__spacetime_shapes) - .align EIGHT_ALIGN -G(caml_system__spacetime_shapes): - .quad G(caml_start_program) - .quad 2 /* indirect call point to OCaml code */ - .quad LBL(107) /* in caml_start_program / caml_callback* */ - .quad 0 /* end of shapes for caml_start_program */ - .quad 0 /* end of shape table */ - .align EIGHT_ALIGN -#endif + .quad LBL(frame_runstack) /* return address into fiber_val_handler */ + .value -1 /* negative frame size => use callback link */ + .value 0 /* no roots here */ #if defined(SYS_macosx) .literal16 diff --git a/runtime/arm64.S b/runtime/arm64.S index 6bad4ce877..13938a48c9 100644 --- a/runtime/arm64.S +++ b/runtime/arm64.S @@ -20,19 +20,12 @@ /* Special registers */ -#define DOMAIN_STATE_PTR x25 -#define TRAP_PTR x26 +#define TRAP_OFF x26 #define ALLOC_PTR x27 #define ALLOC_LIMIT x28 #define ARG x15 #define TMP x16 #define TMP2 x17 -#define ARG_DOMAIN_STATE_PTR x18 - -#define C_ARG_1 x0 -#define C_ARG_2 x1 -#define C_ARG_3 x2 -#define C_ARG_4 x3 /* Support for CFI directives */ @@ -50,34 +43,13 @@ #define CFI_OFFSET(r,n) #endif - .set domain_curr_field, 0 -#define DOMAIN_STATE(c_type, name) \ - .equ domain_field_caml_##name, domain_curr_field ; \ - .set domain_curr_field, domain_curr_field + 1 -#include "../runtime/caml/domain_state.tbl" -#undef DOMAIN_STATE - -#define Caml_state(var) [x25, 8*domain_field_caml_##var] - -#if defined(__PIC__) - -#define ADDRGLOBAL(reg,symb) \ - adrp TMP2, :got:symb; \ - ldr reg, [TMP2, #:got_lo12:symb] -#else - -#define ADDRGLOBAL(reg,symb) \ - adrp reg, symb; \ - add reg, reg, #:lo12:symb - -#endif - #if defined(FUNCTION_SECTIONS) #define TEXT_SECTION(name) .section .text.##name,"ax",%progbits #else #define TEXT_SECTION(name) #endif + #if defined(FUNCTION_SECTIONS) TEXT_SECTION(caml_hot__code_begin) .globl caml_hot__code_begin @@ -95,371 +67,763 @@ caml_hot__code_end: .type name, %function; \ name: + +/******************************************************************************/ +/* Access to the current domain state block. */ +/******************************************************************************/ + +#define CAML_CONFIG_H_NO_TYPEDEFS +#include "../runtime/caml/config.h" + +#define GET_DOMAIN_STATE(reg) \ + and reg, ALLOC_PTR, (0xffffffffffffffff << Minor_heap_align_bits) + +/* CR mshinwell: We should optimize the case where there are multiple + loads/stores in one go to the domain state block. */ + + .set domain_curr_field, 0 +#define DOMAIN_STATE(c_type, name) \ + .equ domain_field_caml_##name, domain_curr_field ; \ + .set domain_curr_field, domain_curr_field + 1 +#include "../runtime/caml/domain_state.tbl" +#undef DOMAIN_STATE + +/* Load from the current domain state block. Clobbers only the destination. */ +#define LOAD_TL_VAR(var,dstreg) \ + GET_DOMAIN_STATE(dstreg) ; \ + ldr dstreg, [dstreg, (8 * domain_field_##var)] + +/* Store to the current domain state block. Clobbers TMP. */ +#define STORE_TL_VAR(srcreg, var) \ + GET_DOMAIN_STATE(TMP) ; \ + str srcreg, [TMP, (8 * domain_field_##var)] + +/* Push pair of values from current domain state block to the stack. Clobbers + TMP. */ +#define PUSH_TL_PAIR(var1,var2) \ + LOAD_TL_VAR(var2, TMP); \ + str TMP, [sp, -16]!; \ + CFI_ADJUST(16); \ + LOAD_TL_VAR(var1, TMP); \ + str TMP, [sp, 8] + +/* Pop pair of values from the stack and store in the current domain state + block. Clobbers TMP and TMP2. */ +#define POP_TL_PAIR(var1,var2) \ + ldr TMP2, [sp], 16; \ + CFI_ADJUST(-16); \ + STORE_TL_VAR(TMP2, var2); \ + ldr TMP2,[sp, -8]; \ + STORE_TL_VAR(TMP2, var1) + + +/******************************************************************************/ +/* Macros to load and store global variables. Destroy TMP2 */ +/******************************************************************************/ + +#if defined(__PIC__) + +#define ADDRGLOBAL(reg,symb) \ + adrp TMP2, :got:symb; \ + ldr reg, [TMP2, #:got_lo12:symb] + +#else + +#define ADDRGLOBAL(reg,symb) \ + adrp reg, symb; \ + add reg, reg, #:lo12:symb + +#endif + +/******************************************************************************/ +/* Stack switching operations */ +/******************************************************************************/ + +/* Switch from OCaml to C stack. Clobbers REG & TRAP_OFF. */ +#define SWITCH_OCAML_TO_C_NO_CTXT(REG) \ + /* Save OCaml SP in the stack slot */ \ + LOAD_TL_VAR(caml_stack_high, TRAP_OFF); \ + sub TRAP_OFF, sp, TRAP_OFF; \ + asr TRAP_OFF, TRAP_OFF, #3; \ + LOAD_TL_VAR(caml_current_stack, REG); \ + str TRAP_OFF, [REG]; \ + /* Switch to system stack */ \ + LOAD_TL_VAR(caml_system_sp, REG); \ + mov sp, REG + +/* Switch from OCaml to C stack. Also builds a context at + * the bottom of the OCaml stack. Clobbers REG & TRAP_OFF. */ +#define SWITCH_OCAML_TO_C(REG) \ + /* Build caml_context at the bottom of the stack */ \ + str TRAP_OFF, [sp, -32]!; /* save trap_off */ \ + CFI_ADJUST(24); \ + str x30, [sp, 24]; /* return address */ \ + str xzr, [sp, 8]; /* gc_regs_slot <- 0 */ \ + SWITCH_OCAML_TO_C_NO_CTXT(REG) + +/* Switch from C to OCaml stack. Clobbers REG. */ +#define SWITCH_C_TO_OCAML_NO_CTXT(REG) \ + /* Switch to OCaml stack */ \ + LOAD_TL_VAR(caml_stack_high, REG); \ + mov sp, REG; \ + LOAD_TL_VAR(caml_current_stack, REG); \ + /* REG is Stack_sp(caml_current_stack) */ \ + ldr REG, [REG]; \ + add sp, sp, REG, LSL 3 + +/* Switch from C to OCaml stack. Also pops the context + * from the bottom of the OCaml stack. Clobbers REG. */ +#define SWITCH_C_TO_OCAML(REG) \ + SWITCH_C_TO_OCAML_NO_CTXT(REG); \ + /* Pop the caml_context from the bottom of stack updating TRAP_OFF and return address. */ \ + ldr x30, [sp, 24]; \ + ldr TRAP_OFF, [sp], 32 + +/* Restore exception handler for OCaml code. Cuts stack, and loads target address in TMP. */ +#define RESTORE_EXN_HANDLER_OCAML \ + LOAD_TL_VAR(caml_stack_high, TMP); \ + sub sp, TMP, TRAP_OFF; \ + ldr TMP, [sp, 8]; \ + ldr TRAP_OFF, [sp], 16 + +/* Load [caml_system_stack_high - TRAP_OFF] into sp. Cuts the stack, and loads the target address in TMP. */ +#define RESTORE_EXN_HANDLER_SYS \ + LOAD_TL_VAR(caml_system_stack_high, TMP); \ + sub sp, TMP, TRAP_OFF; \ + ldr TMP, [sp, 8]; \ + ldr TRAP_OFF, [sp], 16 + +/* Switch between OCaml stacks. + * arguments : target stack (x0) */ +#define SWITCH_OCAML_STACKS \ + /* Switch from OCaml to C */ \ + SWITCH_OCAML_TO_C(TMP); \ + ADDRGLOBAL(ARG,caml_switch_stack); \ + blr ARG; \ + SWITCH_C_TO_OCAML(TMP) + +/* Stack-local variables */ + +#define Stack_sp(REG) [REG] +#define Stack_dirty(REG) [REG, 8] +#define Stack_handle_value(REG) [REG, 16] +#define Stack_handle_exception(REG) [REG, 24] +#define Stack_handle_effect(REG) [REG, 32] +#define Stack_parent(REG) [REG, 40] + +/******************************************************************************/ /* Allocation functions and GC interface */ +/******************************************************************************/ + .globl caml_system__code_begin caml_system__code_begin: -FUNCTION(caml_call_gc) - CFI_STARTPROC -.Lcaml_call_gc: - /* Record return address */ - str x30, Caml_state(last_return_address) - /* Record lowest stack address */ - mov TMP, sp - str TMP, Caml_state(bottom_of_stack) - /* Set up stack space, saving return address and frame pointer */ - /* (2 regs RA/GP, 24 allocatable int regs, 24 caller-save float regs) * 8 */ - CFI_OFFSET(29, -400) - CFI_OFFSET(30, -392) - stp x29, x30, [sp, -400]! - CFI_ADJUST(400) - add x29, sp, #0 - /* Save allocatable integer registers on the stack, in the order - given in proc.ml */ - stp x0, x1, [sp, 16] - stp x2, x3, [sp, 32] - stp x4, x5, [sp, 48] - stp x6, x7, [sp, 64] - stp x8, x9, [sp, 80] - stp x10, x11, [sp, 96] - stp x12, x13, [sp, 112] - stp x14, x15, [sp, 128] - stp x19, x20, [sp, 144] - stp x21, x22, [sp, 160] - stp x23, x24, [sp, 176] - str x25, [sp, 192] - /* Save caller-save floating-point registers on the stack - (callee-saves are preserved by caml_garbage_collection) */ - stp d0, d1, [sp, 208] - stp d2, d3, [sp, 224] - stp d4, d5, [sp, 240] - stp d6, d7, [sp, 256] - stp d16, d17, [sp, 272] - stp d18, d19, [sp, 288] - stp d20, d21, [sp, 304] - stp d22, d23, [sp, 320] - stp d24, d25, [sp, 336] - stp d26, d27, [sp, 352] - stp d28, d29, [sp, 368] - stp d30, d31, [sp, 384] - /* Store pointer to saved integer registers in Caml_state->gc_regs */ - add TMP, sp, #16 - str TMP, Caml_state(gc_regs) - /* Save current allocation pointer for debugging purposes */ - str ALLOC_PTR, Caml_state(young_ptr) - /* Save trap pointer in case an exception is raised during GC */ - str TRAP_PTR, Caml_state(exception_pointer) - /* Call the garbage collector */ - bl caml_garbage_collection - /* Restore registers */ - ldp x0, x1, [sp, 16] - ldp x2, x3, [sp, 32] - ldp x4, x5, [sp, 48] - ldp x6, x7, [sp, 64] - ldp x8, x9, [sp, 80] - ldp x10, x11, [sp, 96] - ldp x12, x13, [sp, 112] - ldp x14, x15, [sp, 128] - ldp x19, x20, [sp, 144] - ldp x21, x22, [sp, 160] - ldp x23, x24, [sp, 176] - ldr x25, [sp, 192] - ldp d0, d1, [sp, 208] - ldp d2, d3, [sp, 224] - ldp d4, d5, [sp, 240] - ldp d6, d7, [sp, 256] - ldp d16, d17, [sp, 272] - ldp d18, d19, [sp, 288] - ldp d20, d21, [sp, 304] - ldp d22, d23, [sp, 320] - ldp d24, d25, [sp, 336] - ldp d26, d27, [sp, 352] - ldp d28, d29, [sp, 368] - ldp d30, d31, [sp, 384] - /* Reload new allocation pointer and allocation limit */ - ldr ALLOC_PTR, Caml_state(young_ptr) - ldr ALLOC_LIMIT, Caml_state(young_limit) - /* Free stack space and return to caller */ +#define SAVE_ALL_REGS_AND_CALL(TARGET_FUN) \ + /* Set up stack space, saving return address and frame pointer */ \ + /* (2 regs RA/GP, 24 allocatable int regs, 24 caller-save float regs) * 8 */ \ + stp x29, x30, [sp, -400]!; \ + CFI_ADJUST(400); \ + add x29, sp, 0 ; \ + /* Save allocatable integer registers on the stack, in the order given in proc.ml */ \ + stp x0, x1, [sp, 16]; \ + stp x2, x3, [sp, 32]; \ + stp x4, x5, [sp, 48]; \ + stp x6, x7, [sp, 64]; \ + stp x8, x9, [sp, 80]; \ + stp x10, x11, [sp, 96]; \ + stp x12, x13, [sp, 112]; \ + stp x14, x15, [sp, 128]; \ + stp x19, x20, [sp, 144]; \ + stp x21, x22, [sp, 160]; \ + stp x23, x24, [sp, 176]; \ + str x25, [sp, 192]; \ + /* Save caller-save floating-point registers on the stack. */ \ + /* (callee-saves are preserved by caml_garbage_collection) */ \ + stp d0, d1, [sp, 208]; \ + stp d2, d3, [sp, 224]; \ + stp d4, d5, [sp, 240]; \ + stp d6, d7, [sp, 256]; \ + stp d16, d17, [sp, 272]; \ + stp d18, d19, [sp, 288]; \ + stp d20, d21, [sp, 304]; \ + stp d22, d23, [sp, 320]; \ + stp d24, d25, [sp, 336]; \ + stp d26, d27, [sp, 352]; \ + stp d28, d29, [sp, 368]; \ + stp d30, d31, [sp, 384]; \ + /* Save current allocation pointer */ \ + STORE_TL_VAR(ALLOC_PTR, caml_young_ptr); \ + /* Update in OCaml stack's context, the pointer to gc_regs. */ \ + /* Store pointer to saved integer registers in caml_gc_regs */ \ + add x0, sp, 16 ; \ + bl caml_update_gc_regs_slot; \ + /* Args are relevant only for caml_realloc_stack */ \ + mov x0, 0; \ + bl TARGET_FUN; \ + /* Restore registers */ \ + ldp x0, x1, [sp, 16]; \ + ldp x2, x3, [sp, 32]; \ + ldp x4, x5, [sp, 48]; \ + ldp x6, x7, [sp, 64]; \ + ldp x8, x9, [sp, 80]; \ + ldp x10, x11, [sp, 96]; \ + ldp x12, x13, [sp, 112]; \ + ldp x14, x15, [sp, 128]; \ + ldp x19, x20, [sp, 144]; \ + ldp x21, x22, [sp, 160]; \ + ldp x23, x24, [sp, 176]; \ + ldr x25, [sp, 192]; \ + ldp d0, d1, [sp, 208]; \ + ldp d2, d3, [sp, 224]; \ + ldp d4, d5, [sp, 240]; \ + ldp d6, d7, [sp, 256]; \ + ldp d16, d17, [sp, 272]; \ + ldp d18, d19, [sp, 288]; \ + ldp d20, d21, [sp, 304]; \ + ldp d22, d23, [sp, 320]; \ + ldp d24, d25, [sp, 336]; \ + ldp d26, d27, [sp, 352]; \ + ldp d28, d29, [sp, 368]; \ + ldp d30, d31, [sp, 384]; \ + /* Reload new allocation pointer and allocation limit */ \ + LOAD_TL_VAR(caml_young_ptr, ALLOC_PTR); \ + LOAD_TL_VAR(caml_young_limit, ALLOC_LIMIT); \ + /* Free stack space and return to caller */ \ ldp x29, x30, [sp], 400 + +FUNCTION(caml_call_gc) +CFI_STARTPROC + SWITCH_OCAML_TO_C(TMP) + SAVE_ALL_REGS_AND_CALL(caml_garbage_collection) + SWITCH_C_TO_OCAML(TMP) ret - CFI_ENDPROC +CFI_ENDPROC + .type caml_call_gc, %function .size caml_call_gc, .-caml_call_gc +FUNCTION(caml_call_realloc_stack) +CFI_STARTPROC + SWITCH_OCAML_TO_C(TMP) + SAVE_ALL_REGS_AND_CALL(caml_realloc_stack) + SWITCH_C_TO_OCAML(TMP) + ret +CFI_ENDPROC + .type caml_call_realloc_stack, %function + .size caml_call_realloc_stack, .-caml_call_realloc_stack + + +/* TODO KC: define MK_CAML_ALLOC(SZ) macro for generating caml_allocX functions. */ + FUNCTION(caml_alloc1) - CFI_STARTPROC - sub ALLOC_PTR, ALLOC_PTR, #16 +CFI_STARTPROC +1: sub ALLOC_PTR, ALLOC_PTR, 16 cmp ALLOC_PTR, ALLOC_LIMIT - b.lo .Lcaml_call_gc + b.lo 2f ret - CFI_ENDPROC +2: SWITCH_OCAML_TO_C(TMP) + SAVE_ALL_REGS_AND_CALL(caml_garbage_collection) + SWITCH_C_TO_OCAML(TMP) + /* Try again */ + b 1b +CFI_ENDPROC + .type caml_alloc1, %function .size caml_alloc1, .-caml_alloc1 FUNCTION(caml_alloc2) - CFI_STARTPROC - sub ALLOC_PTR, ALLOC_PTR, #24 +CFI_STARTPROC +1: sub ALLOC_PTR, ALLOC_PTR, 24 cmp ALLOC_PTR, ALLOC_LIMIT - b.lo .Lcaml_call_gc + b.lo 2f ret - CFI_ENDPROC +2: SWITCH_OCAML_TO_C(TMP) + SAVE_ALL_REGS_AND_CALL(caml_garbage_collection) + SWITCH_C_TO_OCAML(TMP) + /* Try again */ + b 1b +CFI_ENDPROC + .type caml_alloc2, %function .size caml_alloc2, .-caml_alloc2 FUNCTION(caml_alloc3) - CFI_STARTPROC - sub ALLOC_PTR, ALLOC_PTR, #32 +CFI_STARTPROC +1: sub ALLOC_PTR, ALLOC_PTR, 32 cmp ALLOC_PTR, ALLOC_LIMIT - b.lo .Lcaml_call_gc + b.lo 2f ret - CFI_ENDPROC +2: SWITCH_OCAML_TO_C(TMP) + SAVE_ALL_REGS_AND_CALL(caml_garbage_collection) + SWITCH_C_TO_OCAML(TMP) + /* Try again */ + b 1b +CFI_ENDPROC + .type caml_alloc3, %function .size caml_alloc3, .-caml_alloc3 FUNCTION(caml_allocN) - CFI_STARTPROC - sub ALLOC_PTR, ALLOC_PTR, ARG +CFI_STARTPROC +1: sub ALLOC_PTR, ALLOC_PTR, ARG cmp ALLOC_PTR, ALLOC_LIMIT - b.lo .Lcaml_call_gc + b.lo 2f ret - CFI_ENDPROC +2: SWITCH_OCAML_TO_C(TMP) + /* Call GC. This preserves ARG */ + SAVE_ALL_REGS_AND_CALL(caml_garbage_collection) + SWITCH_C_TO_OCAML(TMP) + /* Try again */ + b 1b +CFI_ENDPROC + .type caml_allocN, %function .size caml_allocN, .-caml_allocN +/******************************************************************************/ /* Call a C function from OCaml */ /* Function to call is in ARG */ +/******************************************************************************/ FUNCTION(caml_c_call) - CFI_STARTPROC - /* Preserve return address in callee-save register x19 */ - mov x19, x30 - CFI_REGISTER(30, 19) - /* Record lowest stack address and return address */ - str x30, Caml_state(last_return_address) - add TMP, sp, #0 - str TMP, Caml_state(bottom_of_stack) - /* Make the exception handler alloc ptr available to the C code */ - str ALLOC_PTR, Caml_state(young_ptr) - str TRAP_PTR, Caml_state(exception_pointer) +CFI_STARTPROC + /* Arguments: + C arguments : x0 to x7, d0 to d7 + C function : ARG */ + /* Switch from OCaml to C */ + SWITCH_OCAML_TO_C(TMP) + /* Make alloc ptr available to the C code */ + STORE_TL_VAR(ALLOC_PTR, caml_young_ptr) /* Call the function */ blr ARG /* Reload alloc ptr and alloc limit */ - ldr ALLOC_PTR, Caml_state(young_ptr) - ldr ALLOC_LIMIT, Caml_state(young_limit) + LOAD_TL_VAR(caml_young_ptr, ALLOC_PTR) + LOAD_TL_VAR(caml_young_limit, ALLOC_LIMIT) + /* Switch from C to OCaml */ + SWITCH_C_TO_OCAML(TMP) /* Return */ - ret x19 - CFI_ENDPROC + ret +CFI_ENDPROC + .type caml_c_call, %function .size caml_c_call, .-caml_c_call +FUNCTION(caml_c_call_stack_args) +CFI_STARTPROC + /* Arguments: + C arguments : x0 to x7, d0 to d7 + C function : ARG + C stack args : begin=x19 end=x20 */ + /* Switch from OCaml to C */ + SWITCH_OCAML_TO_C(TMP) + /* Make the exception handler alloc ptr available to the C code */ + STORE_TL_VAR(ALLOC_PTR, caml_young_ptr) + /* Copy arguments from OCaml to C stack */ + sub TMP, x20, x19 + mov TMP2, sp + sub sp, sp, TMP +1: sub x20, x20, 8 + cmp x20, x19 + b.lo 2f + ldr TMP, [x20] + str TMP, [TMP2, -8]!; CFI_ADJUST(8) + b 1b +2: /* Call the function */ + blr ARG + /* Reload alloc ptr and alloc limit */ + LOAD_TL_VAR(caml_young_ptr, ALLOC_PTR) + LOAD_TL_VAR(caml_young_limit, ALLOC_LIMIT) + /* Switch from C to OCaml */ + SWITCH_C_TO_OCAML(TMP) + /* Return */ + ret +CFI_ENDPROC + .type caml_c_call_stack_args, %function + .size caml_c_call_stack_args, .-caml_c_call_stack_args + +/******************************************************************************/ +/* Save and restore all callee-save registers on stack. + Keep the stack 16-aligned. */ +/******************************************************************************/ + +#define PUSH_CALLEE_SAVE_REGS \ + stp x29, x30, [sp, -160]!; \ + CFI_ADJUST(160); \ + add x29, sp, 0 ; \ + stp x19, x20, [sp, 16]; \ + stp x21, x22, [sp, 32]; \ + stp x23, x24, [sp, 48]; \ + stp x25, x26, [sp, 64]; \ + stp x27, x28, [sp, 80]; \ + stp d8, d9, [sp, 96]; \ + stp d10, d11, [sp, 112]; \ + stp d12, d13, [sp, 128]; \ + stp d14, d15, [sp, 144] + +#define POP_CALLEE_SAVE_REGS \ + ldp x19, x20, [sp, 16]; \ + ldp x21, x22, [sp, 32]; \ + ldp x23, x24, [sp, 48]; \ + ldp x25, x26, [sp, 64]; \ + ldp x27, x28, [sp, 80]; \ + ldp d8, d9, [sp, 96]; \ + ldp d10, d11, [sp, 112]; \ + ldp d12, d13, [sp, 128]; \ + ldp d14, d15, [sp, 144]; \ + ldp x29, x30, [sp], 160; \ + CFI_ADJUST(-160) + + +/******************************************************************************/ /* Start the OCaml program */ +/******************************************************************************/ FUNCTION(caml_start_program) - CFI_STARTPROC - mov ARG_DOMAIN_STATE_PTR, C_ARG_1 +CFI_STARTPROC + PUSH_CALLEE_SAVE_REGS + /* Load caml_young_ptr into ALLOC_PTR (was passed as an argument from C) */ + mov ALLOC_PTR, x0 + /* Initial entry point is caml_program */ ADDRGLOBAL(ARG, caml_program) - -/* Code shared with caml_callback* */ -/* Address of OCaml code to call is in ARG */ -/* Arguments to the OCaml code are in x0...x7 */ - + /* Common code for caml_start_program and caml_callback* */ + /* Arguments to the OCaml code are in x0...x3 */ .Ljump_to_caml: - /* Set up stack frame and save callee-save registers */ - CFI_OFFSET(29, -160) - CFI_OFFSET(30, -152) - stp x29, x30, [sp, -160]! - CFI_ADJUST(160) - add x29, sp, #0 - stp x19, x20, [sp, 16] - stp x21, x22, [sp, 32] - stp x23, x24, [sp, 48] - stp x25, x26, [sp, 64] - stp x27, x28, [sp, 80] - stp d8, d9, [sp, 96] - stp d10, d11, [sp, 112] - stp d12, d13, [sp, 128] - stp d14, d15, [sp, 144] - /* Load domain state pointer from argument */ - mov DOMAIN_STATE_PTR, ARG_DOMAIN_STATE_PTR - /* Setup a callback link on the stack */ - ldr x8, Caml_state(bottom_of_stack) - ldr x9, Caml_state(last_return_address) - ldr x10, Caml_state(gc_regs) - stp x8, x9, [sp, -32]! /* 16-byte alignment */ - CFI_ADJUST(32) - str x10, [sp, 16] - /* Setup a trap frame to catch exceptions escaping the OCaml code */ - ldr x8, Caml_state(exception_pointer) - adr x9, .Ltrap_handler - stp x8, x9, [sp, -16]! + /* Save system stack state. */ + PUSH_TL_PAIR(caml_system_exnptr_offset, caml_system_sp) + /* Save parent stack reference and reset it. This ensures that callbacks do + * not inherit the handler from the previous stack chunk. */ + LOAD_TL_VAR(caml_current_stack, TMP) + ldr TMP2, Stack_parent(TMP) + str TMP2, [sp, -16]! /* 16-byte alignment */ CFI_ADJUST(16) - add TRAP_PTR, sp, #0 - /* Reload allocation pointers */ - ldr ALLOC_PTR, Caml_state(young_ptr) - ldr ALLOC_LIMIT, Caml_state(young_limit) - /* Call the OCaml code */ + mov TMP2, 1 + str TMP2, Stack_parent(TMP) + /* Build a handler for exceptions raised in C */ + adr TMP, .Lc_trap_handler + stp xzr, TMP, [sp, -16]! /* xzr => dummy previous trap */ + CFI_ADJUST(16) + mov TMP2, sp + STORE_TL_VAR(TMP2, caml_system_sp) + LOAD_TL_VAR(caml_system_stack_high, TRAP_OFF) + sub TRAP_OFF, TRAP_OFF, TMP2 + STORE_TL_VAR(TRAP_OFF, caml_system_exnptr_offset) + /* Save callback args */ + stp x29, x30, [sp, -64]! + CFI_ADJUST(64) + add x29, sp, 0 + stp x0, x1, [sp, 16] + stp x2, x3, [sp, 32] + stp ARG, xzr, [sp, 48] + /* Create a register array since caml_maybe_expand_stack may GC */ + add x0, sp, 16 + /* Expand the stack if needed */ + ADDRGLOBAL(ARG, caml_maybe_expand_stack) blr ARG + /* Now caml_current_stack corresponds to the new stack. Still on C stack. + * Restore callback args. */ + ldp x0, x1, [sp, 16] + ldp x2, x3, [sp, 32] + ldr ARG, [sp, 48] + ldp x29, x30, [sp], 64 + CFI_ADJUST(-64) + /* Switch from C to OCaml stack */ + SWITCH_C_TO_OCAML_NO_CTXT(TMP) + /* Setup alloc ptr */ + LOAD_TL_VAR(caml_young_ptr, ALLOC_PTR) + LOAD_TL_VAR(caml_young_limit, ALLOC_LIMIT) + /* Build a handler for exceptions raised in OCaml */ + adr TMP, .Lcaml_trap_handler + stp TRAP_OFF, TMP, [sp, -16]! + CFI_ADJUST(16) + LOAD_TL_VAR(caml_stack_high, TRAP_OFF) + mov TMP, sp + sub TRAP_OFF, TRAP_OFF, TMP + /* Call the OCaml code */ + blr ARG .Lcaml_retaddr: - /* Pop the trap frame, restoring caml_exception_pointer */ - ldr x8, [sp], 16 + /* Pop the OCaml exception handler */ + ldr TMP, [sp], 16 CFI_ADJUST(-16) - str x8, Caml_state(exception_pointer) - /* Pop the callback link, restoring the global variables */ -.Lreturn_result: - ldr x10, [sp, 16] - ldp x8, x9, [sp], 32 - CFI_ADJUST(-32) - str x8, Caml_state(bottom_of_stack) - str x9, Caml_state(last_return_address) - str x10, Caml_state(gc_regs) - /* Update allocation pointer */ - str ALLOC_PTR, Caml_state(young_ptr) - /* Reload callee-save registers and return address */ - ldp x19, x20, [sp, 16] - ldp x21, x22, [sp, 32] - ldp x23, x24, [sp, 48] - ldp x25, x26, [sp, 64] - ldp x27, x28, [sp, 80] - ldp d8, d9, [sp, 96] - ldp d10, d11, [sp, 112] - ldp d12, d13, [sp, 128] - ldp d14, d15, [sp, 144] - ldp x29, x30, [sp], 160 - CFI_ADJUST(-160) - /* Return to C caller */ +.Lreturn_to_c: + /* Update alloc ptr */ + STORE_TL_VAR(ALLOC_PTR, caml_young_ptr) + /* Return to C stack */ + SWITCH_OCAML_TO_C_NO_CTXT(TMP) + /* Pop the C exception handler */ + add sp, sp, 16 + CFI_ADJUST(-16) + /* Restore previous parent stack */ + LOAD_TL_VAR(caml_current_stack, TMP2) + ldr TMP, [sp], 16 + str TMP, Stack_parent(TMP2) + /* Restore previous system stack state */ + POP_TL_PAIR(caml_system_exnptr_offset, caml_system_sp) + /* Restore the callee-saved registers */ + POP_CALLEE_SAVE_REGS + /* Return to caller */ ret - CFI_ENDPROC +.Lcaml_trap_handler: /* 109 */ + /* Exception in OCaml code */ + /* Mark the bucket as an exception result and return it */ + orr x0, x0, #2 + b .Lreturn_to_c +.Lc_trap_handler: /* 115 */ + /* Exception in C code */ + /* Reinstall handler for exceptions raised in C */ + adr TMP, .Lc_trap_handler + stp xzr, TMP, [sp, -16]! /* xzr => dummy previous trap */ + CFI_ADJUST(16) + /* Prepare for return to OCaml */ + LOAD_TL_VAR(caml_young_ptr, ALLOC_PTR) + LOAD_TL_VAR(caml_young_limit, ALLOC_LIMIT) + /* Load OCaml stack */ + SWITCH_C_TO_OCAML(TMP) + /* Raise the exception in OCaml */ + b .Lcaml_raise_exn +CFI_ENDPROC .type .Lcaml_retaddr, %function .size .Lcaml_retaddr, .-.Lcaml_retaddr + .type caml_start_program, %function .size caml_start_program, .-caml_start_program -/* The trap handler */ - - .align 2 -.Ltrap_handler: - CFI_STARTPROC - /* Save exception pointer */ - str TRAP_PTR, Caml_state(exception_pointer) - /* Encode exception bucket as an exception result */ - orr x0, x0, #2 - /* Return it */ - b .Lreturn_result - CFI_ENDPROC - .type .Ltrap_handler, %function - .size .Ltrap_handler, .-.Ltrap_handler +/******************************************************************************/ +/* Exceptions */ +/******************************************************************************/ /* Raise an exception from OCaml */ FUNCTION(caml_raise_exn) - CFI_STARTPROC +CFI_STARTPROC +.Lcaml_raise_exn: /* Test if backtrace is active */ - ldr TMP, Caml_state(backtrace_active) - cbnz TMP, 2f + LOAD_TL_VAR(caml_backtrace_active, TMP) + cbnz TMP, 2f 1: /* Cut stack at current trap handler */ - mov sp, TRAP_PTR - /* Pop previous handler and jump to it */ - ldr TMP, [sp, 8] - ldr TRAP_PTR, [sp], 16 + RESTORE_EXN_HANDLER_OCAML br TMP 2: /* Preserve exception bucket in callee-save register x19 */ mov x19, x0 + /* Preserve OCaml sp in callee-save register x20 */ + mov x20, sp /* Stash the backtrace */ + LOAD_TL_VAR(caml_system_sp, TMP) + mov sp, TMP /* arg1: exn bucket, already in x0 */ mov x1, x30 /* arg2: pc of raise */ - add x2, sp, #0 /* arg3: sp of raise */ - mov x3, TRAP_PTR /* arg4: sp of handler */ + mov x2, x20 /* arg3: sp of raise */ + mov x3, TRAP_OFF /* arg4: sp of handler */ bl caml_stash_backtrace /* Restore exception bucket and raise */ mov x0, x19 b 1b - CFI_ENDPROC +CFI_ENDPROC + .type caml_raise_exn, %function .size caml_raise_exn, .-caml_raise_exn /* Raise an exception from C */ FUNCTION(caml_raise_exception) - CFI_STARTPROC - /* Load the domain state ptr */ - mov DOMAIN_STATE_PTR, C_ARG_1 - /* Load the exception bucket */ - mov x0, C_ARG_2 - /* Reload trap ptr, alloc ptr and alloc limit */ - ldr TRAP_PTR, Caml_state(exception_pointer) - ldr ALLOC_PTR, Caml_state(young_ptr) - ldr ALLOC_LIMIT, Caml_state(young_limit) - /* Test if backtrace is active */ - ldr TMP, Caml_state(backtrace_active) - cbnz TMP, 2f -1: /* Cut stack at current trap handler */ - mov sp, TRAP_PTR - /* Pop previous handler and jump to it */ - ldr TMP, [sp, 8] - ldr TRAP_PTR, [sp], 16 +CFI_STARTPROC + mov ALLOC_PTR, x0 + mov x0, x1 + LOAD_TL_VAR(caml_system_exnptr_offset, TRAP_OFF) + /* Cut the stack at current trap handler */ + RESTORE_EXN_HANDLER_SYS br TMP -2: /* Preserve exception bucket in callee-save register x19 */ - mov x19, x0 - /* Stash the backtrace */ - /* arg1: exn bucket */ - ldr x1, Caml_state(last_return_address) /* arg2: pc of raise */ - ldr x2, Caml_state(bottom_of_stack) /* arg3: sp of raise */ - mov x3, TRAP_PTR /* arg4: sp of handler */ - bl caml_stash_backtrace - /* Restore exception bucket and raise */ - mov x0, x19 - b 1b - CFI_ENDPROC +CFI_ENDPROC + .type caml_raise_exception, %function .size caml_raise_exception, .-caml_raise_exception +/******************************************************************************/ /* Callback from C to OCaml */ +/******************************************************************************/ FUNCTION(caml_callback_asm) - CFI_STARTPROC - /* Initial shuffling of arguments */ - /* (x0 = Caml_state, x1 = closure, [x2] = first arg) */ - mov ARG_DOMAIN_STATE_PTR, x0 - ldr x0, [x2] /* x0 = first arg */ - /* x1 = closure environment */ +CFI_STARTPROC + PUSH_CALLEE_SAVE_REGS + /* Initial shuffling of arguments + (x0 = alloc ptr, x1 = closure, x2 = first arg) */ + mov ALLOC_PTR, x0 /* young ptr */ + mov x0, x2 /* x0 = first arg */ + /* x1 = closure environment already */ ldr ARG, [x1] /* code pointer */ b .Ljump_to_caml - CFI_ENDPROC +CFI_ENDPROC .type caml_callback_asm, %function .size caml_callback_asm, .-caml_callback_asm - TEXT_SECTION(caml_callback2_asm) - .align 2 - .globl caml_callback2_asm -caml_callback2_asm: - CFI_STARTPROC - /* Initial shuffling of arguments */ - /* (x0 = Caml_state, x1 = closure, [x2] = arg1, [x2,8] = arg2) */ - mov ARG_DOMAIN_STATE_PTR, x0 +FUNCTION(caml_callback2_asm) +CFI_STARTPROC + PUSH_CALLEE_SAVE_REGS + /* Initial shuffling of arguments + (x0 = alloc ptr, x1 = closure, x2 = arg1, x3 = arg2) */ + mov ALLOC_PTR, x0 /* young ptr */ mov TMP, x1 - ldp x0, x1, [x2, 0] /* x0 = first arg, x1 = second arg */ + mov x0, x2 /* x0 = first arg */ + mov x1, x3 /* x1 = second arg */ mov x2, TMP /* x2 = closure environment */ ADDRGLOBAL(ARG, caml_apply2) b .Ljump_to_caml - CFI_ENDPROC +CFI_ENDPROC .type caml_callback2_asm, %function .size caml_callback2_asm, .-caml_callback2_asm - TEXT_SECTION(caml_callback3_asm) - .align 2 - .globl caml_callback3_asm -caml_callback3_asm: - CFI_STARTPROC - /* Initial shuffling of arguments */ - /* (x0 = Caml_state, x1 = closure, [x2] = arg1, [x2,8] = arg2, - [x2,16] = arg3) */ - mov ARG_DOMAIN_STATE_PTR, x0 - mov x3, x1 /* x3 = closure environment */ - ldp x0, x1, [x2, 0] /* x0 = first arg, x1 = second arg */ - ldr x2, [x2, 16] /* x2 = third arg */ +FUNCTION(caml_callback3_asm) +CFI_STARTPROC + PUSH_CALLEE_SAVE_REGS + /* Initial shuffling of arguments + (x0 = alloc ptr, x1 = closure, x2 = arg1, x3 = arg2, x4 = arg3) */ + mov ALLOC_PTR, x0 /* young ptr */ + mov TMP, x1 + ldr x0, [x2] /* x0 = first arg */ + ldr x1, [x2,8] /* x1 = second arg */ + ldr x2, [x2,16] /* x2 = third arg */ + mov x3, TMP /* x3 = closure environment */ ADDRGLOBAL(ARG, caml_apply3) b .Ljump_to_caml - CFI_ENDPROC +CFI_ENDPROC + .type caml_callback3_asm, %function .size caml_callback3_asm, .-caml_callback3_asm +/******************************************************************************/ +/* Fibers */ +/******************************************************************************/ + +FUNCTION(caml_fiber_exn_handler) +CFI_STARTPROC + /* Save exception (x0) in callee-save regsiter x19 */ + mov x19, x0 + LOAD_TL_VAR(caml_current_stack, x1) + str xzr, Stack_sp(x1) /* zero SP */ + ldr x20, Stack_handle_exception(x1) /* exception handler */ + ldr x0, Stack_parent(x1) /* parent stack. Never NULL here. */ + /* Reset stack */ + mov TMP, 1 + str TMP, Stack_handle_value(x1) + str TMP, Stack_handle_exception(x1) + str TMP, Stack_handle_effect(x1) + /* Switch stacks */ + SWITCH_OCAML_STACKS + /* Invoke exception handler */ + mov x0, x19 /* x0 = first argument */ + mov x1, x20 /* x1 = closure environment */ + ldr ARG, [x1] + br ARG +CFI_ENDPROC + .type caml_fiber_exn_handler, %function + .size caml_fiber_exn_handler, .-caml_fiber_exn_handler + +FUNCTION(caml_fiber_val_handler) +CFI_STARTPROC +.Lfiber_val_handler: + /* Save return value (x0) in callee-save register x19 */ + mov x19, x0 + LOAD_TL_VAR(caml_current_stack, x1) + str xzr, Stack_sp(x1) /* zero SP */ + ldr x20, Stack_handle_value(x1) /* value handler */ + ldr x0, Stack_parent(x1) /* parent stack. Never NULL here. */ + /* Reset stack. First pop off fiber exn handler. */ + add sp, sp, 16 + CFI_ADJUST(-16) + mov TMP, 1 + str TMP, Stack_handle_value(x1) + str TMP, Stack_handle_exception(x1) + str TMP, Stack_handle_effect(x1) + /* Switch stacks */ + SWITCH_OCAML_STACKS + /* Invoke value handler */ + mov x0, x19 /* x0 = first argument */ + mov x1, x20 /* x1 = closure environment */ + ldr ARG, [x1] + br ARG +CFI_ENDPROC + .type caml_fiber_val_handler, %function + .size caml_fiber_val_handler, .-caml_fiber_val_handler + +FUNCTION(caml_perform) +CFI_STARTPROC + /* Save effect (x0) in callee-saved register x19 */ + mov x19, x0 + LOAD_TL_VAR(caml_current_stack, x20) + ldr x0, Stack_parent(x20) /* Parent stack. */ + cmp x0, 1 /* Parent is NULL? */ + b.eq 1f + ldr x21, Stack_handle_effect(x20) /* effect handler */ + mov TMP, 1 + str TMP, Stack_parent(x20) /* Set parent stack of performer to NULL */ + /* Switch stacks */ + SWITCH_OCAML_STACKS + /* Invoke effect handler */ + mov x0, x19 /* x0 = first argument */ + mov x1, x20 /* x1 = second argument */ + mov x2, x21 /* x2 = closure environment */ + ADDRGLOBAL(ARG, caml_apply2) + br ARG +1: /* No parent stack. Raise Unhandled. */ + ADDRGLOBAL(x0, caml_exn_Unhandled) + b .Lcaml_raise_exn +CFI_ENDPROC + .type caml_perform, %function + .size caml_perform, .-caml_perform + +FUNCTION(caml_reperform) +CFI_STARTPROC + /* x0 -> effect (first argument), x1 -> performer */ + mov x19, x0 + LOAD_TL_VAR(caml_current_stack, x2) + ldr x0, Stack_parent(x2) /* Parent stack. */ + cmp x0, 1 /* Parent is NULL? */ + b.eq 1f + str x1, Stack_parent(x2) /* Set performer as parent */ + mov x20, x2 /* Save current stack in callee-saved x20 */ + ldr x21, Stack_handle_effect(x2) /* Save effect handler in callee-saved x21 */ + /* Switch stacks */ + SWITCH_OCAML_STACKS + /* Invoke effect handler */ + mov x0, x19 /* x0 = first argument */ + mov x1, x20 /* x1 = second argument */ + mov x2, x21 /* x2 = closure environment */ + ADDRGLOBAL(ARG, caml_apply2) + br ARG +1: /* No parent stack. Raise Unhandled. */ + ADDRGLOBAL(x0, caml_exn_Unhandled) + b .Lcaml_raise_exn +CFI_ENDPROC + .type caml_reperform, %function + .size caml_reperform, .-caml_reperform + +FUNCTION(caml_resume) +CFI_STARTPROC + /* x0 -> tail of stack list, x1 -> fun, x2 -> arg */ + mov x19, x2 /* Save arg in callee-saved x19 */ + mov x20, x1 /* Save fun in callee-saved x20 */ + LOAD_TL_VAR(caml_current_stack, x3) + mov x2, x0 + /* x0 & x2 = tail */ +.Lcaml_resume_loop: + /* Rewind parent pointers to find the performer */ + mov x0, x2 + ldr x2, Stack_parent(x0) + /* x0 = tail. x2 = parent(tail) */ + str x3, Stack_parent(x0) + /* Stack_parent(tail) <- x3. x0 = tail. x2 = parent(tail) */ + mov x3, x0 + /* x3 & x0 = tail */ + cmp x2, 1 + b.ne .Lcaml_resume_loop + /* x0 now has the desired head of stack list */ + SWITCH_OCAML_STACKS + mov x0, x19 /* x0 = first argument */ + mov x1, x20 /* x1 = closure environment */ + ldr ARG, [x1] + br ARG +CFI_ENDPROC + .type caml_resume, %function + .size caml_resume, .-caml_resume + + FUNCTION(caml_ml_array_bound_error) - CFI_STARTPROC +CFI_STARTPROC /* Load address of [caml_array_bound_error] in ARG */ ADDRGLOBAL(ARG, caml_array_bound_error) /* Call that function */ b caml_c_call - CFI_ENDPROC +CFI_ENDPROC + .type caml_ml_array_bound_error, %function .size caml_ml_array_bound_error, .-caml_ml_array_bound_error .globl caml_system__code_end @@ -471,10 +835,14 @@ caml_system__code_end: .align 3 .globl caml_system__frametable caml_system__frametable: - .quad 1 /* one descriptor */ - .quad .Lcaml_retaddr /* return address into callback */ - .short -1 /* negative frame size => use callback link */ - .short 0 /* no roots */ + .quad 2 /* two descriptors */ + .quad .Lcaml_retaddr /* return address into callback */ + .short -1 /* negative frame size => use callback link */ + .short 0 /* no roots */ + .align 3 + .quad .Lfiber_val_handler /* return address into fiber_val_handler */ + .short -1 /* negative frame size => use callback link */ + .short 0 /* no roots */ .align 3 .type caml_system__frametable, %object .size caml_system__frametable, .-caml_system__frametable diff --git a/runtime/array.c b/runtime/array.c index 37af6b7f60..b33db34dcf 100644 --- a/runtime/array.c +++ b/runtime/array.c @@ -70,11 +70,7 @@ CAMLprim value caml_array_get_float(value array, value index) if (idx < 0 || idx >= Wosize_val(array) / Double_wosize) caml_array_bound_error(); d = Double_flat_field(array, idx); -#define Setup_for_gc -#define Restore_after_gc - Alloc_small(res, Double_wosize, Double_tag); -#undef Setup_for_gc -#undef Restore_after_gc + Alloc_small(res, Double_wosize, Double_tag, { caml_handle_gc_interrupt(); }); Store_double_val(res, d); return res; #else @@ -107,11 +103,7 @@ CAMLprim value caml_floatarray_get(value array, value index) if (idx < 0 || idx >= Wosize_val(array) / Double_wosize) caml_array_bound_error(); d = Double_flat_field(array, idx); -#define Setup_for_gc -#define Restore_after_gc - Alloc_small(res, Double_wosize, Double_tag); -#undef Setup_for_gc -#undef Restore_after_gc + Alloc_small(res, Double_wosize, Double_tag, { caml_handle_gc_interrupt(); }); Store_double_val(res, d); return res; } @@ -121,7 +113,7 @@ CAMLprim value caml_array_set_addr(value array, value index, value newval) { intnat idx = Long_val(index); if (idx < 0 || idx >= Wosize_val(array)) caml_array_bound_error(); - Modify(&Field(array, idx), newval); + caml_modify_field(array, idx, newval); return Val_unit; } @@ -175,11 +167,7 @@ CAMLprim value caml_array_unsafe_get_float(value array, value index) value res; d = Double_flat_field(array, idx); -#define Setup_for_gc -#define Restore_after_gc - Alloc_small(res, Double_wosize, Double_tag); -#undef Setup_for_gc -#undef Restore_after_gc + Alloc_small(res, Double_wosize, Double_tag, { caml_handle_gc_interrupt(); }); Store_double_val(res, d); return res; #else /* FLAT_FLOAT_ARRAY */ @@ -209,11 +197,7 @@ CAMLprim value caml_floatarray_unsafe_get(value array, value index) CAMLassert (Tag_val(array) == Double_array_tag); d = Double_flat_field(array, idx); -#define Setup_for_gc -#define Restore_after_gc - Alloc_small(res, Double_wosize, Double_tag); -#undef Setup_for_gc -#undef Restore_after_gc + Alloc_small(res, Double_wosize, Double_tag, { caml_handle_gc_interrupt(); }); Store_double_val(res, d); return res; } @@ -222,7 +206,7 @@ CAMLprim value caml_floatarray_unsafe_get(value array, value index) CAMLprim value caml_array_unsafe_set_addr(value array, value index,value newval) { intnat idx = Long_val(index); - Modify(&Field(array, idx), newval); + caml_modify_field(array, idx, newval); return Val_unit; } @@ -270,18 +254,14 @@ CAMLprim value caml_floatarray_create(value len) if (wosize == 0) return Atom(0); else -#define Setup_for_gc -#define Restore_after_gc - Alloc_small (result, wosize, Double_array_tag); -#undef Setup_for_gc -#undef Restore_after_gc + Alloc_small (result, wosize, Double_array_tag, { caml_handle_gc_interrupt(); }); }else if (wosize > Max_wosize) caml_invalid_argument("Float.Array.create"); else { result = caml_alloc_shr (wosize, Double_array_tag); + result = caml_check_urgent_gc (result); } - // Give the GC a chance to run, and run memprof callbacks - return caml_process_pending_actions_with_root (result); + return result; } /* [len] is a [value] representing number of words or floats */ @@ -297,8 +277,7 @@ CAMLprim value caml_make_vect(value len, value init) res = Atom(0); #ifdef FLAT_FLOAT_ARRAY } else if (Is_block(init) - && Is_in_value_area(init) - && Tag_val(init) == Double_tag) { + && Tag_val(init) == Double_tag) { mlsize_t wsize; double d; d = Double_val(init); @@ -311,9 +290,7 @@ CAMLprim value caml_make_vect(value len, value init) #endif } else { if (size <= Max_young_wosize) { - uintnat profinfo; - Get_my_profinfo_with_cached_backtrace(profinfo, size); - res = caml_alloc_small_with_my_or_given_profinfo(size, 0, profinfo); + res = caml_alloc_small(size, 0); for (i = 0; i < size; i++) Field(res, i) = init; } else if (size > Max_wosize) caml_invalid_argument("Array.make"); @@ -325,14 +302,12 @@ CAMLprim value caml_make_vect(value len, value init) caml_minor_collection (); } CAMLassert(!(Is_block(init) && Is_young(init))); - res = caml_alloc_shr(size, 0); + res = caml_alloc(size, 0); /* We now know that [init] is not in the minor heap, so there is no need to call [caml_initialize]. */ for (i = 0; i < size; i++) Field(res, i) = init; } } - // Give the GC a chance to run, and run memprof callbacks - caml_process_pending_actions (); CAMLreturn (res); } @@ -363,30 +338,23 @@ CAMLprim value caml_make_array(value init) #ifdef FLAT_FLOAT_ARRAY CAMLparam1 (init); mlsize_t wsize, size, i; - CAMLlocal2 (v, res); + CAMLlocal3 (v, res, x); size = Wosize_val(init); if (size == 0) { CAMLreturn (init); } else { - v = Field(init, 0); + caml_read_field(init, 0, &v); if (Is_long(v) - || ! Is_in_value_area(v) || Tag_val(v) != Double_tag) { CAMLreturn (init); } else { wsize = size * Double_wosize; - if (wsize <= Max_young_wosize) { - res = caml_alloc_small(wsize, Double_array_tag); - } else { - res = caml_alloc_shr(wsize, Double_array_tag); - } + res = caml_alloc(wsize, Double_array_tag); for (i = 0; i < size; i++) { - double d = Double_val(Field(init, i)); - Store_double_flat_field(res, i, d); + caml_read_field(init, i, &x); + Store_double_flat_field(res, i, Double_val(x)); } - // run memprof callbacks - caml_process_pending_actions(); CAMLreturn (res); } } @@ -400,9 +368,6 @@ CAMLprim value caml_make_array(value init) CAMLprim value caml_array_blit(value a1, value ofs1, value a2, value ofs2, value n) { - value * src, * dst; - intnat count; - #ifdef FLAT_FLOAT_ARRAY if (Tag_val(a2) == Double_array_tag) { /* Arrays of floats. The values being copied are floats, not @@ -412,42 +377,17 @@ CAMLprim value caml_array_blit(value a1, value ofs1, value a2, value ofs2, (double *)a1 + Long_val(ofs1), Long_val(n) * sizeof(double)); return Val_unit; - } + } else { #endif - CAMLassert (Tag_val(a2) != Double_array_tag); - if (Is_young(a2)) { - /* Arrays of values, destination is in young generation. - Here too we can do a direct copy since this cannot create - old-to-young pointers, nor mess up with the incremental major GC. - Again, memmove takes care of overlap. */ - memmove(&Field(a2, Long_val(ofs2)), - &Field(a1, Long_val(ofs1)), - Long_val(n) * sizeof(value)); + CAMLassert (Tag_val(a2) != Double_array_tag); + caml_blit_fields(a1, Long_val(ofs1), a2, Long_val(ofs2), Long_val(n)); + /* Many caml_modify_field in a row can create a lot of old-to-young refs. + Give the minor GC a chance to run if it needs to. */ + caml_check_urgent_gc(Val_unit); return Val_unit; +#ifdef FLAT_FLOAT_ARRAY } - /* Array of values, destination is in old generation. - We must use caml_modify. */ - count = Long_val(n); - if (a1 == a2 && Long_val(ofs1) < Long_val(ofs2)) { - /* Copy in descending order */ - for (dst = &Field(a2, Long_val(ofs2) + count - 1), - src = &Field(a1, Long_val(ofs1) + count - 1); - count > 0; - count--, src--, dst--) { - caml_modify(dst, *src); - } - } else { - /* Copy in ascending order */ - for (dst = &Field(a2, Long_val(ofs2)), src = &Field(a1, Long_val(ofs1)); - count > 0; - count--, src++, dst++) { - caml_modify(dst, *src); - } - } - /* Many caml_modify in a row can create a lot of old-to-young refs. - Give the minor GC a chance to run if it needs to. */ - caml_check_urgent_gc(Val_unit); - return Val_unit; +#endif } /* A generic function for extraction and concatenation of sub-arrays */ @@ -463,8 +403,7 @@ static value caml_array_gather(intnat num_arrays, int isfloat = 0; mlsize_t wsize; #endif - mlsize_t i, size, count, pos; - value * src; + mlsize_t i, size, pos; /* Determine total size and whether result array is an array of floats */ size = 0; @@ -494,39 +433,20 @@ static value caml_array_gather(intnat num_arrays, CAMLassert(pos == size); } #endif - else if (size <= Max_young_wosize) { + else if (size > Max_wosize) { + /* Array of values, too big. */ + caml_invalid_argument("Array.concat"); + } + else { /* Array of values, small enough to fit in young generation. We can use memcpy directly. */ res = caml_alloc_small(size, 0); for (i = 0, pos = 0; i < num_arrays; i++) { - memcpy(&Field(res, pos), - &Field(arrays[i], offsets[i]), - lengths[i] * sizeof(value)); + caml_blit_fields(arrays[i], offsets[i], res, pos, lengths[i]); pos += lengths[i]; } CAMLassert(pos == size); } - else if (size > Max_wosize) { - /* Array of values, too big. */ - caml_invalid_argument("Array.concat"); - } else { - /* Array of values, must be allocated in old generation and filled - using caml_initialize. */ - res = caml_alloc_shr(size, 0); - for (i = 0, pos = 0; i < num_arrays; i++) { - for (src = &Field(arrays[i], offsets[i]), count = lengths[i]; - count > 0; - count--, src++, pos++) { - caml_initialize(&Field(res, pos), *src); - } - } - CAMLassert(pos == size); - - /* Many caml_initialize in a row can create a lot of old-to-young - refs. Give the minor GC a chance to run if it needs to. - Run memprof callbacks for the major allocation. */ - res = caml_process_pending_actions_with_root (res); - } CAMLreturn (res); } @@ -600,7 +520,6 @@ CAMLprim value caml_array_fill(value array, { intnat ofs = Long_val(v_ofs); intnat len = Long_val(v_len); - value* fp; /* This duplicates the logic of caml_modify. Please refer to the implementation of that function for a description of GC @@ -614,24 +533,9 @@ CAMLprim value caml_array_fill(value array, return Val_unit; } #endif - fp = &Field(array, ofs); - if (Is_young(array)) { - for (; len > 0; len--, fp++) *fp = val; - } else { - int is_val_young_block = Is_block(val) && Is_young(val); - CAMLassert(Is_in_heap(fp)); - for (; len > 0; len--, fp++) { - value old = *fp; - if (old == val) continue; - *fp = val; - if (Is_block(old)) { - if (Is_young(old)) continue; - if (caml_gc_phase == Phase_mark) caml_darken(old, NULL); - } - if (is_val_young_block) - add_to_ref_table (Caml_state->ref_table, fp); - } - if (is_val_young_block) caml_check_urgent_gc (Val_unit); + /* TODO: potential optimization by code duplication as in PR8716 */ + for (; len > 0; len--, ofs++) { + caml_modify_field(array, ofs, val); } return Val_unit; } diff --git a/runtime/backtrace.c b/runtime/backtrace.c index 3e68a356d5..2b6db83a63 100644 --- a/runtime/backtrace.c +++ b/runtime/backtrace.c @@ -30,7 +30,7 @@ void caml_init_backtrace(void) { - caml_register_global_root(&Caml_state->backtrace_last_exn); + return; } /* Start or stop the backtrace machinery */ @@ -41,12 +41,12 @@ CAMLprim value caml_record_backtrace(value vflag) if (flag != Caml_state->backtrace_active) { Caml_state->backtrace_active = flag; Caml_state->backtrace_pos = 0; - Caml_state->backtrace_last_exn = Val_unit; - /* Note: We do lazy initialization of Caml_state->backtrace_buffer when - needed in order to simplify the interface with the thread - library (thread creation doesn't need to allocate - Caml_state->backtrace_buffer). So we don't have to allocate it here. - */ + if (flag) { + Caml_state->backtrace_last_exn = caml_create_root(Val_unit); + } else { + caml_delete_root(Caml_state->backtrace_last_exn); + Caml_state->backtrace_last_exn = NULL; + } } return Val_unit; } @@ -129,17 +129,35 @@ CAMLprim value caml_get_exception_raw_backtrace(value unit) CAMLparam0(); CAMLlocal1(res); + /* Beware: the allocations below may cause finalizers to be run, and another + backtrace---possibly of a different length---to be stashed (for example + if the finalizer raises then catches an exception). We choose to ignore + any such finalizer backtraces and return the original one. */ + if (!Caml_state->backtrace_active || Caml_state->backtrace_buffer == NULL || Caml_state->backtrace_pos == 0) { res = caml_alloc(0, 0); } else { - intnat i, len = Caml_state->backtrace_pos; + backtrace_slot saved_caml_backtrace_buffer[BACKTRACE_BUFFER_SIZE]; + int saved_caml_backtrace_pos; + intnat i; + + saved_caml_backtrace_pos = Caml_state->backtrace_pos; + + if (saved_caml_backtrace_pos > BACKTRACE_BUFFER_SIZE) { + saved_caml_backtrace_pos = BACKTRACE_BUFFER_SIZE; + } + + memcpy(saved_caml_backtrace_buffer, Caml_state->backtrace_buffer, + saved_caml_backtrace_pos * sizeof(backtrace_slot)); - res = caml_alloc(len, 0); - for (i = 0; i < len; i++) - Field(res, i) = Val_backtrace_slot(Caml_state->backtrace_buffer[i]); + res = caml_alloc(saved_caml_backtrace_pos, 0); + for (i = 0; i < saved_caml_backtrace_pos; i++) { + caml_initialize_field(res, i, + Val_backtrace_slot(saved_caml_backtrace_buffer[i])); + } } CAMLreturn(res); @@ -153,7 +171,10 @@ CAMLprim value caml_restore_raw_backtrace(value exn, value backtrace) intnat i; mlsize_t bt_size; - Caml_state->backtrace_last_exn = exn; + caml_domain_state* domain_state = Caml_state; + + if (domain_state->backtrace_last_exn != NULL) + caml_modify_root (domain_state->backtrace_last_exn, exn); bt_size = Wosize_val(backtrace); if(bt_size > BACKTRACE_BUFFER_SIZE){ @@ -163,19 +184,18 @@ CAMLprim value caml_restore_raw_backtrace(value exn, value backtrace) /* We don't allocate if the backtrace is empty (no -g or backtrace not activated) */ if(bt_size == 0){ - Caml_state->backtrace_pos = 0; + domain_state->backtrace_pos = 0; return Val_unit; } /* Allocate if needed and copy the backtrace buffer */ - if (Caml_state->backtrace_buffer == NULL && - caml_alloc_backtrace_buffer() == -1) { + if (domain_state->backtrace_buffer == NULL && caml_alloc_backtrace_buffer() == -1){ return Val_unit; } - Caml_state->backtrace_pos = bt_size; - for(i=0; i < Caml_state->backtrace_pos; i++){ - Caml_state->backtrace_buffer[i] = Backtrace_slot_val(Field(backtrace, i)); + domain_state->backtrace_pos = bt_size; + for(i=0; i < domain_state->backtrace_pos; i++){ + domain_state->backtrace_buffer[i] = Backtrace_slot_val(Field(backtrace, i)); } return Val_unit; @@ -241,6 +261,8 @@ CAMLprim value caml_convert_raw_backtrace(value bt) array = caml_alloc(index, 0); + for (i = 0; i < index; i++) Op_val(array)[i] = Val_unit; + for (i = 0, index = 0; i < Wosize_val(bt); ++i) { debuginfo dbg; @@ -321,23 +343,9 @@ CAMLprim value caml_get_exception_backtrace(value unit) Store_field(arr, i, caml_convert_debuginfo(dbg)); } - res = caml_alloc_small(1, 0); Field(res, 0) = arr; /* Some */ + res = caml_alloc_small(1, 0); + Field(res, 0) = arr; /* Some */ } CAMLreturn(res); } - -CAMLprim value caml_get_current_callstack(value max_frames_value) -{ - CAMLparam1(max_frames_value); - CAMLlocal1(res); - value* callstack = NULL; - intnat callstack_alloc_len = 0; - intnat callstack_len = - caml_collect_current_callstack(&callstack, &callstack_alloc_len, - Long_val(max_frames_value), -1); - res = caml_alloc(callstack_len, 0); - memcpy(Op_val(res), callstack, sizeof(value) * callstack_len); - caml_stat_free(callstack); - CAMLreturn(res); -} diff --git a/runtime/backtrace_byt.c b/runtime/backtrace_byt.c index 2641daedde..27457f5e60 100644 --- a/runtime/backtrace_byt.c +++ b/runtime/backtrace_byt.c @@ -37,7 +37,7 @@ #include "caml/fix_code.h" #include "caml/memory.h" #include "caml/startup.h" -#include "caml/stacks.h" +#include "caml/fiber.h" #include "caml/sys.h" #include "caml/backtrace.h" #include "caml/fail.h" @@ -271,9 +271,11 @@ int caml_alloc_backtrace_buffer(void){ void caml_stash_backtrace(value exn, value * sp, int reraise) { - if (exn != Caml_state->backtrace_last_exn || !reraise) { + value *trap_sp; + + if (exn != caml_read_root(Caml_state->backtrace_last_exn) || !reraise) { Caml_state->backtrace_pos = 0; - Caml_state->backtrace_last_exn = exn; + caml_modify_root(Caml_state->backtrace_last_exn, exn); } if (Caml_state->backtrace_buffer == NULL && @@ -282,72 +284,141 @@ void caml_stash_backtrace(value exn, value * sp, int reraise) /* Traverse the stack and put all values pointing into bytecode into the backtrace buffer. */ - for (/*nothing*/; sp < Caml_state->trapsp; sp++) { - code_t p; - if (Is_long(*sp)) continue; - p = (code_t) *sp; - if (Caml_state->backtrace_pos >= BACKTRACE_BUFFER_SIZE) break; - if (find_debug_info(p) != NULL) - Caml_state->backtrace_buffer[Caml_state->backtrace_pos++] = p; + trap_sp = Stack_high(Caml_state->current_stack) + Caml_state->trap_sp_off; + for (/*nothing*/; sp < trap_sp; sp++) { + if (Is_long(*sp)) { + code_t p = Pc_val(*sp); + if (Caml_state->backtrace_pos >= BACKTRACE_BUFFER_SIZE) break; + if (find_debug_info(p) != NULL) + Caml_state->backtrace_buffer[Caml_state->backtrace_pos++] = p; + } } } /* returns the next frame pointer (or NULL if none is available); - updates *sp to point to the following one, and *trsp to the next + updates *sp to point to the following one, and *trap_spoff to the next trap frame, which we will skip when we reach it */ -code_t caml_next_frame_pointer(value ** sp, value ** trsp) +code_t caml_next_frame_pointer(value* stack_high, value ** sp, + intnat * trap_spoff) { - while (*sp < Caml_state->stack_high) { - value *spv = (*sp)++; - code_t *p; - if (Is_long(*spv)) continue; - p = (code_t*) spv; - if(&Trap_pc(*trsp) == p) { - *trsp = *trsp + Long_val(Trap_link_offset(*trsp)); + while (*sp < stack_high) { + value* p = (*sp)++; + if(&Trap_pc(stack_high + *trap_spoff) == p) { + *trap_spoff = Trap_link(stack_high + *trap_spoff); continue; } - if (find_debug_info(*p) != NULL) - return *p; + if (Is_long(*p) && find_debug_info(Pc_val(*p)) != NULL) + return Pc_val(*p); } return NULL; } -#define Default_callstack_size 32 -intnat caml_collect_current_callstack(value** ptrace, intnat* plen, - intnat max_frames, int alloc_idx) +/* Stores upto [max_frames_value] frames of the current call stack to + return to the user. This is used not in an exception-raising context, but + only when the user requests to save the trace (hopefully less often). + Instead of using a bounded buffer as [Caml_state->stash_backtrace], we first + traverse the stack to compute the right size, then allocate space for the + trace. */ + +static void get_callstack(value* sp, intnat trap_spoff, + struct stack_info* stack, + intnat max_frames, + code_t** trace, intnat* trace_size) { - value * sp = Caml_state->extern_sp; - value * trsp = Caml_state->trapsp; - intnat trace_pos = 0; - CAMLassert(alloc_idx == 0 || alloc_idx == -1); - - if (max_frames <= 0) return 0; - if (*plen == 0) { - value* trace = - caml_stat_alloc_noexc(Default_callstack_size * sizeof(value)); - if (trace == NULL) return 0; - *ptrace = trace; - *plen = Default_callstack_size; + struct stack_info* parent = Stack_parent(stack); + value *stack_high = Stack_high(stack); + value* saved_sp = sp; + intnat saved_trap_spoff = trap_spoff; + + CAMLnoalloc; + + /* first compute the size of the trace */ + { + *trace_size = 0; + while (*trace_size < max_frames) { + code_t p = caml_next_frame_pointer(stack_high, &sp, &trap_spoff); + if (p == NULL) { + if (parent == NULL) break; + sp = parent->sp; + trap_spoff = Long_val(sp[0]); + stack_high = Stack_high(parent); + parent = Stack_parent(parent); + } else { + ++*trace_size; + } + } } - while (trace_pos < max_frames) { - code_t p = caml_next_frame_pointer(&sp, &trsp); - if (p == NULL) break; - if (trace_pos == *plen) { - intnat new_len = *plen * 2; - value * trace = caml_stat_resize_noexc(*ptrace, new_len * sizeof(value)); - if (trace == NULL) break; - *ptrace = trace; - *plen = new_len; + *trace = caml_stat_alloc(sizeof(code_t*) * *trace_size); + + sp = saved_sp; + parent = Stack_parent(stack); + stack_high = Stack_high(stack); + trap_spoff = saved_trap_spoff; + + /* then collect the trace */ + { + uintnat trace_pos = 0; + + while (trace_pos < *trace_size) { + code_t p = caml_next_frame_pointer(stack_high, &sp, &trap_spoff); + if (p == NULL) { + sp = parent->sp; + trap_spoff = Long_val(sp[0]); + stack_high = Stack_high(parent); + parent = Stack_parent(parent); + } else { + (*trace)[trace_pos] = p; + ++trace_pos; + } } - (*ptrace)[trace_pos++] = Val_backtrace_slot(p); + } +} + +static value alloc_callstack(code_t* trace, intnat trace_len) +{ + CAMLparam0(); + CAMLlocal1(callstack); + int i; + callstack = caml_alloc(trace_len, 0); + for (i = 0; i < trace_len; i++) + Store_field(callstack, i, Val_backtrace_slot(trace[i])); + caml_stat_free(trace); + CAMLreturn(callstack); +} + +CAMLprim value caml_get_current_callstack (value max_frames_value) +{ + code_t* trace; + intnat trace_len; + get_callstack(Caml_state->current_stack->sp, Caml_state->trap_sp_off, + Caml_state->current_stack, Long_val(max_frames_value), + &trace, &trace_len); + return alloc_callstack(trace, trace_len); +} + +CAMLprim value caml_get_continuation_callstack (value cont, value max_frames) +{ + code_t* trace; + intnat trace_len; + struct stack_info *stack; + value *sp; + + stack = Ptr_val(caml_continuation_use(cont)); + { + CAMLnoalloc; /* GC must not see the stack outside the cont */ + sp = stack->sp; + get_callstack(sp, Long_val(sp[0]), stack, Long_val(max_frames), + &trace, &trace_len); + caml_continuation_replace(cont, stack); } - return trace_pos; + return alloc_callstack(trace, trace_len); } + /* Read the debugging info contained in the current bytecode executable. */ static void read_main_debug_info(struct debug_info *di) @@ -367,13 +438,13 @@ static void read_main_debug_info(struct debug_info *di) See https://github.com/ocaml/ocaml/issues/9344 for details. */ - if (caml_cds_file == NULL && caml_byte_program_mode == COMPLETE_EXE) + if (caml_params->cds_file == NULL && caml_byte_program_mode == COMPLETE_EXE) CAMLreturn0; - if (caml_cds_file != NULL) { - exec_name = caml_cds_file; + if (caml_params->cds_file != NULL) { + exec_name = (char_os*) caml_params->cds_file; } else { - exec_name = caml_exe_name; + exec_name = (char_os*) caml_params->exe_name; } fd = caml_attempt_open(&exec_name, &trail, 1); @@ -389,6 +460,8 @@ static void read_main_debug_info(struct debug_info *di) num_events = caml_getword(chan); events = caml_alloc(num_events, 0); + for (i = 0; i < num_events; i++) Op_val(events)[i] = Val_unit; + for (i = 0; i < num_events; i++) { orig = caml_getword(chan); evl = caml_input_val(chan); @@ -396,7 +469,7 @@ static void read_main_debug_info(struct debug_info *di) /* Relocate events in event list */ for (l = evl; l != Val_int(0); l = Field(l, 1)) { value ev = Field(l, 0); - Field(ev, EV_POS) = Val_long(Long_val(Field(ev, EV_POS)) + orig); + Store_field (ev, EV_POS, Val_long(Long_val(Field(ev, EV_POS)) + orig)); } /* Record event list */ Store_field(events, i, evl); diff --git a/runtime/backtrace_nat.c b/runtime/backtrace_nat.c index 893ba15d50..79dd6b7c79 100644 --- a/runtime/backtrace_nat.c +++ b/runtime/backtrace_nat.c @@ -24,43 +24,38 @@ #include "caml/alloc.h" #include "caml/backtrace.h" #include "caml/backtrace_prim.h" +#include "frame_descriptors.h" +#include "caml/stack.h" #include "caml/memory.h" #include "caml/misc.h" #include "caml/mlvalues.h" -#include "caml/stack.h" +#include "caml/fiber.h" +#include "caml/fail.h" /* Returns the next frame descriptor (or NULL if none is available), and updates *pc and *sp to point to the following one. */ -frame_descr * caml_next_frame_descriptor(uintnat * pc, char ** sp) +static frame_descr * caml_next_frame_descriptor(caml_frame_descrs fds, uintnat * pc, char ** sp, struct stack_info* stack) { frame_descr * d; - uintnat h; while (1) { - h = Hash_retaddr(*pc); - while (1) { - d = caml_frame_descriptors[h]; - if (d == NULL) return NULL; /* happens if some code compiled without -g */ - if (d->retaddr == *pc) break; - h = (h+1) & caml_frame_descriptors_mask; - } + d = caml_find_frame_descr(fds, *pc); /* Skip to next frame */ if (d->frame_size != 0xFFFF) { /* Regular frame, update sp/pc and return the frame descriptor */ *sp += (d->frame_size & 0xFFFC); *pc = Saved_return_address(*sp); -#ifdef Mask_already_scanned - *pc = Mask_already_scanned(*pc); -#endif return d; } else { - /* Special frame marking the top of a stack chunk for an ML callback. - Skip C portion of stack and continue with next ML stack chunk. */ - struct caml_context * next_context = Callback_link(*sp); - *sp = next_context->bottom_of_stack; - *pc = next_context->last_retaddr; - /* A null sp means no more ML stack chunks; stop here. */ - if (*sp == NULL) return NULL; + /* This marks the top of an ML stack chunk. Move sp to the previous stack + * chunk. This includes skipping over the DWARF link & trap frame (4 words). */ + *sp += 4 * sizeof(value); + if (*sp == (char*)Stack_high(stack)) { + /* We've reached the top of stack. No more frames. */ + *pc = 0; + return NULL; + } + *sp += sizeof(value); /* return address */ } } } @@ -79,24 +74,28 @@ int caml_alloc_backtrace_buffer(void){ preserved the global, statically bounded buffer of the old implementation -- before the more flexible [caml_get_current_callstack] was implemented. */ -void caml_stash_backtrace(value exn, uintnat pc, char * sp, char * trapsp) +void caml_stash_backtrace(value exn, uintnat pc, char * sp, char* trapsp) { - if (exn != Caml_state->backtrace_last_exn) { - Caml_state->backtrace_pos = 0; - Caml_state->backtrace_last_exn = exn; + caml_domain_state* domain_state = Caml_state; + caml_frame_descrs fds; + + if (exn != caml_read_root(domain_state->backtrace_last_exn)) { + domain_state->backtrace_pos = 0; + caml_modify_root(domain_state->backtrace_last_exn, exn); } if (Caml_state->backtrace_buffer == NULL && caml_alloc_backtrace_buffer() == -1) return; + fds = caml_get_frame_descrs(); /* iterate on each frame */ while (1) { - frame_descr * descr = caml_next_frame_descriptor(&pc, &sp); + frame_descr * descr = caml_next_frame_descriptor(fds, &pc, &sp, domain_state->current_stack); if (descr == NULL) return; /* store its descriptor in the backtrace buffer */ - if (Caml_state->backtrace_pos >= BACKTRACE_BUFFER_SIZE) return; - Caml_state->backtrace_buffer[Caml_state->backtrace_pos++] = + if (domain_state->backtrace_pos >= BACKTRACE_BUFFER_SIZE) return; + domain_state->backtrace_buffer[domain_state->backtrace_pos++] = (backtrace_slot) descr; /* Stop when we reach the current exception handler */ @@ -104,66 +103,108 @@ void caml_stash_backtrace(value exn, uintnat pc, char * sp, char * trapsp) } } -/* A backtrace_slot is either a debuginfo or a frame_descr* */ -#define Slot_is_debuginfo(s) ((uintnat)(s) & 2) -#define Debuginfo_slot(s) ((debuginfo)((uintnat)(s) - 2)) -#define Slot_debuginfo(d) ((backtrace_slot)((uintnat)(d) + 2)) -#define Frame_descr_slot(s) ((frame_descr*)(s)) -#define Slot_frame_descr(f) ((backtrace_slot)(f)) -static debuginfo debuginfo_extract(frame_descr* d, int alloc_idx); - -#define Default_callstack_size 32 -intnat caml_collect_current_callstack(value** ptrace, intnat* plen, - intnat max_frames, int alloc_idx) +/* Stores upto [max_frames_value] frames of the current call stack to + return to the user. This is used not in an exception-raising + context, but only when the user requests to save the trace + (hopefully less often). Instead of using a bounded buffer as + [caml_stash_backtrace], we first traverse the stack to compute the + right size, then allocate space for the trace. */ +static void get_callstack(struct stack_info* orig_stack, intnat max_frames, + frame_descr*** trace, intnat* trace_size) { - uintnat pc = Caml_state->last_return_address; - char * sp = Caml_state->bottom_of_stack; - intnat trace_pos = 0; - - if (max_frames <= 0) return 0; - if (*plen == 0) { - value* trace = - caml_stat_alloc_noexc(Default_callstack_size * sizeof(value)); - if (trace == NULL) return 0; - *ptrace = trace; - *plen = Default_callstack_size; - } + intnat trace_pos; + char *sp; + uintnat pc; + caml_frame_descrs fds; + CAMLnoalloc; - if (alloc_idx >= 0) { - /* First frame has a Comballoc selector */ - frame_descr * descr = caml_next_frame_descriptor(&pc, &sp); - debuginfo info; - if (descr == NULL) return 0; - info = debuginfo_extract(descr, alloc_idx); - if (info != NULL) { - CAMLassert(((uintnat)info & 3) == 0); - (*ptrace)[trace_pos++] = Val_backtrace_slot(Slot_debuginfo(info)); - } else { - (*ptrace)[trace_pos++] = Val_backtrace_slot(Slot_frame_descr(descr)); + fds = caml_get_frame_descrs(); + + /* first compute the size of the trace */ + { + struct stack_info* stack = orig_stack; + caml_get_stack_sp_pc(stack, &sp, &pc); + trace_pos = 0; + + while(1) { + frame_descr *descr = caml_next_frame_descriptor(fds, &pc, &sp, stack); + if (trace_pos >= max_frames) break; + if (descr == NULL) { + stack = Stack_parent(stack); + if (stack == NULL) break; + caml_get_stack_sp_pc(stack, &sp, &pc); + } else { + ++trace_pos; + } } } - while (trace_pos < max_frames) { - frame_descr * descr = caml_next_frame_descriptor(&pc, &sp); - if (descr == NULL) break; - CAMLassert(((uintnat)descr & 3) == 0); - if (trace_pos == *plen) { - intnat new_len = *plen * 2; - value * trace = caml_stat_resize_noexc(*ptrace, new_len * sizeof(value)); - if (trace == NULL) break; - *ptrace = trace; - *plen = new_len; + *trace_size = trace_pos; + *trace = caml_stat_alloc(sizeof(frame_descr*) * trace_pos); + + /* then collect the trace */ + { + struct stack_info* stack = orig_stack; + caml_get_stack_sp_pc(stack, &sp, &pc); + trace_pos = 0; + + while(1) { + frame_descr *descr = caml_next_frame_descriptor(fds, &pc, &sp, stack); + if (trace_pos >= max_frames) break; + if (descr == NULL) { + stack = Stack_parent(stack); + if (stack == NULL) break; + caml_get_stack_sp_pc(stack, &sp, &pc); + } else { + (*trace)[trace_pos] = descr; + ++trace_pos; + } } - (*ptrace)[trace_pos++] = Val_backtrace_slot(Slot_frame_descr(descr)); } +} + +static value alloc_callstack(frame_descr** trace, intnat trace_len) +{ + CAMLparam0(); + CAMLlocal1(callstack); + int i; + callstack = caml_alloc(trace_len, 0); + for (i = 0; i < trace_len; i++) + Store_field(callstack, i, Val_backtrace_slot(trace[i])); + caml_stat_free(trace); + CAMLreturn(callstack); +} - return trace_pos; +CAMLprim value caml_get_current_callstack (value max_frames_value) { + frame_descr** trace; + intnat trace_len; + get_callstack(Caml_state->current_stack, Long_val(max_frames_value), + &trace, &trace_len); + return alloc_callstack(trace, trace_len); } -static debuginfo debuginfo_extract(frame_descr* d, int alloc_idx) +CAMLprim value caml_get_continuation_callstack (value cont, value max_frames) +{ + frame_descr** trace; + intnat trace_len; + struct stack_info* stack; + + stack = Ptr_val(caml_continuation_use(cont)); + { + CAMLnoalloc; + get_callstack(stack, max_frames, + &trace, &trace_len); + caml_continuation_replace(cont, stack); + } + + return alloc_callstack(trace, trace_len); +} + +debuginfo caml_debuginfo_extract(backtrace_slot slot) { unsigned char* infoptr; uint32_t debuginfo_offset; + frame_descr * d = (frame_descr *)slot; /* The special frames marking the top of an ML stack chunk are never returned by caml_next_frame_descriptor, so should never reach here. */ @@ -175,46 +216,24 @@ static debuginfo debuginfo_extract(frame_descr* d, int alloc_idx) /* Recover debugging info */ infoptr = (unsigned char*)&d->live_ofs[d->num_live]; if (d->frame_size & 2) { - CAMLassert(alloc_idx == -1 || (0 <= alloc_idx && alloc_idx < *infoptr)); /* skip alloc_lengths */ infoptr += *infoptr + 1; /* align to 32 bits */ infoptr = Align_to(infoptr, uint32_t); - /* select the right debug info for this allocation */ - if (alloc_idx != -1) { - infoptr += alloc_idx * sizeof(uint32_t); - if (*(uint32_t*)infoptr == 0) { - /* No debug info for this particular allocation */ - return NULL; - } - } else { - /* We don't care which alloc_idx we use, so use the first - that has debug info. (e.g. this is a backtrace through a - finaliser/signal handler triggered via a Comballoc alloc) */ - while (*(uint32_t*)infoptr == 0) { - infoptr += sizeof(uint32_t); - } + /* we know there's at least one valid debuginfo, + but it may not be the one for the first alloc */ + while (*(uint32_t*)infoptr == 0) { + infoptr += sizeof(uint32_t); } } else { /* align to 32 bits */ infoptr = Align_to(infoptr, uint32_t); - CAMLassert(alloc_idx == -1); } + /* read offset to debuginfo */ debuginfo_offset = *(uint32_t*)infoptr; - CAMLassert(debuginfo_offset != 0 && (debuginfo_offset & 3) == 0); return (debuginfo)(infoptr + debuginfo_offset); } -debuginfo caml_debuginfo_extract(backtrace_slot slot) -{ - if (Slot_is_debuginfo(slot)) { - /* already a decoded debuginfo */ - return Debuginfo_slot(slot); - } else { - return debuginfo_extract(Frame_descr_slot(slot), -1); - } -} - debuginfo caml_debuginfo_next(debuginfo dbg) { uint32_t * infoptr; diff --git a/runtime/callback.c b/runtime/callback.c index 347e3a9d1f..fbb69ae60f 100644 --- a/runtime/callback.c +++ b/runtime/callback.c @@ -19,22 +19,48 @@ #include <string.h> #include "caml/callback.h" -#include "caml/domain.h" +#include "caml/codefrag.h" #include "caml/fail.h" +#include "caml/fiber.h" #include "caml/memory.h" #include "caml/mlvalues.h" +#include "caml/platform.h" + +static __thread int callback_depth = 0; + +/* + * These macros are for ensuring effects are handled correctly + * inside callbacks. There are two aspects: + * - we clear the stack parent for a callback to force an Unhandled + * exception rather than effects being passed over the callback + * - we register the stack parent as a local root while the callback + * is executing to ensure that the garbage collector follows the + * stack parent + */ +static inline value save_and_clear_stack_parent(caml_domain_state* domain_state) { + struct stack_info* parent_stack = Stack_parent(domain_state->current_stack); + value cont = caml_alloc_1(Cont_tag, Val_ptr(parent_stack)); + Stack_parent(domain_state->current_stack) = NULL; + return cont; +} + +static inline void restore_stack_parent(caml_domain_state* domain_state, value cont) { + struct stack_info* parent_stack = Ptr_val(Op_val(cont)[0]); + Assert(Stack_parent(domain_state->current_stack) == NULL); + Stack_parent(domain_state->current_stack) = parent_stack; +} + +#define RESTORE_STACK_PARENT(domain_state) \ + #ifndef NATIVE_CODE /* Bytecode callbacks */ -#include "caml/codefrag.h" #include "caml/interp.h" #include "caml/instruct.h" #include "caml/fix_code.h" -#include "caml/stacks.h" - -CAMLexport int caml_callback_depth = 0; +#include "caml/fiber.h" static opcode_t callback_code[] = { ACC, 0, APPLY, 0, POP, 1, STOP }; @@ -53,23 +79,41 @@ static void init_callback_code(void) CAMLexport value caml_callbackN_exn(value closure, int narg, value args[]) { - int i; + CAMLparam1(closure); + CAMLxparamN(args, narg); + CAMLlocal1(cont); value res; + opcode_t code[7]; + int i; + caml_domain_state* domain_state = Caml_state; CAMLassert(narg + 4 <= 256); + domain_state->current_stack->sp -= narg + 4; + for (i = 0; i < narg; i++) domain_state->current_stack->sp[i] = args[i]; /* arguments */ - Caml_state->extern_sp -= narg + 4; - for (i = 0; i < narg; i++) Caml_state->extern_sp[i] = args[i]; /* arguments */ - Caml_state->extern_sp[narg] = (value)(callback_code + 4); /* return address */ - Caml_state->extern_sp[narg + 1] = Val_unit; /* environment */ - Caml_state->extern_sp[narg + 2] = Val_long(0); /* extra args */ - Caml_state->extern_sp[narg + 3] = closure; if (!callback_code_inited) init_callback_code(); - callback_code[1] = narg + 3; - callback_code[3] = narg; - res = caml_interprete(callback_code, sizeof(callback_code)); - if (Is_exception_result(res)) Caml_state->extern_sp += narg + 4; /* PR#3419 */ - return res; + + code[0] = callback_code[0]; + code[1] = narg + 3; + code[2] = callback_code[2]; + code[3] = narg; + code[4] = callback_code[4]; + code[5] = callback_code[5]; + code[6] = callback_code[6]; + + domain_state->current_stack->sp[narg] = Val_pc (code + 4); /* return address */ + domain_state->current_stack->sp[narg + 1] = Val_unit; /* environment */ + domain_state->current_stack->sp[narg + 2] = Val_long(0); /* extra args */ + domain_state->current_stack->sp[narg + 3] = closure; + + cont = save_and_clear_stack_parent(domain_state); + + res = caml_interprete(code, sizeof(code)); + if (Is_exception_result(res)) domain_state->current_stack->sp += narg + 4; /* PR#3419 */ + + restore_stack_parent(domain_state, cont); + + CAMLreturn (res); } CAMLexport value caml_callback_exn(value closure, value arg1) @@ -97,33 +141,77 @@ CAMLexport value caml_callback3_exn(value closure, return caml_callbackN_exn(closure, 3, arg); } -#else +#else /* Nativecode callbacks */ -/* Native-code callbacks. */ +static void init_callback_code(void) +{ +} -typedef value (callback_stub)(caml_domain_state* state, value closure, - value* args); +typedef value (callback_stub)(caml_domain_state* state, value closure, value* args); callback_stub caml_callback_asm, caml_callback2_asm, caml_callback3_asm; CAMLexport value caml_callback_exn(value closure, value arg) { - return caml_callback_asm(Caml_state, closure, &arg); + caml_domain_state* domain_state = Caml_state; + caml_maybe_expand_stack(); + + if (Stack_parent(domain_state->current_stack)) { + CAMLparam2 (closure, arg); + CAMLlocal1 (cont); + value res; + + cont = save_and_clear_stack_parent(domain_state); + res = caml_callback_asm(domain_state, closure, &arg); + restore_stack_parent(domain_state, cont); + + CAMLreturn (res); + } + return caml_callback_asm(domain_state, closure, &arg); } CAMLexport value caml_callback2_exn(value closure, value arg1, value arg2) { value args[] = {arg1, arg2}; - return caml_callback2_asm(Caml_state, closure, args); + caml_domain_state* domain_state = Caml_state; + caml_maybe_expand_stack(); + + if (Stack_parent(domain_state->current_stack)) { + CAMLparam3 (closure, arg1, arg2); + CAMLlocal1 (cont); + value res; + + cont = save_and_clear_stack_parent(domain_state); + res = caml_callback2_asm(domain_state, closure, args); + restore_stack_parent(domain_state, cont); + + CAMLreturn (res); + } + return caml_callback2_asm(domain_state, closure, args); } CAMLexport value caml_callback3_exn(value closure, value arg1, value arg2, value arg3) { value args[] = {arg1, arg2, arg3}; - return caml_callback3_asm(Caml_state, closure, args); + caml_domain_state* domain_state = Caml_state; + caml_maybe_expand_stack(); + + if (Stack_parent(domain_state->current_stack)) { + CAMLparam4 (closure, arg1, arg2, arg3); + CAMLlocal1 (cont); + value res; + + cont = save_and_clear_stack_parent(domain_state); + res = caml_callback3_asm(domain_state, closure, args); + restore_stack_parent(domain_state, cont); + + CAMLreturn (res); + } + return caml_callback3_asm(domain_state, closure, args); } +/* Native-code callbacks. caml_callback[123]_exn are implemented in asm. */ CAMLexport value caml_callbackN_exn(value closure, int narg, value args[]) { @@ -184,7 +272,7 @@ CAMLexport value caml_callbackN (value closure, int narg, value args[]) /* Naming of OCaml values */ struct named_value { - value val; + caml_root val; struct named_value * next; char name[1]; }; @@ -192,6 +280,11 @@ struct named_value { #define Named_value_size 13 static struct named_value * named_value_table[Named_value_size] = { NULL, }; +static caml_plat_mutex named_value_lock = CAML_PLAT_MUTEX_INITIALIZER; + +void caml_init_callbacks() { + init_callback_code(); +} static unsigned int hash_value_name(char const *name) { @@ -206,32 +299,58 @@ CAMLprim value caml_register_named_value(value vname, value val) const char * name = String_val(vname); size_t namelen = strlen(name); unsigned int h = hash_value_name(name); + int found = 0; + caml_plat_lock(&named_value_lock); for (nv = named_value_table[h]; nv != NULL; nv = nv->next) { if (strcmp(name, nv->name) == 0) { - caml_modify_generational_global_root(&nv->val, val); - return Val_unit; + caml_modify_root(nv->val, val); + found = 1; + break; } } - nv = (struct named_value *) - caml_stat_alloc(sizeof(struct named_value) + namelen); - memcpy(nv->name, name, namelen + 1); - nv->val = val; - nv->next = named_value_table[h]; - named_value_table[h] = nv; - caml_register_generational_global_root(&nv->val); + if (!found) { + nv = (struct named_value *) + caml_stat_alloc(sizeof(struct named_value) + namelen); + memcpy(nv->name, name, namelen + 1); + nv->val = caml_create_root(val); + nv->next = named_value_table[h]; + named_value_table[h] = nv; + } + caml_plat_unlock(&named_value_lock); return Val_unit; } -CAMLexport const value * caml_named_value(char const *name) +CAMLexport const value* caml_named_value(char const *name) { struct named_value * nv; + caml_root ret = NULL; + caml_plat_lock(&named_value_lock); for (nv = named_value_table[hash_value_name(name)]; nv != NULL; nv = nv->next) { - if (strcmp(name, nv->name) == 0) return &nv->val; + if (strcmp(name, nv->name) == 0){ + ret = nv->val; + break; + } } - return NULL; + caml_plat_unlock(&named_value_lock); + return Op_val(ret); +} + +CAMLexport int caml_get_callback_depth () +{ + return callback_depth; +} + +void caml_incr_callback_depth () +{ + callback_depth++; +} + +void caml_decr_callback_depth () +{ + callback_depth--; } CAMLexport void caml_iterate_named_values(caml_named_action f) @@ -240,7 +359,7 @@ CAMLexport void caml_iterate_named_values(caml_named_action f) for(i = 0; i < Named_value_size; i++){ struct named_value * nv; for (nv = named_value_table[i]; nv != NULL; nv = nv->next) { - f( &nv->val, nv->name ); + f( Op_val(nv->val), nv->name ); } } } diff --git a/runtime/caml/address_class.h b/runtime/caml/address_class.h index bf95063605..6a867a5ba4 100644 --- a/runtime/caml/address_class.h +++ b/runtime/caml/address_class.h @@ -65,11 +65,6 @@ /* Use the following macros to test an address for the different classes it might belong to. */ -#define Is_young(val) \ - (CAMLassert (Is_block (val)), \ - (char *)(val) < (char *)Caml_state_field(young_end) && \ - (char *)(val) > (char *)Caml_state_field(young_start)) - #define Is_in_heap(a) (Classify_addr(a) & In_heap) #ifdef NO_NAKED_POINTERS diff --git a/runtime/caml/addrmap.h b/runtime/caml/addrmap.h new file mode 100644 index 0000000000..00e0a22e12 --- /dev/null +++ b/runtime/caml/addrmap.h @@ -0,0 +1,79 @@ +#include "mlvalues.h" + +#ifndef CAML_ADDRMAP_H +#define CAML_ADDRMAP_H + +/* An addrmap is a value -> value hashmap, where + the values are blocks */ + +struct addrmap_entry { value key, value; }; +struct addrmap { + struct addrmap_entry* entries; + uintnat size; +}; + +#define ADDRMAP_INIT {0,0} + +int caml_addrmap_contains(struct addrmap* t, value v); +value caml_addrmap_lookup(struct addrmap* t, value v); + +#define ADDRMAP_NOT_PRESENT ((value)(0)) +#define ADDRMAP_INVALID_KEY ((value)(0)) + +value* caml_addrmap_insert_pos(struct addrmap* t, value v); + +/* must not already be present */ +void caml_addrmap_insert(struct addrmap* t, value k, value v); + +void caml_addrmap_clear(struct addrmap* t); + +void caml_addrmap_iter(struct addrmap* t, void (*f)(value, value)); + +/* iteration */ +typedef uintnat addrmap_iterator; +static inline addrmap_iterator caml_addrmap_iter_ok(struct addrmap* t, addrmap_iterator i) +{ + if (i < t->size) { + Assert(t->entries[i].key != ADDRMAP_INVALID_KEY); + return 1; + } else { + return 0; + } +} + +static inline addrmap_iterator caml_addrmap_next(struct addrmap* t, addrmap_iterator i) +{ + if (!t->entries) return (uintnat)(-1); + i++; + while (i < t->size && t->entries[i].key == ADDRMAP_INVALID_KEY) { + i++; + } + caml_addrmap_iter_ok(t, i); /* just for assert-checks */ + return i; +} + +static inline value caml_addrmap_iter_key(struct addrmap* t, addrmap_iterator i) +{ + Assert(caml_addrmap_iter_ok(t, i)); + return t->entries[i].key; +} + +static inline value caml_addrmap_iter_value(struct addrmap* t, addrmap_iterator i) +{ + Assert(caml_addrmap_iter_ok(t, i)); + return t->entries[i].value; +} + +static inline value* caml_addrmap_iter_val_pos(struct addrmap* t, addrmap_iterator i) +{ + Assert(caml_addrmap_iter_ok(t, i)); + return &t->entries[i].value; +} + +static inline addrmap_iterator caml_addrmap_iterator(struct addrmap* t) +{ + return caml_addrmap_next(t, (uintnat)(-1)); +} + + +#endif diff --git a/runtime/caml/alloc.h b/runtime/caml/alloc.h index af6e97980c..aaa2e52eee 100644 --- a/runtime/caml/alloc.h +++ b/runtime/caml/alloc.h @@ -1,17 +1,15 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ +/***********************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/***********************************************************************/ #ifndef CAML_ALLOC_H #define CAML_ALLOC_H @@ -27,23 +25,37 @@ extern "C" { #endif -/* It is guaranteed that these allocation functions will not trigger - any OCaml callback such as finalizers or signal handlers. */ - -CAMLextern value caml_alloc (mlsize_t wosize, tag_t); -CAMLextern value caml_alloc_small (mlsize_t wosize, tag_t); -CAMLextern value caml_alloc_tuple (mlsize_t wosize); -CAMLextern value caml_alloc_float_array (mlsize_t len); -CAMLextern value caml_alloc_string (mlsize_t len); /* len in bytes (chars) */ +CAMLextern value caml_alloc (mlsize_t, tag_t); +CAMLextern value caml_alloc_N(mlsize_t, tag_t, ...); +CAMLextern value caml_alloc_1(tag_t, value); +CAMLextern value caml_alloc_2(tag_t, value, value); +CAMLextern value caml_alloc_3(tag_t, value, value, value); +CAMLextern value caml_alloc_4(tag_t, value, value, value, value); +CAMLextern value caml_alloc_5(tag_t, value, value, value, value, + value); +CAMLextern value caml_alloc_6(tag_t, value, value, value, value, + value, value); +CAMLextern value caml_alloc_7(tag_t, value, value, value, value, + value, value, value); +CAMLextern value caml_alloc_8(tag_t, value, value, value, value, + value, value, value, value); +CAMLextern value caml_alloc_9(tag_t, value, value, value, value, + value, value, value, value, value); +CAMLextern value caml_alloc_small (mlsize_t, tag_t); +#define Init_field_small(o, i, x) (Op_val(o)[i] = (x)) +CAMLextern value caml_alloc_small_with_my_or_given_profinfo (mlsize_t wosize, + tag_t tag, uintnat profinfo); +CAMLextern value caml_alloc_tuple (mlsize_t); +CAMLextern value caml_alloc_string (mlsize_t); /* len in bytes (chars) */ CAMLextern value caml_alloc_initialized_string (mlsize_t len, const char *); CAMLextern value caml_copy_string (char const *); -CAMLextern value caml_copy_string_array (char const **); +CAMLextern value caml_copy_string_array (char const * const*); CAMLextern value caml_copy_double (double); CAMLextern value caml_copy_int32 (int32_t); /* defined in [ints.c] */ CAMLextern value caml_copy_int64 (int64_t); /* defined in [ints.c] */ CAMLextern value caml_copy_nativeint (intnat); /* defined in [ints.c] */ CAMLextern value caml_alloc_array (value (*funct) (char const *), - char const ** array); + char const * const * array); CAMLextern value caml_alloc_sprintf(const char * format, ...) #ifdef __GNUC__ __attribute__ ((format (printf, 1, 2))) @@ -51,33 +63,13 @@ CAMLextern value caml_alloc_sprintf(const char * format, ...) ; CAMLextern value caml_alloc_some(value); -CAMLextern value caml_alloc_with_profinfo (mlsize_t, tag_t, intnat); -CAMLextern value caml_alloc_small_with_my_or_given_profinfo ( - mlsize_t, tag_t, uintnat); -CAMLextern value caml_alloc_small_with_profinfo (mlsize_t, tag_t, intnat); - typedef void (*final_fun)(value); -CAMLextern value caml_alloc_final (mlsize_t wosize, +CAMLextern value caml_alloc_final (mlsize_t, /*size in words*/ final_fun, /*finalization function*/ mlsize_t, /*resources consumed*/ mlsize_t /*max resources*/); -CAMLextern int caml_convert_flag_list (value, int *); - -/* Convenience functions to deal with unboxable types. */ -Caml_inline value caml_alloc_unboxed (value arg) { return arg; } -Caml_inline value caml_alloc_boxed (value arg) { - value result = caml_alloc_small (1, 0); - Field (result, 0) = arg; - return result; -} -Caml_inline value caml_field_unboxed (value arg) { return arg; } -Caml_inline value caml_field_boxed (value arg) { return Field (arg, 0); } - -/* Unannotated unboxable types are boxed by default. (may change in the - future) */ -#define caml_alloc_unboxable caml_alloc_boxed -#define caml_field_unboxable caml_field_boxed +CAMLextern int caml_convert_flag_list (value, const int *); #ifdef __cplusplus } diff --git a/runtime/caml/backtrace.h b/runtime/caml/backtrace.h index 5cf24b8584..498ce85927 100644 --- a/runtime/caml/backtrace.h +++ b/runtime/caml/backtrace.h @@ -83,15 +83,15 @@ /* FIXME: this shouldn't matter anymore. Since OCaml 4.02, non-parameterized * exceptions are constant, so physical equality is no longer appropriate. * raise and re-raise are distinguished by: - * - passing reraise = 1 to [caml_stash_backtrace] (see below) in the bytecode - * interpreter; - * - directly resetting [Caml_state->backtrace_pos] to 0 in native - runtimes for raise. + * - passing reraise = 1 to [Caml_state->stash_backtrace] (see below) in the + * bytecode interpreter; + * - directly resetting [Caml_state->backtrace_pos] to 0 in native runtimes for + * raise. */ -/* [caml_record_backtrace] toggle backtrace recording on and off. - * This function can be called at runtime by user-code, or during - * initialization if backtraces were requested. +/* [Caml_state->record_backtrace] toggle backtrace recording on and off. This + * function can be called at runtime by user-code, or during initialization if + * backtraces were requested. * * It might be called before GC initialization, so it shouldn't do OCaml * allocation. diff --git a/runtime/caml/backtrace_prim.h b/runtime/caml/backtrace_prim.h index cf9596d3e1..9740ef61b0 100644 --- a/runtime/caml/backtrace_prim.h +++ b/runtime/caml/backtrace_prim.h @@ -91,21 +91,10 @@ value caml_remove_debug_info(code_t start); * It defines the [caml_stash_backtrace] function, which is called to quickly * fill the backtrace buffer by walking the stack when an exception is raised. * - * It also defines [caml_collect_current_callstack], which stores up - * to [max_frames] frames of the current call stack into the - * statically allocated buffer [*pbuffer] of length [*plen]. If the - * buffer is not long enough, it will be reallocated. The number of - * frames collected is returned. - * - * The alloc_idx parameter is used to select between the backtraces of - * different allocation sites which were combined by Comballoc. - * Passing -1 here means the caller doesn't care which is chosen. - * - * We use `intnat` for max_frames because, were it only `int`, passing - * `max_int` from the OCaml side would overflow on 64bits machines. */ - -intnat caml_collect_current_callstack(value** pbuffer, intnat* plen, - intnat max_frames, int alloc_idx); + * It also defines the [caml_get_current_callstack] OCaml primitive, which also + * walks the stack but directly turns it into a [raw_backtrace] and is called + * explicitly. + */ #endif /* CAML_INTERNALS */ diff --git a/runtime/caml/byte_domain_state.tbl b/runtime/caml/byte_domain_state.tbl new file mode 100644 index 0000000000..3f7f3c97b4 --- /dev/null +++ b/runtime/caml/byte_domain_state.tbl @@ -0,0 +1,3 @@ +BYTE_DOMAIN_STATE(intnat, trap_sp_off) +BYTE_DOMAIN_STATE(intnat, trap_barrier_off) +BYTE_DOMAIN_STATE(struct caml_exception_context*, external_raise) diff --git a/runtime/caml/callback.h b/runtime/caml/callback.h index eef3342ec7..f82fb50efb 100644 --- a/runtime/caml/callback.h +++ b/runtime/caml/callback.h @@ -22,11 +22,14 @@ #include "compatibility.h" #endif #include "mlvalues.h" +#include "memory.h" #ifdef __cplusplus extern "C" { #endif +void caml_init_callbacks (void); + CAMLextern value caml_callback (value closure, value arg); CAMLextern value caml_callback2 (value closure, value arg1, value arg2); CAMLextern value caml_callback3 (value closure, value arg1, value arg2, @@ -50,7 +53,9 @@ CAMLextern void caml_startup_pooled (char_os ** argv); CAMLextern value caml_startup_pooled_exn (char_os ** argv); CAMLextern void caml_shutdown (void); -CAMLextern int caml_callback_depth; +CAMLextern int caml_get_callback_depth (void); +void caml_incr_callback_depth (void); +void caml_decr_callback_depth (void); #ifdef __cplusplus } diff --git a/runtime/caml/camlatomic.h b/runtime/caml/camlatomic.h new file mode 100644 index 0000000000..a86c302d1a --- /dev/null +++ b/runtime/caml/camlatomic.h @@ -0,0 +1,65 @@ +#ifndef CAML_ATOMIC_H +#define CAML_ATOMIC_H + +#ifndef CAML_NAME_SPACE +#include "compatibility.h" +#endif +#include "config.h" +#include "misc.h" + +/* On platforms supporting C11 atomics, this file just includes <stdatomic.h>. + + On other platforms, this file includes platform-specific stubs for + the subset of C11 atomics needed by the OCaml runtime + */ + +#ifdef __cplusplus + +extern "C++" { +#include <atomic> +using namespace std; +#define ATOMIC_UINTNAT_INIT(x) (x) +typedef atomic<uintnat> atomic_uintnat; +typedef atomic<intnat> atomic_intnat; +} + +#elif defined(HAS_STDATOMIC_H) + +#include <stdatomic.h> +#define ATOMIC_UINTNAT_INIT(x) (x) +typedef _Atomic uintnat atomic_uintnat; +typedef _Atomic intnat atomic_intnat; + +#elif defined(__GNUC__) + +/* Support for versions of gcc which have built-in atomics but do not + expose stdatomic.h (e.g. gcc 4.8) */ +typedef enum memory_order { + memory_order_relaxed = __ATOMIC_RELAXED, + memory_order_acquire = __ATOMIC_ACQUIRE, + memory_order_release = __ATOMIC_RELEASE, + memory_order_acq_rel = __ATOMIC_ACQ_REL, + memory_order_seq_cst = __ATOMIC_SEQ_CST +} memory_order; + +#define ATOMIC_UINTNAT_INIT(x) { (x) } +typedef struct { uintnat repr; } atomic_uintnat; +typedef struct { intnat repr; } atomic_intnat; + +#define atomic_load_explicit(x, m) __atomic_load_n(&(x)->repr, (m)) +#define atomic_load(x) atomic_load_explicit((x), memory_order_seq_cst) +#define atomic_store_explicit(x, v, m) __atomic_store_n(&(x)->repr, (v), (m)) +#define atomic_store(x, v) atomic_store_explicit((x), (v), memory_order_seq_cst) +#define atomic_compare_exchange_strong(x, oldv, newv) \ + __atomic_compare_exchange_n(&(x)->repr, (oldv), (newv), 0, memory_order_seq_cst, memory_order_seq_cst) +#define atomic_exchange(x, newv) \ + __atomic_exchange_n(&(x)->repr, (newv), memory_order_seq_cst) +#define atomic_fetch_add(x, n) \ + __atomic_fetch_add(&(x)->repr, (n), memory_order_seq_cst) +#define atomic_thread_fence __atomic_thread_fence + +#else +#error "C11 atomics are unavailable on this platform. See camlatomic.h" +#endif + +#endif /* CAML_ATOMIC_H */ diff --git a/runtime/caml/compare.h b/runtime/caml/compare.h index 54b71581b9..94b1278c99 100644 --- a/runtime/caml/compare.h +++ b/runtime/caml/compare.h @@ -1,17 +1,15 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, Projet Moscova, INRIA Rocquencourt */ -/* */ -/* Copyright 2003 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ +/***********************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, Projet Moscova, INRIA Rocquencourt */ +/* */ +/* Copyright 2003 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. */ +/* */ +/***********************************************************************/ #ifndef CAML_COMPARE_H #define CAML_COMPARE_H diff --git a/runtime/caml/compatibility.h b/runtime/caml/compatibility.h index 1ec4df3fe2..606b9f7076 100644 --- a/runtime/caml/compatibility.h +++ b/runtime/caml/compatibility.h @@ -56,14 +56,12 @@ /* **** array.c */ /* **** backtrace.c */ -#define backtrace_active caml_backtrace_active -#define backtrace_pos caml_backtrace_pos -#define backtrace_buffer caml_backtrace_buffer -#define backtrace_last_exn caml_backtrace_last_exn +/*#define backtrace_buffer (Caml_state->caml_backtrace_buffer) + #define backtrace_last_exn (Caml_state->caml_backtrace_last_exn)*/ #define print_exception_backtrace caml_print_exception_backtrace /* **** callback.c */ -#define callback_depth caml_callback_depth +#define callback_depth (caml_get_callback_depth()) #define callbackN_exn caml_callbackN_exn #define callback_exn caml_callback_exn #define callback2_exn caml_callback2_exn @@ -226,23 +224,12 @@ /* **** memory.c */ #define alloc_shr caml_alloc_shr -#define initialize caml_initialize -#define modify caml_modify #define stat_alloc caml_stat_alloc #define stat_free caml_stat_free #define stat_resize caml_stat_resize /* **** meta.c */ -/* **** minor_gc.c */ -#define young_start caml_young_start -#define young_end caml_young_end -#define young_ptr caml_young_ptr -#define young_limit caml_young_limit -#define ref_table caml_ref_table -#define minor_collection caml_minor_collection -#define check_urgent_gc caml_check_urgent_gc - /* **** misc.c */ /* **** obj.c */ @@ -255,32 +242,17 @@ #define format_caml_exception caml_format_exception /*SP*/ /* **** roots.c */ -#define local_roots caml_local_roots -#define scan_roots_hook caml_scan_roots_hook +//#define local_roots CAML_LOCAL_ROOTS /* seems unnecessary */ #define do_local_roots caml_do_local_roots /* **** signals.c */ #define pending_signals caml_pending_signals -#define something_to_do caml_something_to_do -#define enter_blocking_section_hook caml_enter_blocking_section_hook -#define leave_blocking_section_hook caml_leave_blocking_section_hook -#define try_leave_blocking_section_hook caml_try_leave_blocking_section_hook #define enter_blocking_section caml_enter_blocking_section #define leave_blocking_section caml_leave_blocking_section #define convert_signal_number caml_convert_signal_number /* **** runtime/signals.c */ #define garbage_collection caml_garbage_collection -/* **** stacks.c */ -#define stack_low caml_stack_low -#define stack_high caml_stack_high -#define stack_threshold caml_stack_threshold -#define extern_sp caml_extern_sp -#define trapsp caml_trapsp -#define trap_barrier caml_trap_barrier - -/* **** startup.c */ -#define atom_table caml_atom_table /* **** runtime/startup_nat.c */ #define static_data_start caml_static_data_start #define static_data_end caml_static_data_end diff --git a/runtime/caml/config.h b/runtime/caml/config.h index 3502fc8240..8c7a62e04e 100644 --- a/runtime/caml/config.h +++ b/runtime/caml/config.h @@ -39,6 +39,12 @@ #define Caml_inline static inline #endif +#if defined(_MSC_VER) && !defined(__cplusplus) +#define Caml_inline static __inline +#else +#define Caml_inline static inline +#endif + #include "s.h" #ifdef BOOTSTRAPPING_FLEXLINK @@ -181,10 +187,19 @@ typedef uint64_t uintnat; #define Page_size (1 << Page_log) /* Initial size of stack (bytes). */ +#ifdef DEBUG +#define Stack_size (32 * sizeof(value)) +#else #define Stack_size (4096 * sizeof(value)) +#endif /* Minimum free size of stack (bytes); below that, it is reallocated. */ -#define Stack_threshold (256 * sizeof(value)) +#define Stack_threshold_words 16 +#define Stack_threshold (Stack_threshold_words * sizeof(value)) + +/* Number of words used in the control structure at the start of a stack + (see fiber.h) */ +#define Stack_ctx_words 5 /* Default maximum size of the stack (words). */ #define Max_stack_def (1024 * 1024) @@ -197,8 +212,8 @@ typedef uint64_t uintnat; /* Minimum size of the minor zone (words). - This must be at least [2 * Max_young_whsize]. */ -#define Minor_heap_min 4096 + This must be at least [Max_young_wosize + 1]. */ +#define Minor_heap_min (Max_young_wosize + 1) /* Maximum size of the minor zone (words). Must be greater than or equal to [Minor_heap_min]. @@ -236,6 +251,16 @@ typedef uint64_t uintnat; */ #define Max_percent_free_def 500 +/* Default setting for promoting with minor GC: 10%. + If the portion of the minor heap to be scanned during a promotion is greater + than 10%, then we promote the object by performing a local garbage + collection. + */ +#define Percent_to_promote_with_GC 10 + +/* Maximum number of domains */ +#define Max_domains 128 + /* Default setting for the major GC slice smoothing window: 1 (i.e. no smoothing) */ diff --git a/runtime/caml/custom.h b/runtime/caml/custom.h index 2713867bdf..de396150e8 100644 --- a/runtime/caml/custom.h +++ b/runtime/caml/custom.h @@ -48,23 +48,23 @@ struct custom_operations { #define custom_compare_ext_default NULL #define custom_fixed_length_default NULL -#define Custom_ops_val(v) (*((struct custom_operations **) (v))) +#define Custom_ops_val(v) (*((const struct custom_operations **) (v))) #ifdef __cplusplus extern "C" { #endif -CAMLextern value caml_alloc_custom(struct custom_operations * ops, +CAMLextern value caml_alloc_custom(const struct custom_operations * ops, uintnat size, /*size in bytes*/ mlsize_t mem, /*resources consumed*/ mlsize_t max /*max resources*/); -CAMLextern value caml_alloc_custom_mem(struct custom_operations * ops, +CAMLextern value caml_alloc_custom_mem(const struct custom_operations * ops, uintnat size, /*size in bytes*/ mlsize_t mem /*memory consumed*/); -CAMLextern void caml_register_custom_operations(struct custom_operations * ops); +CAMLextern void caml_register_custom_operations(const struct custom_operations * ops); /* Global variable moved to Caml_state in 4.10 */ #define caml_compare_unordered (Caml_state_field(compare_unordered)) diff --git a/runtime/caml/domain.h b/runtime/caml/domain.h index 23833d24f1..75fb60eaef 100644 --- a/runtime/caml/domain.h +++ b/runtime/caml/domain.h @@ -23,9 +23,125 @@ extern "C" { #ifdef CAML_INTERNALS +#include "config.h" +#include "mlvalues.h" #include "domain_state.h" +#include "memory.h" +#include "major_gc.h" +#include "platform.h" -void caml_init_domain(void); +struct domain { + struct dom_internal* internals; + caml_domain_state* state; +}; + +#define Caml_check_gc_interrupt(dom_st) \ + (CAMLalloc_point_here, \ + CAMLunlikely((uintnat)(dom_st)->young_ptr < (dom_st)->young_limit)) + +asize_t caml_norm_minor_heap_size (intnat); +int caml_reallocate_minor_heap(asize_t); + +int caml_incoming_interrupts_queued(void); + +void caml_handle_gc_interrupt(void); + +void caml_handle_incoming_interrupts(void); + +void caml_request_major_slice (void); + +void caml_request_minor_gc (void); + +void caml_interrupt_self(void); + +#if defined(COLLECT_STATS) && defined(NATIVE_CODE) +struct detailed_stats { + uint64 allocations; + + uint64 mutable_loads; + uint64 immutable_loads; + + uint64 mutable_stores; + uint64 immutable_stores; + + uint64 extcall_noalloc; + uint64 extcall_alloc; + uint64 extcall_alloc_stackargs; + + uint64 tailcall_imm; + uint64 tailcall_ind; + uint64 call_imm; + uint64 call_ind; + + uint64 stackoverflow_checks; +}; +#endif + +void caml_sample_gc_stats(struct gc_stats* buf); +void caml_print_stats(void); + +CAMLexport void caml_reset_domain_lock(void); +CAMLexport int caml_bt_is_in_blocking_section(void); +CAMLexport void caml_bt_enter_ocaml(void); +CAMLexport void caml_bt_exit_ocaml(void); +CAMLexport void caml_acquire_domain_lock(void); +CAMLexport void caml_release_domain_lock(void); + +CAMLextern void caml_enter_blocking_section(void); +CAMLextern void caml_leave_blocking_section(void); + +CAMLextern void (*caml_enter_blocking_section_hook)(void); +CAMLextern void (*caml_leave_blocking_section_hook)(void); + +CAMLextern void (*caml_domain_start_hook)(void); +CAMLextern void (*caml_domain_stop_hook)(void); + +void caml_init_domains(uintnat minor_heap_size); +void caml_init_domain_self(int); + +struct domain* caml_domain_self(); +struct domain* caml_owner_of_young_block(value); +struct domain* caml_domain_of_id(int); + +CAMLextern atomic_uintnat caml_num_domains_running; +CAMLextern uintnat caml_minor_heaps_base; +CAMLextern uintnat caml_minor_heaps_end; + +INLINE intnat caml_domain_alone() +{ + return atomic_load_acq(&caml_num_domains_running) == 1; +} + +typedef struct interrupt interrupt; +typedef void (*domain_rpc_handler)(struct domain*, void*, interrupt*); + +CAMLcheckresult +int caml_domain_rpc(struct domain*, + domain_rpc_handler, void*); + +typedef struct interrupt interrupt; +void caml_acknowledge_interrupt(interrupt*); + +#ifdef DEBUG +int caml_domain_is_in_stw(); +#endif + +void caml_run_on_all_running_domains_during_stw(void (*handler)(struct domain*, void*), void* data); +int caml_try_run_on_all_domains_with_spin_work(void (*handler)(struct domain*, void*, int, struct domain**), void*, void (*leader_setup)(struct domain*), + void (*enter_spin_callback)(struct domain*, void*), void*, + void (*leave_spin_callback)(struct domain*, void*), void*, + int); +int caml_try_run_on_all_domains(void (*handler)(struct domain*, void*, int, struct domain**), void*, void (*leader_setup)(struct domain*), int); + +void caml_global_barrier(); + +typedef uintnat barrier_status; +barrier_status caml_global_barrier_begin(); +int caml_global_barrier_is_final(barrier_status); +void caml_global_barrier_end(barrier_status); +int caml_global_barrier_num_domains(); +int caml_domain_is_terminating(void); +int caml_global_barrier_leave_when_done(); #endif /* CAML_INTERNALS */ diff --git a/runtime/caml/domain_state.h b/runtime/caml/domain_state.h index ee4613d60b..6edd57fc2d 100644 --- a/runtime/caml/domain_state.h +++ b/runtime/caml/domain_state.h @@ -17,23 +17,29 @@ #ifndef CAML_STATE_H #define CAML_STATE_H +#ifdef __APPLE__ +#include <pthread.h> +#endif #include <stddef.h> #include <stdio.h> + #include "misc.h" -#include "mlvalues.h" + +typedef struct caml_root_private* caml_root; /* This structure sits in the TLS area and is also accessed efficiently * via native code, which is why the indices are important */ - typedef struct { -#ifdef CAML_NAME_SPACE #define DOMAIN_STATE(type, name) CAMLalign(8) type name; -#else -#define DOMAIN_STATE(type, name) CAMLalign(8) type _##name; -#endif #include "domain_state.tbl" +#ifndef NATIVE_CODE + /* Bytecode TLS vars, not used for native code */ + #define BYTE_DOMAIN_STATE(type, name) type name; + #include "byte_domain_state.tbl" + #undef BYTE_DOMAIN_STATE +#endif #undef DOMAIN_STATE - CAMLalign(8) char end_of_domain_state; + CAMLalign(8) char end_of_domain_state; } caml_domain_state; enum { @@ -41,19 +47,42 @@ enum { #define DOMAIN_STATE(type, name) + 1 #include "domain_state.tbl" #undef DOMAIN_STATE + +#ifndef NATIVE_CODE + , + Byte_domain_state_num_fields = +#define BYTE_DOMAIN_STATE(type, name) + 1 +#include "byte_domain_state.tbl" +#undef BYTE_DOMAIN_STATE +#endif }; /* Check that the structure was laid out without padding, since the runtime assumes this in computing offsets */ +#ifdef NATIVE_CODE CAML_STATIC_ASSERT( offsetof(caml_domain_state, end_of_domain_state) == Domain_state_num_fields * 8); +#else +CAML_STATIC_ASSERT( + offsetof(caml_domain_state, end_of_domain_state) == + (Domain_state_num_fields + Byte_domain_state_num_fields) * 8); +#endif -CAMLextern caml_domain_state* Caml_state; -#ifdef CAML_NAME_SPACE -#define Caml_state_field(field) Caml_state->field +#ifdef __APPLE__ + CAMLextern pthread_key_t caml_domain_state_key; + CAMLextern void caml_init_domain_state_key(void); + #define CAML_INIT_DOMAIN_STATE caml_init_domain_state_key() + #define Caml_state \ + ((caml_domain_state*) pthread_getspecific(caml_domain_state_key)) + #define SET_Caml_state(x) \ + (pthread_setspecific(caml_domain_state_key, x)) #else -#define Caml_state_field(field) Caml_state->_##field + CAMLextern __thread caml_domain_state* Caml_state; + #define CAML_INIT_DOMAIN_STATE + #define SET_Caml_state(x) (Caml_state = (x)) #endif +#define Caml_state_field(field) (Caml_state->field) + #endif /* CAML_STATE_H */ diff --git a/runtime/caml/domain_state.tbl b/runtime/caml/domain_state.tbl index 8093020fab..4a22f04456 100644 --- a/runtime/caml/domain_state.tbl +++ b/runtime/caml/domain_state.tbl @@ -14,66 +14,134 @@ /* */ /**************************************************************************/ -DOMAIN_STATE(value*, young_ptr) -DOMAIN_STATE(value*, young_limit) -/* Minor heap limit. See minor_gc.c. */ - -DOMAIN_STATE(char*, exception_pointer) -/* Exception pointer that points into the current stack */ - -DOMAIN_STATE(void*, young_base) -DOMAIN_STATE(value*, young_start) -DOMAIN_STATE(value*, young_end) -DOMAIN_STATE(value*, young_alloc_start) -DOMAIN_STATE(value*, young_alloc_end) -DOMAIN_STATE(value*, young_alloc_mid) -DOMAIN_STATE(value*, young_trigger) -DOMAIN_STATE(asize_t, minor_heap_wsz) -DOMAIN_STATE(intnat, in_minor_collection) -DOMAIN_STATE(double, extra_heap_resources_minor) -DOMAIN_STATE(struct caml_ref_table*, ref_table) -DOMAIN_STATE(struct caml_ephe_ref_table*, ephe_ref_table) -DOMAIN_STATE(struct caml_custom_table*, custom_table) -/* See minor_gc.c */ - -DOMAIN_STATE(value*, stack_low) -DOMAIN_STATE(value*, stack_high) -DOMAIN_STATE(value*, stack_threshold) -DOMAIN_STATE(value*, extern_sp) -DOMAIN_STATE(value*, trapsp) -DOMAIN_STATE(value*, trap_barrier) -DOMAIN_STATE(struct longjmp_buffer*, external_raise) -DOMAIN_STATE(value, exn_bucket) -/* See interp.c */ - -DOMAIN_STATE(char*, top_of_stack) -DOMAIN_STATE(char*, bottom_of_stack) -DOMAIN_STATE(uintnat, last_return_address) +DOMAIN_STATE(volatile uintnat, young_limit) +/* Minor heap limit. Typically young_limit == young_end, but this field is set + * by other domains to signal this domain by causing a spurious allocation + * failure. */ + +DOMAIN_STATE(char*, young_ptr) +/* Minor heap pointer */ + +DOMAIN_STATE(char*, young_start) +/* Start of the minor heap */ + +DOMAIN_STATE(char*, young_end) +/* End of the minor heap. always(young_end <= young_ptr <= young_start) */ + +DOMAIN_STATE(struct stack_info*, current_stack) +/* Current stack */ + +DOMAIN_STATE(void*, exn_handler) +/* Pointer into into the current stack */ + +DOMAIN_STATE(struct c_stack_link*, c_stack) +/* The C stack associated with this domain. Used by this domain to perform external calls. */ + +DOMAIN_STATE(struct stack_info**, stack_cache) +/* This is a list of freelist buckets of stacks */ + +DOMAIN_STATE(value*, gc_regs_buckets) + DOMAIN_STATE(value*, gc_regs) -/* See roots_nat.c */ -DOMAIN_STATE(intnat, backtrace_active) +DOMAIN_STATE(value**, gc_regs_slot) + +DOMAIN_STATE(struct caml_minor_tables*, minor_tables) + +DOMAIN_STATE(struct mark_stack*, mark_stack) +/* Mark stack */ + +DOMAIN_STATE(uintnat, marking_done) +/* Is marking done for the current major cycle. */ + +DOMAIN_STATE(uintnat, sweeping_done) +/* Is sweeping done for the current major cycle. */ + +DOMAIN_STATE(uintnat, allocated_words) + +DOMAIN_STATE(uintnat, swept_words) + +DOMAIN_STATE(intnat, major_work_computed) +/* total work accumulated in this GC clock cycle (in words) */ + +DOMAIN_STATE(intnat, major_work_todo) +/* balance of work to do in this GC clock cycle (in words) + * positive: we need to do this amount of work to finish the slice + * negative: we have done more than we need and this is credit + */ + +DOMAIN_STATE(double, major_gc_clock) + +DOMAIN_STATE(struct caml__roots_block*, local_roots) + +DOMAIN_STATE(struct caml_ephe_info*, ephe_info) + +DOMAIN_STATE(struct caml_final_info*, final_info) + DOMAIN_STATE(intnat, backtrace_pos) -DOMAIN_STATE(backtrace_slot*, backtrace_buffer) -DOMAIN_STATE(value, backtrace_last_exn) -/* See backtrace.c */ + +DOMAIN_STATE(intnat, backtrace_active) + +DOMAIN_STATE(code_t*, backtrace_buffer) + +DOMAIN_STATE(caml_root, backtrace_last_exn) DOMAIN_STATE(intnat, compare_unordered) -DOMAIN_STATE(intnat, requested_major_slice) -DOMAIN_STATE(intnat, requested_minor_gc) -DOMAIN_STATE(struct caml__roots_block *, local_roots) -DOMAIN_STATE(double, stat_minor_words) -DOMAIN_STATE(double, stat_promoted_words) -DOMAIN_STATE(double, stat_major_words) +DOMAIN_STATE(uintnat, oo_next_id_local) + +DOMAIN_STATE(uintnat, requested_major_slice) + +DOMAIN_STATE(uintnat, requested_minor_gc) + +DOMAIN_STATE(intnat, critical_section_nesting) + +DOMAIN_STATE(struct interrupt*, pending_interrupts) + +DOMAIN_STATE(int, parser_trace) +/* See parsing.c */ + +DOMAIN_STATE(asize_t, minor_heap_wsz) + +DOMAIN_STATE(struct caml_heap_state*, shared_heap) + +DOMAIN_STATE(int, id) + +DOMAIN_STATE(int, unique_id) + +DOMAIN_STATE(struct pool**, pools_to_rescan) +DOMAIN_STATE(int, pools_to_rescan_len) +DOMAIN_STATE(int, pools_to_rescan_count) + +DOMAIN_STATE(caml_root, dls_root) + +/*****************************************************************************/ +/* GC stats (see gc_ctrl.c and the Gc module) */ +/*****************************************************************************/ +DOMAIN_STATE(uintnat, stat_minor_words) +DOMAIN_STATE(uintnat, stat_promoted_words) +DOMAIN_STATE(uintnat, stat_major_words) DOMAIN_STATE(intnat, stat_minor_collections) DOMAIN_STATE(intnat, stat_major_collections) -DOMAIN_STATE(intnat, stat_heap_wsz) -DOMAIN_STATE(intnat, stat_top_heap_wsz) -DOMAIN_STATE(intnat, stat_compactions) DOMAIN_STATE(intnat, stat_forced_major_collections) -DOMAIN_STATE(intnat, stat_heap_chunks) -/* See gc_ctrl.c */ +DOMAIN_STATE(uintnat, stat_blocks_marked) + +/*****************************************************************************/ +/* Detailed stats */ +/*****************************************************************************/ +DOMAIN_STATE(uintnat, allocations) +DOMAIN_STATE(uintnat, mutable_loads) +DOMAIN_STATE(uintnat, immutable_loads) +DOMAIN_STATE(uintnat, mutable_stores) +DOMAIN_STATE(uintnat, immutable_stores) +DOMAIN_STATE(uintnat, extcall_noalloc) +DOMAIN_STATE(uintnat, extcall_alloc) +DOMAIN_STATE(uintnat, extcall_alloc_stackargs) +DOMAIN_STATE(uintnat, tailcall_imm) +DOMAIN_STATE(uintnat, tailcall_ind) +DOMAIN_STATE(uintnat, call_imm) +DOMAIN_STATE(uintnat, call_ind) +DOMAIN_STATE(uintnat, stackoverflow_checks) DOMAIN_STATE(uintnat, eventlog_startup_timestamp) DOMAIN_STATE(long, eventlog_startup_pid) @@ -81,3 +149,9 @@ DOMAIN_STATE(uintnat, eventlog_paused) DOMAIN_STATE(uintnat, eventlog_enabled) DOMAIN_STATE(FILE*, eventlog_out) /* See eventlog.c */ + + +// whether or not a domain is inside of a stop-the-world handler +// this is used for several debug assertions inside of methods that +// can only be called from either in or outside this state. +DOMAIN_STATE(int, inside_stw_handler) diff --git a/runtime/caml/eventlog.h b/runtime/caml/eventlog.h index 3f2a4fca2d..25a9a0f086 100644 --- a/runtime/caml/eventlog.h +++ b/runtime/caml/eventlog.h @@ -1,4 +1,3 @@ -/**************************************************************************/ /* */ /* OCaml */ /* */ @@ -26,37 +25,55 @@ typedef enum { } ev_type; typedef enum { - EV_COMPACT_MAIN, - EV_COMPACT_RECOMPACT, + EV_DOMAIN_SPAWN, + EV_DOMAIN_SEND_INTERRUPT, + EV_DOMAIN_IDLE_WAIT, EV_EXPLICIT_GC_SET, EV_EXPLICIT_GC_STAT, EV_EXPLICIT_GC_MINOR, EV_EXPLICIT_GC_MAJOR, + EV_EXPLICIT_GC_MAJOR_SLICE, EV_EXPLICIT_GC_FULL_MAJOR, EV_EXPLICIT_GC_COMPACT, + EV_FINALISE_UPDATE_FIRST, + EV_FINALISE_UPDATE_LAST, + EV_INTERRUPT_GC, + EV_INTERRUPT_REMOTE, EV_MAJOR, - EV_MAJOR_ROOTS, - EV_MAJOR_SWEEP, + EV_MAJOR_EPHE_MARK, + EV_MAJOR_EPHE_SWEEP, + EV_MAJOR_FINISH_MARKING, + EV_MAJOR_GC_CYCLE_DOMAINS, + EV_MAJOR_GC_PHASE_CHANGE, + EV_MAJOR_GC_STW, EV_MAJOR_MARK_ROOTS, EV_MAJOR_MARK_MAIN, EV_MAJOR_MARK_FINAL, EV_MAJOR_MARK, EV_MAJOR_MARK_GLOBAL_ROOTS_SLICE, + EV_MAJOR_MARK_OPPORTUNISTIC, + EV_MAJOR_ROOTS, EV_MAJOR_ROOTS_GLOBAL, EV_MAJOR_ROOTS_DYNAMIC_GLOBAL, EV_MAJOR_ROOTS_LOCAL, EV_MAJOR_ROOTS_C, EV_MAJOR_ROOTS_FINALISED, - EV_MAJOR_ROOTS_MEMPROF, EV_MAJOR_ROOTS_HOOK, - EV_MAJOR_CHECK_AND_COMPACT, + EV_MAJOR_SLICE, + EV_MAJOR_SWEEP, EV_MINOR, + EV_MINOR_CLEAR, + EV_MINOR_FINALIZED, + EV_MINOR_FINALIZERS_OLDIFY, + EV_MINOR_GLOBAL_ROOTS, + EV_MINOR_LEAVE_BARRIER, EV_MINOR_LOCAL_ROOTS, EV_MINOR_REF_TABLES, - EV_MINOR_COPY, EV_MINOR_UPDATE_WEAK, - EV_MINOR_FINALIZED, - EV_EXPLICIT_GC_MAJOR_SLICE + EV_STW_API_BARRIER, + EV_STW_HANDLER, + EV_STW_LEADER, + } ev_gc_phase; typedef enum { @@ -64,8 +81,6 @@ typedef enum { EV_C_FORCE_MINOR_ALLOC_SMALL, EV_C_FORCE_MINOR_MAKE_VECT, EV_C_FORCE_MINOR_SET_MINOR_HEAP_SIZE, - EV_C_FORCE_MINOR_WEAK, - EV_C_FORCE_MINOR_MEMPROF, EV_C_MAJOR_MARK_SLICE_REMAIN, EV_C_MAJOR_MARK_SLICE_FIELDS, EV_C_MAJOR_MARK_SLICE_POINTERS, diff --git a/runtime/caml/fail.h b/runtime/caml/fail.h index ca4d8fd404..f79d060c6b 100644 --- a/runtime/caml/fail.h +++ b/runtime/caml/fail.h @@ -39,6 +39,8 @@ #define SYS_BLOCKED_IO 9 /* "Sys_blocked_io" */ #define ASSERT_FAILURE_EXN 10 /* "Assert_failure" */ #define UNDEFINED_RECURSIVE_MODULE_EXN 11 /* "Undefined_recursive_module" */ +#define UNHANDLED_EXN 12 /* "Unhandled" */ +#define CONTINUATION_ALREADY_TAKEN_EXN 13 /* "Continuation_already_taken" */ #ifdef POSIX_SIGNALS struct longjmp_buffer { @@ -59,6 +61,12 @@ struct longjmp_buffer { #define siglongjmp(buf,val) longjmp(buf,val) #endif +struct caml_exception_context { + struct longjmp_buffer* jmp; + struct caml__roots_block* local_roots; + volatile value* exn_bucket; +}; + /* Global variables moved to Caml_state in 4.10 */ #define caml_external_raise (Caml_state_field(external_raise)) #define caml_exn_bucket (Caml_state_field(exn_bucket)) @@ -141,6 +149,10 @@ CAMLnoreturn_start CAMLextern void caml_raise_sys_blocked_io (void) CAMLnoreturn_end; +CAMLnoreturn_start +CAMLextern void caml_raise_continuation_already_taken (void) +CAMLnoreturn_end; + #ifdef __cplusplus } #endif diff --git a/runtime/caml/fiber.h b/runtime/caml/fiber.h new file mode 100644 index 0000000000..f5ed1086b0 --- /dev/null +++ b/runtime/caml/fiber.h @@ -0,0 +1,109 @@ +#ifndef CAML_FIBER_H +#define CAML_FIBER_H + +#ifdef CAML_INTERNALS + +#include "misc.h" +#include "mlvalues.h" +#include "memory.h" +#include "roots.h" + +struct stack_info; + +struct stack_handler { + value handle_value; + value handle_exn; + value handle_effect; + struct stack_info* parent; +}; + +struct stack_info { +#ifdef NATIVE_CODE + void* sp; + void* exception_ptr; +#else + value* sp; + value* exception_ptr; +#endif + struct stack_handler* handler; + + /* [size_bucket] is a pointer to a bucket in Caml->stack_cache if this + * size is pooled. If unpooled, it is NULL. + * + * Stacks may be unpooled if either the stack size is not 2**N multiple of + * [caml_fiber_wsz] (may be the case in debug mode) or the stack is bigger + * than pooled sizes. */ + struct stack_info** size_bucket; + uintnat magic; +}; + +CAML_STATIC_ASSERT(sizeof(struct stack_info) == Stack_ctx_words * sizeof(value)); +#define Stack_base(stk) ((value*)(stk + 1)) +#define Stack_threshold_ptr(stk) (Stack_base(stk) + Stack_threshold / sizeof(value)) +#define Stack_high(stk) (value*)stk->handler + +#define Stack_handle_value(stk) (stk)->handler->handle_value +#define Stack_handle_exception(stk) (stk)->handler->handle_exn +#define Stack_handle_effect(stk) (stk)->handler->handle_effect +#define Stack_parent(stk) (stk)->handler->parent + +/* Stack layout for native code. Stack grows downwards. + * + * +------------------------+ + * | struct stack_handler | + * +------------------------+ <--- Stack_high + * | caml_runstack | + * +------------------------+ + * | | + * . OCaml frames . <--- sp + * | | + * +------------------------+ <--- Stack_threshold + * | | + * . Slop space . + * | | + * +------------------------+ <--- Stack_base + * | struct stack_info | + * +------------------------+ <--- Caml_state->current_stack + * | HEADER WORD | + * +------------------------+ + */ + +struct c_stack_link { + struct stack_info* stack; + void* sp; + struct c_stack_link* prev; +}; + +#define NUM_STACK_SIZE_CLASSES 5 + +/* The table of global identifiers */ +extern caml_root caml_global_data; + +#define Trap_pc(tp) ((tp)[0]) +#define Trap_link(tp) ((tp)[1]) + +struct stack_info** caml_alloc_stack_cache (void); +struct stack_info* caml_alloc_main_stack (uintnat init_size); +void caml_scan_stack(scanning_action f, void* fdata, struct stack_info* stack, value* v_gc_regs); +/* try to grow the stack until at least required_size words are available. + returns nonzero on success */ +int caml_try_realloc_stack (asize_t required_size); +void caml_change_max_stack_size (uintnat new_max_size); +void caml_maybe_expand_stack(); +void caml_free_stack(struct stack_info* stk); + +#ifdef NATIVE_CODE +void caml_get_stack_sp_pc (struct stack_info* stack, char** sp /* out */, uintnat* pc /* out */); +#endif + +value caml_continuation_use (value cont); + +/* Replace the stack of a continuation that was previouly removed + with caml_continuation_use. The GC must not be allowed to run + between continuation_use and continuation_replace. + Used for cloning continuations and continuation backtraces. */ +void caml_continuation_replace(value cont, struct stack_info* stack); + +#endif /* CAML_INTERNALS */ + +#endif /* CAML_FIBER_H */ diff --git a/runtime/caml/finalise.h b/runtime/caml/finalise.h index fbde3619a5..9eb7b2a460 100644 --- a/runtime/caml/finalise.h +++ b/runtime/caml/finalise.h @@ -19,17 +19,66 @@ #ifdef CAML_INTERNALS #include "roots.h" +#include "domain.h" -void caml_final_update_mark_phase (void); -void caml_final_update_clean_phase (void); -value caml_final_do_calls_exn (void); -void caml_final_do_roots (scanning_action f); -void caml_final_invert_finalisable_values (void); -void caml_final_oldify_young_roots (void); -void caml_final_empty_young (void); -void caml_final_update_minor_roots(void); +struct final { + value fun; + value val; + int offset; +}; + +struct finalisable { + struct final *table; + uintnat old; + uintnat young; + uintnat size; +}; +/* [0..old) : finalisable set, the values are in the major heap + [old..young) : recent set, the values could be in the minor heap + [young..size) : free space + + The element of the finalisable set are moved to the finalising set + below when the value are unreachable (for the first or last time). + +*/ + +struct final_todo { + struct final_todo *next; + int size; + struct final item[1]; /* variable size */ +}; + +/* + todo_head: head of the list of finalisation functions that can be run. + todo_tail: tail of the list of finalisation functions that can be run. + + It is the finalising set. +*/ + +struct caml_final_info { + struct finalisable first; + uintnat updated_first; + struct finalisable last; + uintnat updated_last; + struct final_todo *todo_head; + struct final_todo *todo_tail; + uintnat running_finalisation_function; + struct caml_final_info* next; /* used for orphaned finalisers. See major_gc.c */ +}; + +void caml_final_merge_finalisable (struct finalisable *source, + struct finalisable *target); +int caml_final_update_first (struct domain* d); +int caml_final_update_last (struct domain* d); +void caml_final_do_calls (void); +void caml_final_do_roots (scanning_action f, void* fdata, + struct domain* domain, int do_val); +void caml_final_do_young_roots (scanning_action f, void* fdata, + struct domain* d, int do_last_val); +void caml_final_empty_young (struct domain* d); +void caml_final_update_last_minor (struct domain* d); value caml_final_register (value f, value v); -void caml_final_invariant_check(void); +struct caml_final_info* caml_alloc_final_info(void); #endif /* CAML_INTERNALS */ diff --git a/runtime/caml/freelist.h b/runtime/caml/freelist.h deleted file mode 100644 index 17ebf5ef72..0000000000 --- a/runtime/caml/freelist.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* Free lists of heap blocks. */ - -#ifndef CAML_FREELIST_H -#define CAML_FREELIST_H - -#ifdef CAML_INTERNALS - -#include "misc.h" -#include "mlvalues.h" - -extern asize_t caml_fl_cur_wsz; - -/* See [freelist.c] for usage info on these functions. */ -extern header_t *(*caml_fl_p_allocate) (mlsize_t wo_sz); -extern void (*caml_fl_p_init_merge) (void); -extern header_t *(*caml_fl_p_merge_block) (value bp, char *limit); -extern void (*caml_fl_p_add_blocks) (value bp); -extern void (*caml_fl_p_make_free_blocks) - (value *p, mlsize_t size, int do_merge, int color); -#ifdef DEBUG -extern void (*caml_fl_p_check) (void); -#endif - -Caml_inline header_t *caml_fl_allocate (mlsize_t wo_sz) - { return (*caml_fl_p_allocate) (wo_sz); } - -Caml_inline void caml_fl_init_merge (void) - { (*caml_fl_p_init_merge) (); } - -Caml_inline header_t *caml_fl_merge_block (value bp, char *limit) - { return (*caml_fl_p_merge_block) (bp, limit); } - -Caml_inline void caml_fl_add_blocks (value bp) - { (*caml_fl_p_add_blocks) (bp); } - -Caml_inline void caml_make_free_blocks - (value *p, mlsize_t size, int do_merge, int color) - { (*caml_fl_p_make_free_blocks) (p, size, do_merge, color); } - -extern void caml_set_allocation_policy (intnat); -extern void caml_fl_reset_and_switch_policy (intnat); - -#ifdef DEBUG -Caml_inline void caml_fl_check (void) - { (*caml_fl_p_check) (); } -#endif - -#endif /* CAML_INTERNALS */ - -#endif /* CAML_FREELIST_H */ diff --git a/runtime/caml/gc.h b/runtime/caml/gc.h index 5276087e04..af6da9eea9 100644 --- a/runtime/caml/gc.h +++ b/runtime/caml/gc.h @@ -19,25 +19,6 @@ #include "mlvalues.h" -#define Caml_white (0 << 8) -#define Caml_gray (1 << 8) -#define Caml_blue (2 << 8) -#define Caml_black (3 << 8) - -#define Color_hd(hd) ((color_t) ((hd) & Caml_black)) -#define Color_hp(hp) (Color_hd (Hd_hp (hp))) -#define Color_val(val) (Color_hd (Hd_val (val))) - -#define Is_white_hd(hd) (Color_hd (hd) == Caml_white) -#define Is_gray_hd(hd) (Color_hd (hd) == Caml_gray) -#define Is_blue_hd(hd) (Color_hd (hd) == Caml_blue) -#define Is_black_hd(hd) (Color_hd (hd) == Caml_black) - -#define Whitehd_hd(hd) (((hd) & ~Caml_black)/*| Caml_white*/) -#define Grayhd_hd(hd) (((hd) & ~Caml_black) | Caml_gray) -#define Blackhd_hd(hd) (((hd)/*& ~Caml_black*/)| Caml_black) -#define Bluehd_hd(hd) (((hd) & ~Caml_black) | Caml_blue) - /* This depends on the layout of the header. See [mlvalues.h]. */ #define Make_header(wosize, tag, color) \ (/*CAMLassert ((wosize) <= Max_wosize),*/ \ @@ -46,34 +27,9 @@ + (tag_t) (tag))) \ ) -#ifdef WITH_PROFINFO -#define Make_header_with_profinfo(wosize, tag, color, profinfo) \ - (Make_header(wosize, tag, color) \ - | ((((intnat) profinfo) & PROFINFO_MASK) << PROFINFO_SHIFT) \ - ) -#else #define Make_header_with_profinfo(wosize, tag, color, profinfo) \ - Make_header(wosize, tag, color) -#endif - -#ifdef WITH_SPACETIME -struct ext_table; -extern uintnat caml_spacetime_my_profinfo(struct ext_table**, uintnat); -#define Make_header_allocated_here(wosize, tag, color) \ - (Make_header_with_profinfo(wosize, tag, color, \ - caml_spacetime_my_profinfo(NULL, wosize)) \ - ) -#else -#define Make_header_allocated_here Make_header -#endif - -#define Is_white_val(val) (Color_val(val) == Caml_white) -#define Is_gray_val(val) (Color_val(val) == Caml_gray) -#define Is_blue_val(val) (Color_val(val) == Caml_blue) -#define Is_black_val(val) (Color_val(val) == Caml_black) + Make_header(wosize,tag,color) -/* For extern.c */ -#define Colornum_hd(hd) ((color_t) (((hd) >> 8) & 3)) -#define Coloredhd_hd(hd,colnum) (((hd) & ~Caml_black) | ((colnum) << 8)) +#define Whitehd_hd(hd) (((hd) & ~(3 << 8))) #endif /* CAML_GC_H */ diff --git a/runtime/caml/gc_ctrl.h b/runtime/caml/gc_ctrl.h index dd3be4e52a..029ab18676 100644 --- a/runtime/caml/gc_ctrl.h +++ b/runtime/caml/gc_ctrl.h @@ -20,34 +20,12 @@ #include "misc.h" -/* Global variables moved to Caml_state in 4.10 */ -#define caml_stat_minor_words (Caml_state_field(stat_minor_words)) -#define caml_stat_promoted_words (Caml_state_field(stat_promoted_words)) -#define caml_stat_major_words (Caml_state_field(stat_major_words)) -#define caml_stat_minor_collections (Caml_state_field(stat_minor_collections)) -#define caml_stat_major_collections (Caml_state_field(stat_major_collections)) -#define caml_stat_heap_wsz (Caml_state_field(stat_heap_wsz)) -#define caml_stat_top_heap_wsz (Caml_state_field(stat_top_heap_wsz)) -#define caml_stat_compactions (Caml_state_field(stat_compactions)) -#define caml_stat_heap_chunks (Caml_state_field(stat_heap_chunks)) - -/* - 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 - custom_maj: cf. custom_major_ratio in gc.mli - custom_min: cf. custom_minor_ratio in gc.mli - custom_sz : cf. custom_minor_max_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, - uintnat custom_maj, uintnat custom_min, uintnat custom_bsz); - - -CAMLextern value caml_gc_stat(value v); +extern uintnat caml_max_stack_size; +extern uintnat caml_fiber_wsz; + +void caml_init_gc (); +value caml_gc_stat(value); +value caml_gc_major(value); #ifdef DEBUG void caml_heap_check (void); diff --git a/runtime/caml/globroots.h b/runtime/caml/globroots.h index 10fe66f5b7..ccd3d54202 100644 --- a/runtime/caml/globroots.h +++ b/runtime/caml/globroots.h @@ -23,9 +23,13 @@ #include "mlvalues.h" #include "roots.h" -void caml_scan_global_roots(scanning_action f); -void caml_scan_global_young_roots(scanning_action f); +void caml_scan_global_roots(scanning_action f, void* fdata); +void caml_scan_global_young_roots(scanning_action f, void* fdata); + +#ifdef NATIVE_CODE +void caml_register_dyn_global(void *v); +#endif #endif /* CAML_INTERNALS */ -#endif /* CAML_GLOBROOTS_H */ +#endif /* CAML_GLOBROOTS_H */
\ No newline at end of file diff --git a/runtime/caml/hash.h b/runtime/caml/hash.h index fcc7589f55..6b981f6347 100644 --- a/runtime/caml/hash.h +++ b/runtime/caml/hash.h @@ -35,5 +35,4 @@ CAMLextern uint32_t caml_hash_mix_string(uint32_t h, value s); } #endif - #endif /* CAML_HASH_H */ diff --git a/runtime/caml/instrtrace.h b/runtime/caml/instrtrace.h index 17ee3ce0c7..ba15fa2371 100644 --- a/runtime/caml/instrtrace.h +++ b/runtime/caml/instrtrace.h @@ -23,7 +23,7 @@ #include "mlvalues.h" #include "misc.h" -extern intnat caml_icount; +extern __thread intnat caml_icount; void caml_stop_here (void); void caml_disasm_instr (code_t pc); void caml_trace_value_file (value v, code_t prog, asize_t proglen, FILE * f); diff --git a/runtime/caml/instruct.h b/runtime/caml/instruct.h index 5c10df4f7b..da61991460 100644 --- a/runtime/caml/instruct.h +++ b/runtime/caml/instruct.h @@ -38,7 +38,9 @@ enum instructions { GETGLOBAL, PUSHGETGLOBAL, GETGLOBALFIELD, PUSHGETGLOBALFIELD, SETGLOBAL, ATOM0, ATOM, PUSHATOM0, PUSHATOM, MAKEBLOCK, MAKEBLOCK1, MAKEBLOCK2, MAKEBLOCK3, MAKEFLOATBLOCK, - GETFIELD0, GETFIELD1, GETFIELD2, GETFIELD3, GETFIELD, GETFLOATFIELD, + GETFIELD0, GETFIELD1, GETFIELD2, GETFIELD3, GETFIELD, + GETMUTABLEFIELD0, GETMUTABLEFIELD1, GETMUTABLEFIELD2, GETMUTABLEFIELD3, + GETMUTABLEFIELD, GETFLOATFIELD, SETFIELD0, SETFIELD1, SETFIELD2, SETFIELD3, SETFIELD, SETFLOATFIELD, VECTLENGTH, GETVECTITEM, SETVECTITEM, GETBYTESCHAR, SETBYTESCHAR, @@ -60,6 +62,7 @@ enum instructions { STOP, EVENT, BREAK, RERAISE, RAISE_NOTRACE, + PERFORM, RESUME, RESUMETERM, REPERFORMTERM, GETSTRINGCHAR, FIRST_UNIMPLEMENTED_OP}; diff --git a/runtime/caml/intext.h b/runtime/caml/intext.h index be4b9467b9..ceb3e6a006 100644 --- a/runtime/caml/intext.h +++ b/runtime/caml/intext.h @@ -148,7 +148,7 @@ CAMLextern value caml_input_value_from_malloc(char * data, intnat ofs); to the beginning of the buffer, and [ofs] is the offset of the beginning of the externed data in this buffer. The buffer is deallocated with [free] on return, or if an exception is raised. */ -CAMLextern value caml_input_value_from_block(char * data, intnat len); +CAMLextern value caml_input_value_from_block(const char * data, intnat len); /* Read a structured value from a user-provided buffer. [data] points to the beginning of the externed data in this buffer, and [len] is the length in bytes of valid data in this buffer. diff --git a/runtime/caml/io.h b/runtime/caml/io.h index 2d961f9565..0238b675af 100644 --- a/runtime/caml/io.h +++ b/runtime/caml/io.h @@ -22,6 +22,7 @@ #include "misc.h" #include "mlvalues.h" +#include "platform.h" #ifndef IO_BUFFER_SIZE #define IO_BUFFER_SIZE 65536 @@ -40,7 +41,7 @@ struct channel { char * end; /* Physical end of the buffer */ char * curr; /* Current position in the buffer */ char * max; /* Logical end of the buffer (for input) */ - void * mutex; /* Placeholder for mutex (for systhreads) */ + caml_plat_mutex mutex; /* Mutex protecting buffer */ struct channel * next, * prev;/* Double chaining of channels (flush_all) */ int revealed; /* For Cash only */ int old_revealed; /* For Cash only */ @@ -98,24 +99,9 @@ CAMLextern intnat caml_really_getblock (struct channel *, char *, intnat); #define Channel(v) (*((struct channel **) (Data_custom_val(v)))) -/* The locking machinery */ - -CAMLextern void (*caml_channel_mutex_free) (struct channel *); -CAMLextern void (*caml_channel_mutex_lock) (struct channel *); -CAMLextern void (*caml_channel_mutex_unlock) (struct channel *); -CAMLextern void (*caml_channel_mutex_unlock_exn) (void); - CAMLextern struct channel * caml_all_opened_channels; -#define Lock(channel) \ - if (caml_channel_mutex_lock != NULL) (*caml_channel_mutex_lock)(channel) -#define Unlock(channel) \ - if (caml_channel_mutex_unlock != NULL) (*caml_channel_mutex_unlock)(channel) -#define Unlock_exn() \ - if (caml_channel_mutex_unlock_exn != NULL) (*caml_channel_mutex_unlock_exn)() - /* Conversion between file_offset and int64_t */ - #define Val_file_offset(fofs) caml_copy_int64(fofs) #define File_offset_val(v) ((file_offset) Int64_val(v)) diff --git a/runtime/caml/major_gc.h b/runtime/caml/major_gc.h index 873397570a..dbaef4d005 100644 --- a/runtime/caml/major_gc.h +++ b/runtime/caml/major_gc.h @@ -13,76 +13,80 @@ /* */ /**************************************************************************/ -#ifndef CAML_MAJOR_GC_H -#define CAML_MAJOR_GC_H +#ifndef CAML_MAJOR_GC +#define CAML_MAJOR_GC #ifdef CAML_INTERNALS -#include "freelist.h" -#include "misc.h" - -typedef struct { - void *block; /* address of the malloced block this chunk lives in */ - asize_t alloc; /* in bytes, used for compaction */ - asize_t size; /* in bytes */ - char *next; -} heap_chunk_head; - -#define Chunk_size(c) (((heap_chunk_head *) (c)) [-1]).size -#define Chunk_alloc(c) (((heap_chunk_head *) (c)) [-1]).alloc -#define Chunk_next(c) (((heap_chunk_head *) (c)) [-1]).next -#define Chunk_block(c) (((heap_chunk_head *) (c)) [-1]).block - -extern int caml_gc_phase; -extern int caml_gc_subphase; -extern uintnat caml_allocated_words; -extern double caml_extra_heap_resources; -extern uintnat caml_dependent_size, caml_dependent_allocated; -extern uintnat caml_fl_wsz_at_phase_change; - -#define Phase_mark 0 -#define Phase_clean 1 -#define Phase_sweep 2 -#define Phase_idle 3 - -/* Subphase of mark */ -#define Subphase_mark_roots 10 -/* Subphase_mark_roots: At the end of this subphase all the global - roots are marked. */ -#define Subphase_mark_main 11 -/* Subphase_mark_main: At the end of this subphase all the value alive at - the start of this subphase and created during it are marked. */ -#define Subphase_mark_final 12 -/* Subphase_mark_final: At the start of this subphase register which - value with an ocaml finalizer are not marked, the associated - finalizer will be run later. So we mark now these values as alive, - since they must be available for their finalizer. - */ - -CAMLextern char *caml_heap_start; -extern uintnat total_heap_size; -extern char *caml_gc_sweep_hp; - -extern int caml_major_window; -extern double caml_major_ring[Max_major_window]; -extern int caml_major_ring_index; -extern double caml_major_work_credit; -extern double caml_gc_clock; - -/* [caml_major_gc_hook] is called just between the end of the mark - phase and the beginning of the sweep phase of the major GC. - - This hook must not allocate, change any heap value, nor - call OCaml code. */ -CAMLextern void (*caml_major_gc_hook)(void); - -void caml_init_major_heap (asize_t); /* size in bytes */ -asize_t caml_clip_heap_chunk_wsz (asize_t wsz); -void caml_darken (value, value *); -void caml_major_collection_slice (intnat); -void major_collection (void); -void caml_finish_major_cycle (void); -void caml_set_major_window (int); +typedef enum { + Phase_sweep_and_mark_main, + Phase_mark_final, + Phase_sweep_ephe +} gc_phase_t; +extern gc_phase_t caml_gc_phase; + +static inline char caml_gc_phase_char(gc_phase_t phase) { + switch (phase) { + case Phase_sweep_and_mark_main: + return 'M'; + case Phase_mark_final: + return 'F'; + case Phase_sweep_ephe: + return 'E'; + default: + return 'U'; + } +} + +intnat caml_opportunistic_major_work_available (); +intnat caml_opportunistic_major_collection_slice (intnat); +/* auto-triggered slice from within the GC */ +#define AUTO_TRIGGERED_MAJOR_SLICE -1 +/* external triggered slice, but GC will compute the amount of work */ +#define GC_CALCULATE_MAJOR_SLICE 0 +intnat caml_major_collection_slice (intnat); +void caml_finish_sweeping(void); +void caml_finish_marking (void); +uintnat caml_get_num_domains_to_mark(void); +int caml_init_major_gc(caml_domain_state*); +void caml_teardown_major_gc(void); +void caml_darken(void*, value, value* ignored); +void caml_darken_cont(value); +void caml_mark_root(value, value*); +void caml_empty_mark_stack(void); +void caml_finish_major_cycle(void); + +/* Ephemerons and finalisers */ +void caml_ephe_todo_list_emptied(void); +void caml_orphan_allocated_words(); +void caml_add_to_orphaned_ephe_list(struct caml_ephe_info* ephe_info); +void caml_add_orphaned_finalisers (struct caml_final_info*); +void caml_final_domain_terminate (caml_domain_state *domain_state); +void caml_adopt_orphaned_work (void); + +struct heap_stats { + intnat pool_words; + intnat pool_max_words; + intnat pool_live_words; + intnat pool_live_blocks; + intnat pool_frag_words; + intnat large_words; + intnat large_max_words; + intnat large_blocks; +}; +void caml_accum_heap_stats(struct heap_stats* acc, const struct heap_stats* s); +void caml_remove_heap_stats(struct heap_stats* acc, const struct heap_stats* s); + +struct gc_stats { + uint64_t minor_words; + uint64_t promoted_words; + uint64_t major_words; + uint64_t minor_collections; + uint64_t forced_major_collections; + struct heap_stats major_heap; +}; +void caml_sample_gc_stats(struct gc_stats* buf); +void caml_sample_gc_collect(caml_domain_state *domain); /* Forces finalisation of all heap-allocated values, disregarding both local and global roots. @@ -93,6 +97,12 @@ void caml_set_major_window (int); */ void caml_finalise_heap (void); -#endif /* CAML_INTERNALiS */ +/* This variable is only written with the world stopped, + so it need not be atomic */ +extern uintnat caml_major_cycles_completed; + +double caml_mean_space_overhead(void); + +#endif /* CAML_INTERNALS */ #endif /* CAML_MAJOR_GC_H */ diff --git a/runtime/caml/memory.h b/runtime/caml/memory.h index 2669cfdfc0..79279b5aac 100644 --- a/runtime/caml/memory.h +++ b/runtime/caml/memory.h @@ -18,7 +18,7 @@ #ifndef CAML_MEMORY_H #define CAML_MEMORY_H -#ifndef CAML_NAME_SPACE +#ifndef CAML_INTERNALS #include "compatibility.h" #endif #include "config.h" @@ -27,44 +27,46 @@ #include "major_gc.h" #include "minor_gc.h" #endif /* CAML_INTERNALS */ +#include "domain.h" #include "misc.h" #include "mlvalues.h" -#include "domain.h" +#include "alloc.h" #ifdef __cplusplus extern "C" { #endif CAMLextern value caml_alloc_shr (mlsize_t wosize, tag_t); +CAMLextern value caml_alloc_shr_noexc(mlsize_t wosize, tag_t); #ifdef WITH_PROFINFO CAMLextern value caml_alloc_shr_with_profinfo (mlsize_t, tag_t, intnat); +CAMLextern value caml_alloc_shr_preserving_profinfo (mlsize_t, tag_t, + header_t); #else #define caml_alloc_shr_with_profinfo(size, tag, profinfo) \ caml_alloc_shr(size, tag) +#define caml_alloc_shr_preserving_profinfo(size, tag, header) \ + caml_alloc_shr(size, tag) #endif /* WITH_PROFINFO */ - -/* Variant of [caml_alloc_shr] where no memprof sampling is performed. */ -CAMLextern value caml_alloc_shr_no_track_noexc (mlsize_t, tag_t); - -/* Variant of [caml_alloc_shr] where no memprof sampling is performed, - and re-using the profinfo associated with the header given in - parameter. */ -CAMLextern value caml_alloc_shr_for_minor_gc (mlsize_t, tag_t, header_t); - -CAMLextern void caml_adjust_gc_speed (mlsize_t, mlsize_t); -CAMLextern void caml_alloc_dependent_memory (mlsize_t bsz); -CAMLextern void caml_free_dependent_memory (mlsize_t bsz); -CAMLextern void caml_modify (value *, value); -CAMLextern void caml_initialize (value *, value); +CAMLextern value caml_alloc_shr_no_raise (mlsize_t wosize, tag_t); +CAMLextern void caml_alloc_dependent_memory (mlsize_t); +CAMLextern void caml_free_dependent_memory (mlsize_t); +CAMLextern void caml_modify_field (value, intnat, value); +#define caml_modify_field caml_modify_field +CAMLextern int caml_atomic_cas_field (value, intnat, value, value); +CAMLextern void caml_initialize_field (value, intnat, value); +#define caml_initialize_field caml_initialize_field +CAMLextern void caml_blit_fields (value src, int srcoff, value dst, int dstoff, int n); CAMLextern value caml_check_urgent_gc (value); CAMLextern char *caml_alloc_for_heap (asize_t request); /* Size in bytes. */ CAMLextern void caml_free_for_heap (char *mem); -CAMLextern void caml_disown_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; +CAMLextern int caml_huge_fallback_count; /* FIXME KC: Make per domain */ +/* old CAPI function compatability */ +CAMLextern void caml_modify (value *, value); +CAMLextern void caml_initialize (value *, value); /* [caml_stat_*] functions below provide an interface to the static memory manager built into the runtime, which can be used for managing static @@ -184,6 +186,15 @@ CAMLextern wchar_t* caml_stat_wcsconcat(int n, ...); #ifdef CAML_INTERNALS +/* FIXME */ +/* There are two GC bits in the object header, with the following + possible values: + 00: new object, not forwarded + 11: forwarded by a fault promotion */ + +#define Is_promoted_hd(hd) (((hd) & (3 << 8)) == (3 << 8)) +#define Promotedhd_hd(hd) ((hd) | (3 << 8)) + extern uintnat caml_use_huge_pages; #ifdef HAS_HUGE_PAGES @@ -193,86 +204,58 @@ extern uintnat caml_use_huge_pages; (((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; \ for (caml__DEBUG_i = 0; caml__DEBUG_i < (wosize); ++ caml__DEBUG_i){ \ - Field ((result), caml__DEBUG_i) = Debug_uninit_minor; \ + Op_val (result)[caml__DEBUG_i] = Debug_uninit_minor; \ } \ }while(0) #else #define DEBUG_clear(result, wosize) #endif -enum caml_alloc_small_flags { - CAML_DONT_TRACK = 0, CAML_DO_TRACK = 1, - CAML_FROM_C = 0, CAML_FROM_CAML = 2 -}; - -extern void caml_alloc_small_dispatch (intnat wosize, int flags, - int nallocs, unsigned char* alloc_lens); -// Do not call asynchronous callbacks from allocation functions -#define Alloc_small_origin CAML_FROM_C -#define Alloc_small_aux(result, wosize, tag, profinfo, track) do { \ - CAMLassert ((wosize) >= 1); \ - CAMLassert ((tag_t) (tag) < 256); \ - CAMLassert ((wosize) <= Max_young_wosize); \ - Caml_state_field(young_ptr) -= Whsize_wosize (wosize); \ - if (Caml_state_field(young_ptr) < Caml_state_field(young_limit)) { \ - Setup_for_gc; \ - caml_alloc_small_dispatch((wosize), (track) | Alloc_small_origin, \ - 1, NULL); \ - Restore_after_gc; \ - } \ - Hd_hp (Caml_state_field(young_ptr)) = \ - Make_header_with_profinfo ((wosize), (tag), 0, profinfo); \ - (result) = Val_hp (Caml_state_field(young_ptr)); \ - DEBUG_clear ((result), (wosize)); \ -}while(0) - -#define Alloc_small_with_profinfo(result, wosize, tag, profinfo) \ - Alloc_small_aux(result, wosize, tag, profinfo, CAML_DO_TRACK) - -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - -extern uintnat caml_spacetime_my_profinfo(struct ext_table**, uintnat); - -#define Alloc_small(result, wosize, tag) \ - Alloc_small_with_profinfo(result, wosize, tag, \ - caml_spacetime_my_profinfo(NULL, wosize)) -#define Alloc_small_no_track(result, wosize, tag) \ - Alloc_small_aux(result, wosize, tag, \ - caml_spacetime_my_profinfo(NULL, wosize), CAML_DONT_TRACK) - +#if defined(COLLECT_STATS) && defined(NATIVE_CODE) +#define Count_alloc dom_st->allocations++ #else - -#define Alloc_small(result, wosize, tag) \ - Alloc_small_with_profinfo(result, wosize, tag, (uintnat) 0) -#define Alloc_small_no_track(result, wosize, tag) \ - Alloc_small_aux(result, wosize, tag, (uintnat) 0, CAML_DONT_TRACK) - +#define Count_alloc #endif -/* Deprecated alias for [caml_modify] */ +#define Alloc_small_with_profinfo(result, wosize, tag, GC, profinfo) do{ \ + caml_domain_state* dom_st; \ + CAMLassert ((wosize) >= 1); \ + CAMLassert ((tag_t) (tag) < 256); \ + CAMLassert ((wosize) <= Max_young_wosize); \ + dom_st = Caml_state; \ + dom_st->young_ptr -= Bhsize_wosize (wosize); \ + if (Caml_check_gc_interrupt(dom_st)){ \ + dom_st->young_ptr += Bhsize_wosize (wosize); \ + { GC } \ + dom_st->young_ptr -= Bhsize_wosize (wosize); \ + } \ + Hd_hp (dom_st->young_ptr) = \ + Make_header_with_profinfo ((wosize), (tag), 0, profinfo); \ + /* FIXME: Spacetime */ if (profinfo == 0); \ + (result) = Val_hp (dom_st->young_ptr); \ + DEBUG_clear ((result), (wosize)); \ + Count_alloc; \ +}while(0) -#define Modify(fp,val) caml_modify((fp), (val)) +#define Alloc_small(result, wosize, tag, GC) \ + Alloc_small_with_profinfo(result, wosize, tag, GC, (uintnat)0) #endif /* CAML_INTERNALS */ +struct caml__mutex_unwind; struct caml__roots_block { struct caml__roots_block *next; + struct caml__mutex_unwind *mutexes; intnat ntables; intnat nitems; value *tables [5]; }; -/* Global variable moved to Caml_state in 4.10 */ -#define caml_local_roots (Caml_state_field(local_roots)) +#define CAML_LOCAL_ROOTS (Caml_state->local_roots) /* The following macros are used to declare C local variables and function parameters of type [value]. @@ -306,7 +289,8 @@ struct caml__roots_block { */ #define CAMLparam0() \ - struct caml__roots_block *caml__frame = Caml_state_field(local_roots) + struct caml__roots_block** caml_local_roots_ptr = &CAML_LOCAL_ROOTS;\ + struct caml__roots_block *caml__frame = *caml_local_roots_ptr #define CAMLparam1(x) \ CAMLparam0 (); \ @@ -332,34 +316,12 @@ struct caml__roots_block { CAMLparam0 (); \ CAMLxparamN (x, (size)) -/* CAMLunused is preserved for compatibility reasons. - Instead of the legacy GCC/Clang-only - CAMLunused foo; - you should prefer - CAMLunused_start foo CAMLunused_end; - which supports both GCC/Clang and MSVC. -*/ -#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 7)) - #define CAMLunused_start __attribute__ ((unused)) - #define CAMLunused_end - #define CAMLunused __attribute__ ((unused)) -#elif _MSC_VER >= 1500 - #define CAMLunused_start __pragma( warning (push) ) \ - __pragma( warning (disable:4189 ) ) - #define CAMLunused_end __pragma( warning (pop)) - #define CAMLunused -#else - #define CAMLunused_start - #define CAMLunused_end - #define CAMLunused -#endif - #define CAMLxparam1(x) \ struct caml__roots_block caml__roots_##x; \ CAMLunused_start int caml__dummy_##x = ( \ - (void) caml__frame, \ - (caml__roots_##x.next = Caml_state_field(local_roots)), \ - (Caml_state_field(local_roots) = &caml__roots_##x), \ + (caml__roots_##x.next = *caml_local_roots_ptr), \ + (*caml_local_roots_ptr = &caml__roots_##x), \ + (caml__roots_##x.mutexes = 0), \ (caml__roots_##x.nitems = 1), \ (caml__roots_##x.ntables = 1), \ (caml__roots_##x.tables [0] = &x), \ @@ -369,9 +331,9 @@ struct caml__roots_block { #define CAMLxparam2(x, y) \ struct caml__roots_block caml__roots_##x; \ CAMLunused_start int caml__dummy_##x = ( \ - (void) caml__frame, \ - (caml__roots_##x.next = Caml_state_field(local_roots)), \ - (Caml_state_field(local_roots) = &caml__roots_##x), \ + (caml__roots_##x.next = *caml_local_roots_ptr), \ + (*caml_local_roots_ptr = &caml__roots_##x), \ + (caml__roots_##x.mutexes = 0), \ (caml__roots_##x.nitems = 1), \ (caml__roots_##x.ntables = 2), \ (caml__roots_##x.tables [0] = &x), \ @@ -382,9 +344,9 @@ struct caml__roots_block { #define CAMLxparam3(x, y, z) \ struct caml__roots_block caml__roots_##x; \ CAMLunused_start int caml__dummy_##x = ( \ - (void) caml__frame, \ - (caml__roots_##x.next = Caml_state_field(local_roots)), \ - (Caml_state_field(local_roots) = &caml__roots_##x), \ + (caml__roots_##x.next = *caml_local_roots_ptr), \ + (*caml_local_roots_ptr = &caml__roots_##x), \ + (caml__roots_##x.mutexes = 0), \ (caml__roots_##x.nitems = 1), \ (caml__roots_##x.ntables = 3), \ (caml__roots_##x.tables [0] = &x), \ @@ -396,9 +358,9 @@ struct caml__roots_block { #define CAMLxparam4(x, y, z, t) \ struct caml__roots_block caml__roots_##x; \ CAMLunused_start int caml__dummy_##x = ( \ - (void) caml__frame, \ - (caml__roots_##x.next = Caml_state_field(local_roots)), \ - (Caml_state_field(local_roots) = &caml__roots_##x), \ + (caml__roots_##x.next = *caml_local_roots_ptr), \ + (*caml_local_roots_ptr = &caml__roots_##x), \ + (caml__roots_##x.mutexes = 0), \ (caml__roots_##x.nitems = 1), \ (caml__roots_##x.ntables = 4), \ (caml__roots_##x.tables [0] = &x), \ @@ -411,9 +373,9 @@ struct caml__roots_block { #define CAMLxparam5(x, y, z, t, u) \ struct caml__roots_block caml__roots_##x; \ CAMLunused_start int caml__dummy_##x = ( \ - (void) caml__frame, \ - (caml__roots_##x.next = Caml_state_field(local_roots)), \ - (Caml_state_field(local_roots) = &caml__roots_##x), \ + (caml__roots_##x.next = *caml_local_roots_ptr), \ + (*caml_local_roots_ptr = &caml__roots_##x), \ + (caml__roots_##x.mutexes = 0), \ (caml__roots_##x.nitems = 1), \ (caml__roots_##x.ntables = 5), \ (caml__roots_##x.tables [0] = &x), \ @@ -426,16 +388,20 @@ struct caml__roots_block { #define CAMLxparamN(x, size) \ struct caml__roots_block caml__roots_##x; \ - CAMLunused_start int caml__dummy_##x = ( \ - (void) caml__frame, \ - (caml__roots_##x.next = Caml_state_field(local_roots)), \ - (Caml_state_field(local_roots) = &caml__roots_##x), \ + CAMLunused_start int caml__dummy_##x = ( \ + (caml__roots_##x.next = *caml_local_roots_ptr), \ + (*caml_local_roots_ptr = &caml__roots_##x), \ + (caml__roots_##x.mutexes = 0), \ (caml__roots_##x.nitems = (size)), \ (caml__roots_##x.ntables = 1), \ (caml__roots_##x.tables[0] = &(x[0])), \ 0) \ CAMLunused_end +#define CAMLxparamNextend(x, new_size) \ + (caml__roots_##x.nitems = (new_size)) \ + CAMLunused_end + #define CAMLlocal1(x) \ value x = Val_unit; \ CAMLxparam1 (x) @@ -459,13 +425,28 @@ struct caml__roots_block { #define CAMLlocalN(x, size) \ value x [(size)]; \ int caml__i_##x; \ + CAMLxparamN (x, (size)); \ for (caml__i_##x = 0; caml__i_##x < size; caml__i_##x ++) { \ x[caml__i_##x] = Val_unit; \ - } \ - CAMLxparamN (x, (size)) + } +#ifdef DEBUG +#define CAMLcheck_mutexes do { \ + struct caml__roots_block* r; \ + for (r = CAML_LOCAL_ROOTS; \ + r != caml__frame; \ + r = r->next) { \ + CAMLassert(r->mutexes == 0); \ + } \ +} while (0) +#else +#define CAMLcheck_mutexes do {} while(0) +#endif -#define CAMLdrop Caml_state_field(local_roots) = caml__frame +#define CAMLdrop do{ \ + CAMLcheck_mutexes; \ + *caml_local_roots_ptr = caml__frame; \ +}while (0) #define CAMLreturn0 do{ \ CAMLdrop; \ @@ -475,7 +456,7 @@ struct caml__roots_block { #define CAMLreturnT(type, result) do{ \ type caml__temp_result = (result); \ CAMLdrop; \ - return caml__temp_result; \ + return (caml__temp_result); \ }while(0) #define CAMLreturn(result) CAMLreturnT(value, result) @@ -487,7 +468,7 @@ struct caml__roots_block { #define Store_field(block, offset, val) do{ \ mlsize_t caml__temp_offset = (offset); \ value caml__temp_val = (val); \ - caml_modify (&Field ((block), caml__temp_offset), caml__temp_val); \ + caml_modify_field ((block), caml__temp_offset, caml__temp_val); \ }while(0) /* @@ -514,16 +495,20 @@ struct caml__roots_block { #define Begin_roots1(r0) { \ struct caml__roots_block caml__roots_block; \ - caml__roots_block.next = Caml_state_field(local_roots); \ - Caml_state_field(local_roots) = &caml__roots_block; \ + caml_domain_state* domain_state = Caml_state; \ + caml__roots_block.next = domain_state->local_roots; \ + domain_state->local_roots = &caml__roots_block; \ + caml__roots_block.mutexes = 0; \ caml__roots_block.nitems = 1; \ caml__roots_block.ntables = 1; \ caml__roots_block.tables[0] = &(r0); #define Begin_roots2(r0, r1) { \ struct caml__roots_block caml__roots_block; \ - caml__roots_block.next = Caml_state_field(local_roots); \ - Caml_state_field(local_roots) = &caml__roots_block; \ + caml_domain_state* domain_state = Caml_state; \ + caml__roots_block.next = domain_state->local_roots; \ + domain_state->local_roots = &caml__roots_block; \ + caml__roots_block.mutexes = 0; \ caml__roots_block.nitems = 1; \ caml__roots_block.ntables = 2; \ caml__roots_block.tables[0] = &(r0); \ @@ -531,8 +516,10 @@ struct caml__roots_block { #define Begin_roots3(r0, r1, r2) { \ struct caml__roots_block caml__roots_block; \ - caml__roots_block.next = Caml_state_field(local_roots); \ - Caml_state_field(local_roots) = &caml__roots_block; \ + caml_domain_state* domain_state = Caml_state; \ + caml__roots_block.next = domain_state->local_roots; \ + domain_state->local_roots = &caml__roots_block; \ + caml__roots_block.mutexes = 0; \ caml__roots_block.nitems = 1; \ caml__roots_block.ntables = 3; \ caml__roots_block.tables[0] = &(r0); \ @@ -541,8 +528,10 @@ struct caml__roots_block { #define Begin_roots4(r0, r1, r2, r3) { \ struct caml__roots_block caml__roots_block; \ - caml__roots_block.next = Caml_state_field(local_roots); \ - Caml_state_field(local_roots) = &caml__roots_block; \ + caml_domain_state* domain_state = Caml_state; \ + caml__roots_block.next = domain_state->local_roots; \ + domain_state->local_roots = &caml__roots_block; \ + caml__roots_block.mutexes = 0; \ caml__roots_block.nitems = 1; \ caml__roots_block.ntables = 4; \ caml__roots_block.tables[0] = &(r0); \ @@ -552,8 +541,10 @@ struct caml__roots_block { #define Begin_roots5(r0, r1, r2, r3, r4) { \ struct caml__roots_block caml__roots_block; \ - caml__roots_block.next = Caml_state_field(local_roots); \ - Caml_state_field(local_roots) = &caml__roots_block; \ + caml_domain_state* domain_state = Caml_state; \ + caml__roots_block.next = domain_state->local_roots; \ + domain_state->local_roots = &caml__roots_block; \ + caml__roots_block.mutexes = 0; \ caml__roots_block.nitems = 1; \ caml__roots_block.ntables = 5; \ caml__roots_block.tables[0] = &(r0); \ @@ -564,14 +555,37 @@ struct caml__roots_block { #define Begin_roots_block(table, size) { \ struct caml__roots_block caml__roots_block; \ - caml__roots_block.next = Caml_state_field(local_roots); \ - Caml_state_field(local_roots) = &caml__roots_block; \ + caml_domain_state* domain_state = Caml_state; \ + caml__roots_block.next = domain_state->local_roots; \ + domain_state->local_roots = &caml__roots_block; \ + caml__roots_block.mutexes = 0; \ caml__roots_block.nitems = (size); \ caml__roots_block.ntables = 1; \ caml__roots_block.tables[0] = (table); -#define End_roots() Caml_state_field(local_roots) = caml__roots_block.next; } +#define End_roots() CAML_LOCAL_ROOTS = caml__roots_block.next; } + +/* [caml_create_root] creates a new GC root, initialised to the given + value. The value stored in this root may only be read and written + with [caml_read_root] and [caml_modify_root]. */ + +CAMLextern caml_root caml_create_root (value); +CAMLextern caml_root caml_create_root_noexc(value); + +/* [caml_delete_root] deletes a root created by caml_create_root */ + +CAMLextern void caml_delete_root (caml_root); +/* [caml_read_root] loads the value stored in a root */ + +CAMLextern value caml_read_root (caml_root); + +/* [caml_modify_root] stores a new value in a root */ + +CAMLextern void caml_modify_root (caml_root, value); + + +/** Compatability with old C-API **/ /* [caml_register_global_root] registers a global C variable as a memory root for the duration of the program, or until [caml_remove_global_root] is @@ -613,6 +627,7 @@ CAMLextern void caml_remove_generational_global_root (value *); CAMLextern void caml_modify_generational_global_root(value *r, value newval); + #ifdef __cplusplus } #endif diff --git a/runtime/caml/minor_gc.h b/runtime/caml/minor_gc.h index 20baa8d5e2..da7a2b9c63 100644 --- a/runtime/caml/minor_gc.h +++ b/runtime/caml/minor_gc.h @@ -16,23 +16,10 @@ #ifndef CAML_MINOR_GC_H #define CAML_MINOR_GC_H -#include "address_class.h" +#include "misc.h" +#include "addrmap.h" #include "config.h" -/* Global variables moved to Caml_state in 4.10 */ -#define caml_young_start (Caml_state_field(young_start)) -#define caml_young_end (Caml_state_field(young_end)) -#define caml_young_ptr (Caml_state_field(young_ptr)) -#define caml_young_limit (Caml_state_field(young_limit)) -#define caml_young_alloc_start (Caml_state_field(young_alloc_start)) -#define caml_young_alloc_end (Caml_state_field(young_alloc_end)) -#define caml_young_alloc_mid (Caml_state_field(young_alloc_mid)) -#define caml_young_trigger (Caml_state_field(young_trigger)) -#define caml_minor_heap_wsz (Caml_state_field(minor_heap_wsz)) -#define caml_in_minor_collection (Caml_state_field(in_minor_collection)) -#define caml_extra_heap_resources_minor \ - (Caml_state_field(extra_heap_resources_minor)) - #define CAML_TABLE_STRUCT(t) { \ t *base; \ @@ -50,7 +37,6 @@ struct caml_ephe_ref_elt { value ephe; /* an ephemeron in major heap */ mlsize_t offset; /* the offset that points in the minor heap */ }; - struct caml_ephe_ref_table CAML_TABLE_STRUCT(struct caml_ephe_ref_elt); struct caml_custom_elt { @@ -58,52 +44,46 @@ struct caml_custom_elt { mlsize_t mem; /* The parameters for adjusting GC speed. */ mlsize_t max; }; - struct caml_custom_table CAML_TABLE_STRUCT(struct caml_custom_elt); -/* Table of custom blocks in the minor heap that contain finalizers - or GC speed parameters. */ + +struct caml_minor_tables { + struct caml_ref_table major_ref; + struct caml_ephe_ref_table ephe_ref; + struct caml_custom_table custom; +}; + +struct domain; extern void caml_set_minor_heap_size (asize_t); /* size in bytes */ -extern void caml_empty_minor_heap (void); -CAMLextern void caml_gc_dispatch (void); +extern void caml_empty_minor_heap_no_major_slice_from_stw (struct domain* domain, void* unused, int participating_count, struct domain** participating); /* in STW */ +extern int caml_try_stw_empty_minor_heap_on_all_domains(); /* out STW */ +extern void caml_empty_minor_heaps_once(); /* out STW */ CAMLextern void caml_minor_collection (void); -CAMLextern void garbage_collection (void); /* runtime/signals_nat.c */ -extern void caml_oldify_one (value, value *); -extern void caml_oldify_mopup (void); - +CAMLextern void garbage_collection (void); /* def in asmrun/signals.c */ +header_t caml_get_header_val(value v); +void caml_alloc_table (struct caml_ref_table *tbl, asize_t sz, asize_t rsv); extern void caml_realloc_ref_table (struct caml_ref_table *); -extern void caml_alloc_table (struct caml_ref_table *, asize_t, asize_t); extern void caml_realloc_ephe_ref_table (struct caml_ephe_ref_table *); -extern void caml_alloc_ephe_table (struct caml_ephe_ref_table *, - asize_t, asize_t); extern void caml_realloc_custom_table (struct caml_custom_table *); -extern void caml_alloc_custom_table (struct caml_custom_table *, - asize_t, asize_t); -void caml_alloc_minor_tables (void); - -/* Asserts that a word is a valid header for a young object */ -#define CAMLassert_young_header(hd) \ - CAMLassert(Wosize_hd(hd) > 0 && \ - Wosize_hd(hd) <= Max_young_wosize && \ - Color_hd(hd) == 0) - -#define Oldify(p) do{ \ - value __oldify__v__ = *p; \ - if (Is_block (__oldify__v__) && Is_young (__oldify__v__)){ \ - caml_oldify_one (__oldify__v__, (p)); \ - } \ - }while(0) - -Caml_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; -} - -Caml_inline void add_to_ephe_ref_table (struct caml_ephe_ref_table *tbl, +struct caml_minor_tables* caml_alloc_minor_tables(); +void caml_free_minor_tables(struct caml_minor_tables*); +void caml_empty_minor_heap_setup(struct domain* domain); + +#ifdef DEBUG +extern int caml_debug_is_minor(value val); +extern int caml_debug_is_major(value val); +#endif + +#define Ref_table_add(ref_table, x) do { \ + struct caml_ref_table* ref = (ref_table); \ + if (ref->ptr >= ref->limit) { \ + CAMLassert (ref->ptr == ref->limit); \ + caml_realloc_ref_table (ref); \ + } \ + *ref->ptr++ = (x); \ + } while (0) + +static inline void add_to_ephe_ref_table (struct caml_ephe_ref_table *tbl, value ar, mlsize_t offset) { struct caml_ephe_ref_elt *ephe_ref; @@ -117,7 +97,7 @@ Caml_inline void add_to_ephe_ref_table (struct caml_ephe_ref_table *tbl, CAMLassert(ephe_ref->offset < Wosize_val(ephe_ref->ephe)); } -Caml_inline void add_to_custom_table (struct caml_custom_table *tbl, value v, +static inline void add_to_custom_table (struct caml_custom_table *tbl, value v, mlsize_t mem, mlsize_t max) { struct caml_custom_elt *elt; diff --git a/runtime/caml/misc.h b/runtime/caml/misc.h index 4d9ac010a0..5916cd0942 100644 --- a/runtime/caml/misc.h +++ b/runtime/caml/misc.h @@ -29,6 +29,8 @@ #include <stdlib.h> #include <stdarg.h> +#include "camlatomic.h" + /* Basic types and constants */ typedef size_t asize_t; @@ -180,6 +182,40 @@ CAMLnoreturn_end; #define CAMLassert(x) ((void) 0) #endif +#ifndef CAML_AVOID_CONFLICTS +#define Assert CAMLassert +#endif + +#ifdef __GNUC__ +#define CAMLcheckresult __attribute__((warn_unused_result)) +#define CAMLlikely(e) __builtin_expect((e), 1) +#define CAMLunlikely(e) __builtin_expect((e), 0) +#else +#define CAMLcheckresult +#define CAMLlikely(e) (e) +#define CAMLunlikely(e) (e) +#endif + +/* GC status assertions. + + CAMLnoalloc at the start of a block means that the GC must not be + invoked during the block. */ +#if defined(__GNUC__) && defined(DEBUG) +int caml_noalloc_begin(void); +void caml_noalloc_end(int*); +void caml_alloc_point_here(void); +#define CAMLnoalloc \ + int caml__noalloc \ + __attribute__((cleanup(caml_noalloc_end),unused)) \ + = caml_noalloc_begin() +#define CAMLalloc_point_here (caml_alloc_point_here()) +#else +#define CAMLnoalloc +#define CAMLalloc_point_here ((void)0) +#endif + +#define Is_power_of_2(x) (((x) & ((x) - 1)) == 0) + /* This hook is called when a fatal error occurs in the OCaml runtime. It is given arguments to be passed to the [vprintf]-like functions in order to synthetize the error message. @@ -189,12 +225,14 @@ CAMLnoreturn_end; [abort()] is called. */ extern void (*caml_fatal_error_hook) (char *msg, va_list args); -CAMLnoreturn_start CAMLextern void caml_fatal_error (char *, ...) #ifdef __GNUC__ __attribute__ ((format (printf, 1, 2))) #endif CAMLnoreturn_end; +CAMLextern void caml_fatal_error_arg (const char *fmt, const char *arg) Noreturn; +CAMLextern void caml_fatal_error_arg2 (const char *fmt1, const char *arg1, + const char *fmt2, const char *arg2) Noreturn; /* Detection of available C built-in functions, the Clang way. */ @@ -330,8 +368,8 @@ struct ext_table { extern void caml_ext_table_init(struct ext_table * tbl, int init_capa); extern int caml_ext_table_add(struct ext_table * tbl, void * data); -extern void caml_ext_table_remove(struct ext_table * tbl, void * data); extern void caml_ext_table_free(struct ext_table * tbl, int free_entries); +extern void caml_ext_table_remove(struct ext_table * tbl, void * data); extern void caml_ext_table_clear(struct ext_table * tbl, int free_entries); CAMLextern int caml_read_directory(char_os * dirname, @@ -346,7 +384,12 @@ CAMLextern int caml_read_directory(char_os * dirname, /* GC flags and messages */ -extern uintnat caml_verb_gc; +void caml_gc_log (char *, ...) +#ifdef __GNUC__ + __attribute__ ((format (printf, 1, 2))) +#endif +; + void caml_gc_message (int, char *, ...) #ifdef __GNUC__ __attribute__ ((format (printf, 2, 3))) @@ -362,8 +405,12 @@ int caml_runtime_warnings_active(void); #define Debug_tag(x) (INT64_LITERAL(0xD700D7D7D700D6D7u) \ | ((uintnat) (x) << 16) \ | ((uintnat) (x) << 48)) +#define Is_debug_tag(x) \ + (((x) & 0xff00ffffff00fffful) == 0xD700D7D7D700D6D7ul) #else #define Debug_tag(x) (0xD700D6D7ul | ((uintnat) (x) << 16)) +#define Is_debug_tag(x) \ + (((x) & 0xff00fffful) == 0xD700D6D7ul) #endif /* ARCH_SIXTYFOUR */ /* @@ -394,10 +441,6 @@ int caml_runtime_warnings_active(void); #define Debug_uninit_stat 0xD7 -/* Note: the first argument is in fact a [value] but we don't have this - type available yet because we can't include [mlvalues.h] in this file. -*/ -extern void caml_set_fields (intnat v, uintnat, uintnat); #endif /* DEBUG */ diff --git a/runtime/caml/mlvalues.h b/runtime/caml/mlvalues.h index 0cd6fc2d93..fc44c07307 100644 --- a/runtime/caml/mlvalues.h +++ b/runtime/caml/mlvalues.h @@ -22,6 +22,14 @@ #include "config.h" #include "misc.h" +/* Needed here for domain_state */ +typedef intnat value; +typedef atomic_intnat atomic_value; +typedef int32_t opcode_t; +typedef opcode_t * code_t; + +#include "domain_state.h" + #ifdef __cplusplus extern "C" { #endif @@ -57,7 +65,6 @@ extern "C" { This is for use only by the GC. */ -typedef intnat value; typedef uintnat header_t; typedef uintnat mlsize_t; typedef unsigned int tag_t; /* Actually, an unsigned char */ @@ -131,9 +138,8 @@ bits 63 (64-P) (63-P) 10 9 8 7 0 #define Wosize_hd(hd) ((mlsize_t) ((hd) >> 10)) #endif /* WITH_PROFINFO */ -#define Hd_val(val) (((header_t *) (val)) [-1]) /* Also an l-value. */ -#define Hd_op(op) (Hd_val (op)) /* Also an l-value. */ -#define Hd_bp(bp) (Hd_val (bp)) /* Also an l-value. */ +#define Hd_val(val) (((header_t *) (val)) [-1] + 0) +#define Hp_atomic_val(val) ((atomic_uintnat *)(val) - 1) #define Hd_hp(hp) (* ((header_t *) (hp))) /* Also an l-value. */ #define Hp_val(val) (((header_t *) (val)) - 1) #define Hp_op(op) (Hp_val (op)) @@ -194,11 +200,18 @@ bits 63 (64-P) (63-P) 10 9 8 7 0 /* Pointer to the first field. */ #define Op_val(x) ((value *) (x)) +#define Op_atomic_val(x) ((atomic_value *) (x)) /* Fields are numbered from 0. */ #define Field(x, i) (((value *)(x)) [i]) /* Also an l-value. */ -typedef int32_t opcode_t; -typedef opcode_t * code_t; +/* Is_young(val) is true iff val is in the reserved area for minor heaps */ + +#define Is_young(val) \ + (CAMLassert (Is_block (val)), \ + (char *)(val) < (char *)caml_minor_heaps_end && \ + (char *)(val) > (char *)caml_minor_heaps_base) + +#define Is_block_and_young(val) (Is_block(val) && Is_young(val)) /* NOTE: [Forward_tag] and [Infix_tag] must be just under [No_scan_tag], with [Infix_tag] the lower one. @@ -210,7 +223,7 @@ typedef opcode_t * code_t; /* Forward_tag: forwarding pointer that the GC may silently shortcut. See stdlib/lazy.ml. */ #define Forward_tag 250 -#define Forward_val(v) Field(v, 0) +#define Forward_val(v) Field(v, 0) /* FIXME: not immutable once shortcutting is implemented */ /* If tag == Infix_tag : an infix header inside a closure */ /* Infix_tag must be odd so that the infix header is scanned as an integer */ @@ -224,7 +237,7 @@ typedef opcode_t * code_t; /* Another special case: objects */ #define Object_tag 248 #define Class_val(val) Field((val), 0) -#define Oid_val(val) Long_val(Field((val), 1)) +#define Oid_val(val) Long_field((val), 1) CAMLextern value caml_get_public_method (value obj, value tag); /* Called as: caml_callback(caml_get_public_method(obj, caml_hash_variant(name)), obj) */ @@ -232,9 +245,27 @@ CAMLextern value caml_get_public_method (value obj, value tag); Note however that tags being hashed, same tag does not necessarily mean same method name. */ +static inline value Val_ptr(void* p) +{ + CAMLassert(((value)p & 1) == 0); + return (value)p + 1; +} +static inline void* Ptr_val(value val) +{ + CAMLassert(val & 1); + return (void*)(val - 1); +} + +#define Val_pc(pc) Val_ptr(pc) +#define Pc_val(val) ((code_t)Ptr_val(val)) + /* Special case of tuples of fields: closures */ #define Closure_tag 247 -#define Code_val(val) (((code_t *) (val)) [0]) /* Also an l-value. */ + +/* TODO: move fully to the upstream representation of Code_val */ +#define Bytecode_val(val) (Pc_val(val)) +#define Val_bytecode(code) (Val_pc(code)) +#define Code_val(val) Bytecode_val(Field((val), 0)) #define Closinfo_val(val) Field((val), 1) /* Arity and start env */ /* In the closure info field, the top 8 bits are the arity (signed). The low bit is set to one, to look like an integer. @@ -253,10 +284,17 @@ CAMLextern value caml_get_public_method (value obj, value tag); (((uintnat)(arity) << 24) + ((uintnat)(delta) << 1) + 1) #endif -/* This tag is used (with Forward_tag) to implement lazy values. +/* This tag is used (with Forcing_tag & Forward_tag) to implement lazy values. See major_gc.c and stdlib/lazy.ml. */ #define Lazy_tag 246 +/* Tag used for continuations (see fiber.c) */ +#define Cont_tag 245 + +/* This tag is used (with Lazy_tag & Forward_tag) to implement lazy values. + * See major_gc.c and stdlib/lazy.ml. */ +#define Forcing_tag 244 + /* Another special case: variants */ CAMLextern value caml_hash_variant(char const * tag); @@ -355,7 +393,7 @@ CAMLextern int caml_is_double_array (value); /* 0 is false, 1 is true */ the GC; therefore, they must not contain any [value]. See [custom.h] for operations on method suites. */ #define Custom_tag 255 -#define Data_custom_val(v) ((void *) &Field((v), 1)) +#define Data_custom_val(v) ((void *) (Op_val(v) + 1)) struct custom_operations; /* defined in [custom.h] */ /* Int32.t, Int64.t and Nativeint.t are represented as custom blocks. */ @@ -371,8 +409,8 @@ CAMLextern int64_t caml_Int64_val(value v); /* 3- Atoms are 0-tuples. They are statically allocated once and for all. */ -CAMLextern header_t *caml_atom_table; -#define Atom(tag) (Val_hp (&(caml_atom_table [(tag)]))) +CAMLextern value caml_atom(tag_t); +#define Atom(tag) caml_atom(tag) /* Booleans are integers 0 or 1 */ @@ -398,20 +436,20 @@ CAMLextern header_t *caml_atom_table; #define Is_none(v) ((v) == Val_none) #define Is_some(v) Is_block(v) -/* The table of global identifiers */ - -extern value caml_global_data; - CAMLextern value caml_set_oo_id(value obj); -/* Header for out-of-heap blocks. */ +Caml_inline void caml_read_field(value x, intnat i, value* ret) { + value v; + Assert (Hd_val(x)); + /* See Note [MM] in memory.c */ + v = atomic_load_explicit(&Op_atomic_val(x)[i], memory_order_relaxed); + *ret = v; +} + +#define Int_field(x, i) Int_val(Op_val(x)[i]) +#define Long_field(x, i) Long_val(Op_val(x)[i]) +#define Bool_field(x, i) Bool_val(Op_val(x)[i]) -#define Caml_out_of_heap_header(wosize, tag) \ - (/*CAMLassert ((wosize) <= Max_wosize),*/ \ - ((header_t) (((header_t) (wosize) << 10) \ - + (3 << 8) /* matches [Caml_black]. See [gc.h] */ \ - + (tag_t) (tag))) \ - ) #ifdef __cplusplus } diff --git a/runtime/caml/osdeps.h b/runtime/caml/osdeps.h index d41779d3fe..2014160b08 100644 --- a/runtime/caml/osdeps.h +++ b/runtime/caml/osdeps.h @@ -155,6 +155,15 @@ extern int caml_win32_isatty(int fd); #endif /* _WIN32 */ +/* Returns the current value of a counter that increments once per nanosecond. + On systems that support it, this uses a monotonic timesource which ignores + changes in the system time (so that this counter increases by 1000000 each + millisecond, even if the system clock was set back by an hour during that + millisecond). This makes it useful for benchmarking and timeouts, but not + for telling the time. The units are always nanoseconds, but the achieved + resolution may be less. The starting point is unspecified. */ +extern int64_t caml_time_counter(void); + #endif /* CAML_INTERNALS */ #endif /* CAML_OSDEPS_H */ diff --git a/runtime/caml/platform.h b/runtime/caml/platform.h new file mode 100644 index 0000000000..f1c339d00c --- /dev/null +++ b/runtime/caml/platform.h @@ -0,0 +1,174 @@ +#ifndef CAML_PLAT_THREADS_H +#define CAML_PLAT_THREADS_H +/* Platform-specific concurrency and memory primitives */ + +#include <pthread.h> +#include <errno.h> +#include <string.h> +#include "mlvalues.h" + +#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) +#define MAP_ANONYMOUS MAP_ANON +#endif + +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) +#define INLINE static inline +#else +#define INLINE static +#endif + +/* Loads and stores with acquire and release semantics respectively */ + +INLINE void cpu_relax() { +#if defined(__x86_64__) || defined(__i386__) + asm volatile("pause" ::: "memory"); +#elif defined(__aarch64__) + asm volatile ("yield" ::: "memory"); +#else + #warning "cpu_relax() undefined for this architecture!" +#endif +} + +INLINE uintnat atomic_load_acq(atomic_uintnat* p) { + return atomic_load_explicit(p, memory_order_acquire); +} + +INLINE void atomic_store_rel(atomic_uintnat* p, uintnat v) { + atomic_store_explicit(p, v, memory_order_release); +} + +/* Spin-wait loops */ + +#define Max_spins 1000 + +unsigned caml_plat_spin_wait(unsigned spins, + const char* file, int line, + const char* function); + +#define GENSYM_3(name, l) name##l +#define GENSYM_2(name, l) GENSYM_3(name, l) +#define GENSYM(name) GENSYM_2(name, __LINE__) + +#define SPIN_WAIT \ + unsigned GENSYM(caml__spins) = 0; \ + for (; 1; cpu_relax(), \ + GENSYM(caml__spins) = \ + CAMLlikely(GENSYM(caml__spins) < Max_spins) ? \ + GENSYM(caml__spins) + 1 : \ + caml_plat_spin_wait(GENSYM(caml__spins), \ + __FILE__, __LINE__, __func__)) + +INLINE uintnat atomic_load_wait_nonzero(atomic_uintnat* p) { + SPIN_WAIT { + uintnat v = atomic_load_acq(p); + if (v) return v; + } +} + +/* Atomic read-modify-write instructions, with full fences */ + +INLINE uintnat atomic_fetch_add_verify_ge0(atomic_uintnat* p, uintnat v) { + uintnat result = atomic_fetch_add(p,v); + CAMLassert ((intnat)result > 0); + return result; +} + + +typedef pthread_mutex_t caml_plat_mutex; +#define CAML_PLAT_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +void caml_plat_mutex_init(caml_plat_mutex*); +static inline void caml_plat_lock(caml_plat_mutex*); +static inline int caml_plat_try_lock(caml_plat_mutex*); +void caml_plat_assert_locked(caml_plat_mutex*); +void caml_plat_assert_all_locks_unlocked(); +static inline void caml_plat_unlock(caml_plat_mutex*); +void caml_plat_mutex_free(caml_plat_mutex*); +typedef struct { pthread_cond_t cond; caml_plat_mutex* mutex; } caml_plat_cond; +#define CAML_PLAT_COND_INITIALIZER(m) { PTHREAD_COND_INITIALIZER, m } +void caml_plat_cond_init(caml_plat_cond*, caml_plat_mutex*); +void caml_plat_cond_init_no_mutex(caml_plat_cond* cond); +void caml_plat_cond_set_mutex(caml_plat_cond *cond, caml_plat_mutex* m); +void caml_plat_wait(caml_plat_cond*); +/* like caml_plat_wait, but if caml_time_counter() surpasses the second parameter + without a signal, then this function returns 1. */ +int caml_plat_timedwait(caml_plat_cond*, int64_t); +void caml_plat_broadcast(caml_plat_cond*); +void caml_plat_signal(caml_plat_cond*); +void caml_plat_cond_free(caml_plat_cond*); + +struct caml__mutex_unwind { + caml_plat_mutex* mutex; + struct caml__mutex_unwind* next; +}; + +#define With_mutex(mutex0, BODY) do { \ + struct caml__mutex_unwind caml__locked_mutex; \ + caml_plat_mutex* caml__mutex = (mutex0); \ + int caml__mutex_go = 1; \ + Assert(CAML_LOCAL_ROOTS); \ + caml__locked_mutex.mutex = caml__mutex; \ + caml__locked_mutex.next = CAML_LOCAL_ROOTS->mutexes; \ + CAML_LOCAL_ROOTS->mutexes = &caml__locked_mutex; \ + for (caml_plat_try_lock(caml__mutex) || \ + ((caml_enter_blocking_section(), \ + caml_plat_lock(caml__mutex), \ + caml_leave_blocking_section()), 0); \ + caml__mutex_go; \ + caml_plat_unlock(caml__mutex), \ + caml__mutex_go = 0, \ + CAML_LOCAL_ROOTS->mutexes = \ + CAML_LOCAL_ROOTS->mutexes->next) \ + { BODY } \ + } while(0) + +/* Memory management primitives (mmap) */ + +uintnat caml_mem_round_up_pages(uintnat size); +void* caml_mem_map(uintnat size, uintnat alignment, int reserve_only); +void* caml_mem_commit(void* mem, uintnat size); +void caml_mem_decommit(void* mem, uintnat size); +void caml_mem_unmap(void* mem, uintnat size); + + +static inline void check_err(char* action, int err) +{ + if (err) { + caml_fatal_error_arg2("Fatal error during %s", action, ": %s\n", strerror(err)); + } +} + +#ifdef DEBUG +static __thread int lockdepth; +#define DEBUG_LOCK(m) (lockdepth++) +#define DEBUG_UNLOCK(m) (lockdepth--) +#else +#define DEBUG_LOCK(m) +#define DEBUG_UNLOCK(m) +#endif + +static inline void caml_plat_lock(caml_plat_mutex* m) +{ + check_err("lock", pthread_mutex_lock(m)); + DEBUG_LOCK(m); +} + +static inline int caml_plat_try_lock(caml_plat_mutex* m) +{ + int r = pthread_mutex_trylock(m); + if (r == EBUSY) { + return 0; + } else { + check_err("try_lock", r); + DEBUG_LOCK(m); + return 1; + } +} + +static inline void caml_plat_unlock(caml_plat_mutex* m) +{ + DEBUG_UNLOCK(m); + check_err("unlock", pthread_mutex_unlock(m)); +} + + +#endif /* CAML_PLATFORM_H */ diff --git a/runtime/caml/printexc.h b/runtime/caml/printexc.h index 92c5af5368..dcfd0d8e90 100644 --- a/runtime/caml/printexc.h +++ b/runtime/caml/printexc.h @@ -16,7 +16,6 @@ #ifndef CAML_PRINTEXC_H #define CAML_PRINTEXC_H - #include "misc.h" #include "mlvalues.h" @@ -26,7 +25,7 @@ extern "C" { CAMLextern char * caml_format_exception (value); -CAMLnoreturn_start void caml_fatal_uncaught_exception (value) CAMLnoreturn_end; +void caml_fatal_uncaught_exception (value) Noreturn; #ifdef __cplusplus } diff --git a/runtime/caml/roots.h b/runtime/caml/roots.h index 755aa8a7ef..910c63c60a 100644 --- a/runtime/caml/roots.h +++ b/runtime/caml/roots.h @@ -21,23 +21,15 @@ #include "misc.h" #include "memory.h" -typedef void (*scanning_action) (value, value *); - -void caml_oldify_local_roots (void); -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 *); -#else -CAMLextern void caml_do_local_roots(scanning_action f, char * c_bottom_of_stack, - uintnat last_retaddr, value * v_gc_regs, - struct caml__roots_block * gc_local_roots); -#endif - -CAMLextern void (*caml_scan_roots_hook) (scanning_action); +typedef void (*scanning_action) (void*, value, value *); +CAMLextern void (*caml_scan_roots_hook)(scanning_action, void*, struct domain*); + +void caml_do_roots (scanning_action f, void* data, struct domain* d, + int do_final_val); +void caml_do_local_roots(scanning_action f, void* data, + struct caml__roots_block* local_roots, + struct stack_info *current_stack, + value * v_gc_regs); #endif /* CAML_INTERNALS */ diff --git a/runtime/caml/s.h.in b/runtime/caml/s.h.in index 6b1be03234..9f4049386e 100644 --- a/runtime/caml/s.h.in +++ b/runtime/caml/s.h.in @@ -62,6 +62,10 @@ #undef HAS_ISSETUGID +#undef HAS_STDATOMIC_H + +#undef COLLECT_STATS + /* 2. For the Unix library. */ #undef HAS_SOCKETS diff --git a/runtime/caml/shared_heap.h b/runtime/caml/shared_heap.h new file mode 100644 index 0000000000..d78c334d18 --- /dev/null +++ b/runtime/caml/shared_heap.h @@ -0,0 +1,87 @@ +#ifndef CAML_SHARED_HEAP_H +#define CAML_SHARED_HEAP_H + +#ifdef CAML_INTERNALS + +#include "config.h" +#include "roots.h" +#include "domain.h" +#include "misc.h" + +struct caml_heap_state; +struct pool; + +struct caml_heap_state* caml_init_shared_heap(); +void caml_teardown_shared_heap(struct caml_heap_state* heap); + +value* caml_shared_try_alloc(struct caml_heap_state*, mlsize_t wosize, tag_t tag, int is_pinned); + +void caml_sample_heap_stats(struct caml_heap_state*, struct heap_stats*); + +uintnat caml_heap_size(struct caml_heap_state*); +uintnat caml_top_heap_words(struct caml_heap_state*); +uintnat caml_heap_blocks(struct caml_heap_state*); + +struct pool* caml_pool_of_shared_block(value v); +struct domain* caml_owner_of_shared_block(value v); + +void caml_shared_unpin(value v); + +/* always readable by all threads + written only by a single thread during STW periods */ +typedef uintnat status; +struct global_heap_state { + status MARKED, UNMARKED, GARBAGE; +}; +extern struct global_heap_state global; + +/* CR mshinwell: ensure this matches [Emitaux] */ +enum {NOT_MARKABLE = 3 << 8}; + +static inline int Has_status_hd(header_t hd, status s) { + return (hd & (3 << 8)) == s; +} + +static inline header_t With_status_hd(header_t hd, status s) { + return (hd & ~(3 << 8)) | s; +} + +static inline int is_garbage(value v) { + return Has_status_hd(Hd_val(v), global.GARBAGE); +} + +static inline int is_unmarked(value v) { + return Has_status_hd(Hd_val(v), global.UNMARKED); +} + +static inline int is_marked(value v) { + return Has_status_hd(Hd_val(v), global.MARKED); +} + +void caml_redarken_pool(struct pool*, scanning_action, void*); + +intnat caml_sweep(struct caml_heap_state*, intnat); + + +/* must be called during STW */ +void caml_cycle_heap_stw(void); + +/* must be called on each domain + (after caml_cycle_heap_stw) */ +void caml_cycle_heap(struct caml_heap_state*); + +/* Heap invariant verification (for debugging) */ + +/* caml_verify_begin must only be called while all domains are paused */ +struct heap_verify_state* caml_verify_begin(); +void caml_verify_root(void*, value, value*); +void caml_verify_heap(struct heap_verify_state*); /* deallocates arg */ + +#ifdef DEBUG +/* [is_garbage(v)] returns true if [v] is a garbage value */ +int is_garbage (value); +#endif + +#endif /* CAML_INTERNALS */ + +#endif /* CAML_SHARED_HEAP_H */ diff --git a/runtime/caml/signals.h b/runtime/caml/signals.h index 7ec1ad3ba1..a9c769918a 100644 --- a/runtime/caml/signals.h +++ b/runtime/caml/signals.h @@ -16,10 +16,6 @@ #ifndef CAML_SIGNALS_H #define CAML_SIGNALS_H -#if defined(CAML_INTERNALS) && defined(POSIX_SIGNALS) -#include<signal.h> -#endif - #ifndef CAML_NAME_SPACE #include "compatibility.h" #endif @@ -30,68 +26,31 @@ extern "C" { #endif -CAMLextern void caml_enter_blocking_section (void); -CAMLextern void caml_leave_blocking_section (void); - -CAMLextern void caml_process_pending_actions (void); -/* Checks for pending actions and executes them. This includes pending - minor and major collections, signal handlers, finalisers, and - Memprof callbacks. Assumes that the runtime lock is held. Can raise - exceptions asynchronously into OCaml code. */ - -CAMLextern value caml_process_pending_actions_exn (void); -/* Same as [caml_process_pending_actions], but returns the exception - if any (otherwise returns [Val_unit]). */ - #ifdef CAML_INTERNALS +CAMLextern intnat volatile caml_signals_are_pending; CAMLextern intnat volatile caml_pending_signals[]; - -/* When an action is pending, either [caml_something_to_do] is 1, or - there is a function currently running which will end by either - executing all actions, or set [caml_something_to_do] back to 1. We - set it to 0 when starting executing all callbacks. - - In the case there are two different callbacks (say, a signal and a - finaliser) arriving at the same time, then the processing of one - awaits the return of the other. In case of long-running callbacks, - we may want to run the second one without waiting the end of the - first one. We do this by provoking an additional polling every - minor collection and every major slice. To guarantee a low latency - for signals, we avoid delaying signal handlers in that case by - calling them first. - - FIXME: We could get into caml_process_pending_actions when - caml_something_to_do is seen as set but not caml_pending_signals, - making us miss the signal. -*/ CAMLextern int volatile caml_something_to_do; +int caml_init_signal_stack(void); +void caml_free_signal_stack(void); +void caml_init_signal_handling(void); +/* </private> */ -/* Global variables moved to Caml_state in 4.10 */ -#define caml_requested_major_slice (Caml_state_field(requested_major_slice)) -#define caml_requested_minor_gc (Caml_state_field(requested_minor_gc)) +CAMLextern void caml_enter_blocking_section (void); +CAMLextern void caml_leave_blocking_section (void); -void caml_update_young_limit(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); -value caml_execute_signal_exn(int signal_number, int in_signal_handler); void caml_record_signal(int signal_number); -value caml_process_pending_signals_exn(void); -void caml_set_action_pending (void); -value caml_do_pending_actions_exn (void); -value caml_process_pending_actions_with_root (value extra_root); // raises +void caml_process_pending_signals(void); int caml_set_signal_action(int signo, int action); -void caml_setup_stack_overflow_detection(void); -CAMLextern void (*caml_enter_blocking_section_hook)(void); -CAMLextern void (*caml_leave_blocking_section_hook)(void); -CAMLextern int (*caml_try_leave_blocking_section_hook)(void); -#ifdef POSIX_SIGNALS -CAMLextern int (*caml_sigmask_hook)(int, const sigset_t *, sigset_t *); -#endif + +CAMLextern void (* volatile caml_async_action_hook)(void); #endif /* CAML_INTERNALS */ +CAMLextern void caml_enter_blocking_section (void); +CAMLextern void caml_leave_blocking_section (void); + #ifdef __cplusplus } #endif diff --git a/runtime/caml/sizeclasses.h b/runtime/caml/sizeclasses.h new file mode 100644 index 0000000000..548f207161 --- /dev/null +++ b/runtime/caml/sizeclasses.h @@ -0,0 +1,18 @@ +#define POOL_WSIZE 4096 +#define POOL_HEADER_WSIZE 4 +#define SIZECLASS_MAX 128 +#define NUM_SIZECLASSES 32 +static const unsigned int wsize_sizeclass[NUM_SIZECLASSES] = +{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 23, 26, 29, 33, 37, 42, + 47, 53, 59, 65, 73, 81, 89, 99, 108, 118, 128 }; +static const unsigned char wastage_sizeclass[NUM_SIZECLASSES] = +{ 0, 0, 0, 0, 2, 0, 4, 4, 6, 2, 0, 4, 12, 6, 12, 21, 10, 3, 0, 22, 18, 3, 11, + 21, 62, 4, 42, 87, 33, 96, 80, 124 }; +static const unsigned char sizeclass_wsize[SIZECLASS_MAX + 1] = +{ 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, + 15, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, + 20, 20, 20, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, + 23, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, + 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }; diff --git a/runtime/caml/stack.h b/runtime/caml/stack.h index 6b7df0e670..85d9b391e1 100644 --- a/runtime/caml/stack.h +++ b/runtime/caml/stack.h @@ -25,9 +25,9 @@ #ifdef TARGET_i386 #define Saved_return_address(sp) *((intnat *)((sp) - 4)) #ifndef SYS_win32 -#define Callback_link(sp) ((struct caml_context *)((sp) + 16)) +#define Callback_link(sp) ((struct caml_context *)((sp) + 16)) //FIXME KC #else -#define Callback_link(sp) ((struct caml_context *)((sp) + 8)) +#define Callback_link(sp) ((struct caml_context *)((sp) + 8)) //FIXME KC #endif #endif @@ -52,22 +52,23 @@ #ifdef TARGET_s390x #define Saved_return_address(sp) *((intnat *)((sp) - SIZEOF_PTR)) #define Trap_frame_size 16 -#define Callback_link(sp) ((struct caml_context *)((sp) + Trap_frame_size)) +#define Callback_link(sp) ((struct caml_context *)((sp) + Trap_frame_size)) //FIXME KC #endif #ifdef TARGET_arm #define Saved_return_address(sp) *((intnat *)((sp) - 4)) -#define Callback_link(sp) ((struct caml_context *)((sp) + 8)) +#define Callback_link(sp) ((struct caml_context *)((sp) + 8)) //FIXME KC #endif #ifdef TARGET_amd64 +/* Size of the gc_regs structure, in words. See amd64.S and amd64/proc.ml for the indices */ +#define Wosize_gc_regs (13 /* int regs */ + 16 /* float regs */) #define Saved_return_address(sp) *((intnat *)((sp) - 8)) -#define Callback_link(sp) ((struct caml_context *)((sp) + 16)) #endif #ifdef TARGET_arm64 #define Saved_return_address(sp) *((intnat *)((sp) - 8)) -#define Callback_link(sp) ((struct caml_context *)((sp) + 16)) +#define Context_needs_padding /* keep stack 16-byte aligned */ #endif #ifdef TARGET_riscv @@ -78,72 +79,16 @@ /* Structure of OCaml callback contexts */ struct caml_context { - char * bottom_of_stack; /* beginning of OCaml stack chunk */ - uintnat last_retaddr; /* last return address in OCaml code */ + uintnat exception_ptr; /* exception pointer */ value * gc_regs; /* pointer to register block */ -#ifdef WITH_SPACETIME - void* trie_node; +#ifdef Context_needs_padding + value padding; #endif }; -/* Structure of frame descriptors */ - -typedef struct { - uintnat retaddr; - unsigned short frame_size; - unsigned short num_live; - unsigned short live_ofs[1 /* num_live */]; - /* - If frame_size & 2, then allocation info follows: - unsigned char num_allocs; - unsigned char alloc_lengths[num_alloc]; - - If frame_size & 1, then debug info follows: - uint32_t debug_info_offset[num_debug]; - - Debug info is stored as relative offsets to debuginfo structures. - num_debug is num_alloc if frame_size & 2, otherwise 1. */ -} frame_descr; - -/* Allocation lengths are encoded as 0-255, giving sizes 1-256 */ -#define Wosize_encoded_alloc_len(n) ((uintnat)(n) + 1) - -/* Used to compute offsets in frame tables. - ty must have power-of-2 size */ -#define Align_to(p, ty) \ - (void*)(((uintnat)(p) + sizeof(ty) - 1) & -sizeof(ty)) - - -/* Hash table of frame descriptors */ - -extern frame_descr ** caml_frame_descriptors; -extern uintnat caml_frame_descriptors_mask; - -#define Hash_retaddr(addr) \ - (((uintnat)(addr) >> 3) & caml_frame_descriptors_mask) - -extern void caml_init_frame_descriptors(void); -extern void caml_register_frametable(intnat *); -extern void caml_unregister_frametable(intnat *); -extern void caml_register_dyn_global(void *); - -extern uintnat caml_stack_usage (void); -extern uintnat (*caml_stack_usage_hook)(void); - /* Declaration of variables used in the asm code */ extern value * caml_globals[]; -extern char caml_globals_map[]; extern intnat caml_globals_inited; -extern intnat * caml_frametable[]; - -/* Global variables moved to Caml_state in 4.10 */ -#define caml_top_of_stack (Caml_state_field(top_of_stack)) -#define caml_bottom_of_stack (Caml_state_field(bottom_of_stack)) -#define caml_last_return_address (Caml_state_field(last_return_address)) -#define caml_gc_regs (Caml_state_field(gc_regs)) -#define caml_exception_pointer (Caml_state_field(exception_pointer)) - -CAMLextern frame_descr * caml_next_frame_descriptor(uintnat * pc, char ** sp); #endif /* CAML_INTERNALS */ diff --git a/runtime/caml/stacks.h b/runtime/caml/stacks.h deleted file mode 100644 index d309141f9b..0000000000 --- a/runtime/caml/stacks.h +++ /dev/null @@ -1,47 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* structure of the stacks */ - -#ifndef CAML_STACKS_H -#define CAML_STACKS_H - -#ifdef CAML_INTERNALS - -#include "misc.h" -#include "mlvalues.h" -#include "memory.h" - -/* Global variables moved to Caml_state in 4.10 */ -#define caml_stack_low (Caml_state_field(stack_low)) -#define caml_stack_high (Caml_state_field(stack_high)) -#define caml_stack_threshold (Caml_state_field(stack_threshold)) -#define caml_extern_sp (Caml_state_field(extern_sp)) -#define caml_trapsp (Caml_state_field(trapsp)) -#define caml_trap_barrier (Caml_state_field(trap_barrier)) - -#define Trap_pc(tp) (((code_t *)(tp))[0]) -#define Trap_link_offset(tp) (((value *)(tp))[1]) - -void caml_init_stack (uintnat init_max_size); -void caml_realloc_stack (asize_t required_size); -void caml_change_max_stack_size (uintnat new_max_size); -uintnat caml_stack_usage (void); - -CAMLextern uintnat (*caml_stack_usage_hook)(void); - -#endif /* CAML_INTERNALS */ - -#endif /* CAML_STACKS_H */ diff --git a/runtime/caml/startup.h b/runtime/caml/startup.h index abbcd596d2..41886bfed8 100644 --- a/runtime/caml/startup.h +++ b/runtime/caml/startup.h @@ -20,6 +20,7 @@ #include "mlvalues.h" #include "exec.h" +#include "startup_aux.h" CAMLextern void caml_main(char_os **argv); diff --git a/runtime/caml/startup_aux.h b/runtime/caml/startup_aux.h index 77ced69fa0..a5768d4e56 100644 --- a/runtime/caml/startup_aux.h +++ b/runtime/caml/startup_aux.h @@ -23,28 +23,55 @@ extern void caml_init_locale(void); extern void caml_free_locale(void); -extern void caml_init_atom_table (void); - -extern uintnat caml_init_percent_free; -extern uintnat caml_init_max_percent_free; -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_init_custom_major_ratio; -extern uintnat caml_init_custom_minor_ratio; -extern uintnat caml_init_custom_minor_max_bsz; -extern uintnat caml_trace_level; -extern int caml_cleanup_on_exit; +/* readonly after startup */ +struct caml_params { + const char* exe_name; + + /* for meta.c */ + const char* section_table; + asize_t section_table_size; + + const char* cds_file; + + uintnat verb_gc; + uintnat parser_trace; + uintnat trace_level; + uintnat eventlog_enabled; + uintnat verify_heap; + uintnat print_stats; + + uintnat init_percent_free; + uintnat init_max_percent_free; + uintnat init_minor_heap_wsz; + uintnat init_heap_chunk_sz; + uintnat init_heap_wsz; + uintnat init_custom_major_ratio; + uintnat init_custom_minor_ratio; + uintnat init_custom_minor_max_bsz; + + uintnat init_max_stack_wsz; + uintnat init_fiber_wsz; + + uintnat backtrace_enabled_init; + uintnat runtime_warnings; + uintnat cleanup_on_exit; +}; + +extern const struct caml_params* const caml_params; extern void caml_parse_ocamlrunparam (void); +extern int caml_parse_command_line (char_os **argv); /* Common entry point to caml_startup. Returns 0 if the runtime is already initialized. If [pooling] is 0, [caml_stat_*] functions will not be backed by a pool. */ extern int caml_startup_aux (int pooling); +void caml_init_exe_name(const char* exe_name); +void caml_init_section_table(const char* section_table, + asize_t section_table_size); +value caml_maybe_print_stats (value v); + #endif /* CAML_INTERNALS */ #endif /* CAML_STARTUP_AUX_H */ diff --git a/runtime/caml/sys.h b/runtime/caml/sys.h index 39e24c57cc..18c135ed10 100644 --- a/runtime/caml/sys.h +++ b/runtime/caml/sys.h @@ -12,7 +12,6 @@ /* special exception on linking described in the file LICENSE. */ /* */ /**************************************************************************/ - #ifndef CAML_SYS_H #define CAML_SYS_H @@ -44,8 +43,6 @@ CAMLnoreturn_end; extern double caml_sys_time_unboxed(value); CAMLextern value caml_sys_get_argv(value unit); -extern char_os * caml_exe_name; - #ifdef __cplusplus } #endif diff --git a/runtime/caml/ui.h b/runtime/caml/ui.h index 3047ba7fb7..2958465038 100644 --- a/runtime/caml/ui.h +++ b/runtime/caml/ui.h @@ -1,25 +1,21 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ +/***********************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 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. */ +/* */ +/***********************************************************************/ /* Function declarations for non-Unix user interfaces */ #ifndef CAML_UI_H #define CAML_UI_H -#ifdef CAML_INTERNALS - #include "config.h" void ui_exit (int return_code); @@ -27,6 +23,4 @@ int ui_read (int file_desc, char *buf, unsigned int length); int ui_write (int file_desc, char *buf, unsigned int length); void ui_print_stderr (char *format, void *arg); -#endif /* CAML_INTERNALS */ - #endif /* CAML_UI_H */ diff --git a/runtime/caml/weak.h b/runtime/caml/weak.h index df35fac96a..b618b79b08 100644 --- a/runtime/caml/weak.h +++ b/runtime/caml/weak.h @@ -1,147 +1,45 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1997 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ +/***********************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Damien Doligez, projet Para, INRIA Rocquencourt */ +/* */ +/* Copyright 1997 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. */ +/* */ +/***********************************************************************/ /* Operations on weak arrays */ #ifndef CAML_WEAK_H #define CAML_WEAK_H +#ifdef CAML_INTERNALS + #include "mlvalues.h" #include "memory.h" #ifdef __cplusplus extern "C" { #endif - -/** The requirements of the functions must be satisfied, it is - unspecified what happens if they are not. The debugging runtime - could check some of them. */ - -CAMLextern value caml_ephemeron_create(mlsize_t len); -/** Create an ephemeron with the given number of keys. - This function allocates. - */ - -CAMLextern mlsize_t caml_ephemeron_num_keys(value eph); -/** Return the number of key in the ephemeron. The valid key offset goes - from [0] to the predecessor of the returned value. */ - -CAMLextern int caml_ephemeron_key_is_set(value eph, mlsize_t offset); -/** Return 1 if the key in the ephemeron at the given offset is set. - Otherwise 0. The value [eph] must be an ephemeron and [offset] a - valid key offset. -*/ - -CAMLextern void caml_ephemeron_set_key(value eph, mlsize_t offset, value k); -/** Set the key of the given ephemeron [eph] at the given offset - [offset] to the given value [k]. The value [eph] must be an - ephemeron, [offset] a valid key offset and [k] a block. -*/ - -CAMLextern void caml_ephemeron_unset_key(value eph, mlsize_t offset); -/** Unset the key of the given ephemeron at the given offset. The - value [eph] must be an ephemeron and [offset] a valid key offset. -*/ - -CAMLextern int caml_ephemeron_get_key(value eph, mlsize_t offset, value *key); -/** Return 1 if the key in the ephemeron at the given offset is set. - Otherwise 0. When returning 1, set [*key] to the pointed value. - - The value [eph] must be an ephemeron and [offset] a valid key - offset. -*/ - -CAMLextern int caml_ephemeron_get_key_copy(value eph, mlsize_t offset, - value *key); -/** Return 1 if the key in the ephemeron at the given offset is set. - Otherwise 0. When returning 1, set [*key] to a shallow copy of the - key. This function allocates. - - The value [eph] must be an ephemeron and [offset] a valid key - offset. -*/ - -CAMLextern void caml_ephemeron_blit_key(value eph1, mlsize_t off1, - value eph2, mlsize_t off2, - mlsize_t len); -/** Fill the given range of keys of [eph2] with the given range of - keys of [eph1]. Contrary to using caml_ephemeron_get_key followed - by caml_ephemeron_set_key or caml_ephemeron_unset_key, this - function does not prevent the incremental GC from erasing the - value in its current cycle. The value [eph1] (resp. [eph2]) must - be an ephemeron and the offsets between [off1] and [off1+len] - (resp. between [off2] and [off2+offset]) must be valid keys of - [eph1] (resp. [eph2]). -*/ - -CAMLextern int caml_ephemeron_data_is_set(value eph); -/** Return 1 if the data in the ephemeron is set. - Otherwise 0. The value [eph] must be an ephemeron. -*/ - -CAMLextern void caml_ephemeron_set_data(value eph, value k); -/** Set the data of the given ephemeron [eph] to the given value - [k]. The value [eph] must be an ephemeron and [k] a block. -*/ - -CAMLextern void caml_ephemeron_unset_data(value eph); -/** Unset the data of the given ephemeron. The value [eph] must be an - ephemeron. -*/ - -CAMLextern int caml_ephemeron_get_data(value eph, value *data); -/** Return 1 if the data in the ephemeron at the given offset is set. - Otherwise 0. When returning 1, set [*data] to the pointed value. - - The value [eph] must be an ephemeron and [offset] a valid key - offset. -*/ - -CAMLextern int caml_ephemeron_get_data_copy(value eph, value *data); -/** Return 1 if the data in the ephemeron at the given offset is set. - Otherwise 0. When returning 1, set [*data] to a shallow copy of - the data. This function allocates. - - The value [eph] must be an ephemeron and [offset] a valid key - offset. -*/ - -CAMLextern void caml_ephemeron_blit_data(value eph1, value eph2); -/** Sets the data of [eph2] to be the same as the data of [eph1]. - Contrary to using caml_ephemeron_get_data followed by - caml_ephemeron_set_data or caml_ephemeron_unset_data, this - function does not prevent the incremental GC from erasing the - value in its current cycle. The values [eph1] and [eph2] must be - ephemerons. -*/ - - -#define caml_weak_array_length caml_ephemeron_num_keys -#define caml_weak_array_create caml_ephemeron_create -#define caml_weak_array_check caml_ephemeron_key_is_set -#define caml_weak_array_unset caml_ephemeron_unset_key -#define caml_weak_array_set caml_ephemeron_set_key -#define caml_weak_array_get caml_ephemeron_get_key -#define caml_weak_array_get_copy caml_ephemeron_get_key_copy -#define caml_weak_array_blit caml_ephemeron_blit_key - -#ifdef CAML_INTERNALS - -extern value caml_ephe_list_head; extern value caml_ephe_none; +struct caml_ephe_info { + value todo; /* These are ephemerons which need to be marked and swept in the + current cycle. If the ephemeron is alive, after marking, they + go into the live list. */ + value live; /* These are ephemerons which are alive in the current cycle. + They still need to be swept to get rid of dead keys and + values. Invariant: No keys are unreachable for these + ephemerons. */ + uintnat cycle; + struct { + value* todop; + uintnat cycle; + } cursor; +}; /** The first field 0: weak list; second field 1: data; @@ -159,68 +57,11 @@ extern value caml_ephe_none; #define CAML_EPHE_FIRST_KEY 2 #define CAML_EPHE_MAX_WOSIZE (Max_wosize - CAML_EPHE_FIRST_KEY) -/* In the header, in order to let major_gc.c - and weak.c see the body of the function */ -Caml_inline void caml_ephe_clean_partial (value v, - mlsize_t offset_start, - mlsize_t offset_end) { - value child; - int release_data = 0; - mlsize_t i; - CAMLassert(caml_gc_phase == Phase_clean); - CAMLassert(2 <= offset_start - && offset_start <= offset_end - && offset_end <= Wosize_hd (Hd_val(v))); - - for (i = offset_start; i < offset_end; i++){ - child = Field (v, i); - ephemeron_again: - if (child != caml_ephe_none - && Is_block (child) && Is_in_value_area (child)){ - if (Tag_val (child) == Forward_tag){ - value f = Forward_val (child); - if (Is_block (f)) { - if (!Is_in_value_area(f) || Tag_val (f) == Forward_tag - || Tag_val (f) == Lazy_tag || Tag_val (f) == Double_tag){ - /* Do not short-circuit the pointer. */ - }else{ - Field (v, i) = child = f; - if (Is_block (f) && Is_young (f)) - add_to_ephe_ref_table(Caml_state_field(ephe_ref_table), v, i); - goto ephemeron_again; - } - } - } - if (Is_white_val (child) && !Is_young (child)){ - release_data = 1; - Field (v, i) = caml_ephe_none; - } - } - } - - child = Field (v, 1); - if(child != caml_ephe_none){ - if (release_data){ - Field (v, 1) = caml_ephe_none; - } else { - /* If we scanned all the keys and the data field remains filled, - then the mark phase must have marked it */ - CAMLassert( !(offset_start == 2 && offset_end == Wosize_hd (Hd_val(v)) - && Is_block (child) && Is_in_heap (child) - && Is_white_val (child))); - } - } -} - -Caml_inline void caml_ephe_clean (value v) { - mlsize_t size; - header_t hd; - hd = Hd_val (v); - size = Wosize_hd (hd); - - caml_ephe_clean_partial(v, 2, size); -} +#define Ephe_link(e) (*(Op_val(e) + CAML_EPHE_LINK_OFFSET)) +#define Ephe_data(e) (*(Op_val(e) + CAML_EPHE_DATA_OFFSET)) +struct caml_ephe_info* caml_alloc_ephe_info (void); +void caml_ephe_clean(value e); #endif /* CAML_INTERNALS */ diff --git a/runtime/compact.c b/runtime/compact.c deleted file mode 100644 index ff793da666..0000000000 --- a/runtime/compact.c +++ /dev/null @@ -1,518 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -#include <string.h> - -#include "caml/address_class.h" -#include "caml/config.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/mlvalues.h" -#include "caml/roots.h" -#include "caml/weak.h" -#include "caml/compact.h" -#include "caml/memprof.h" -#include "caml/eventlog.h" - -extern uintnat caml_percent_free; /* major_gc.c */ -extern void caml_shrink_heap (char *); /* memory.c */ - -/* Colors - - We use the GC's color bits in the following way: - - - White words are headers of live blocks. - - Blue words are headers of free blocks. - - Black words are headers of out-of-heap "blocks". - - Gray words are the encoding of pointers in inverted lists. - - Encoded pointers: - Pointers always have their two low-order bits clear. We make use of - this to encode pointers by shifting bits 2-9 to 0-7: - ...XXXyyyyyyyy00 becomes ...XXX01yyyyyyyy - Note that 01 corresponds to the "gray" color of the GC, so we can now - mix pointers and headers because there are no gray headers anywhere in - the heap (or outside) when we start a compaction (which must be done at - the end of a sweep phase). -*/ - -typedef uintnat word; - -#define eptr(p) \ - (((word) (p) & ~0x3FF) | ((((word) p) & 0x3FF) >> 2) | Caml_gray) -#define dptr(p) ((word *) (((word) (p) & ~0x3FF) | ((((word) p) & 0xFF) << 2))) - -static void invert_pointer_at (word *p) -{ - word q = *p; - header_t h; - - CAMLassert (((uintnat) p & 3) == 0); - - if (Is_block (q) && Is_in_value_area (q)){ - h = Hd_val (q); - switch (Color_hd (h)){ - case Caml_white: - if (Tag_hd (h) == Infix_tag){ - value realvalue = (value) q - Infix_offset_val (q); - if (Is_black_val (realvalue)) break; - } - /* FALL THROUGH */ - case Caml_gray: - CAMLassert (Is_in_heap (q)); - /* [q] points to some inverted list, insert it. */ - *p = h; - Hd_val (q) = eptr (p); - break; - case Caml_black: - /* [q] points to an out-of-heap value. Leave it alone. */ - break; - default: /* Caml_blue */ - /* We found a pointer to a free block. This cannot happen. */ - CAMLassert (0); - break; - } - } -} - -void caml_invert_root (value v, value *p) -{ -#ifdef NO_NAKED_POINTERS - /* Note: this assertion will become tautological and should be removed when - we finally get rid of the page table in NNP mode. - */ - CAMLassert (Is_long (*p) || Is_in_heap (*p) || Is_black_val (*p) - || Tag_val (*p) == Infix_tag); -#endif - invert_pointer_at ((word *) p); -} - -static char *compact_fl; - -static void init_compact_allocate (void) -{ - char *ch = caml_heap_start; - while (ch != NULL){ - Chunk_alloc (ch) = 0; - ch = Chunk_next (ch); - } - compact_fl = caml_heap_start; -} - -/* [size] is a number of bytes and includes the header size */ -static char *compact_allocate (mlsize_t size) -{ - char *chunk, *adr; - - while (Chunk_size (compact_fl) - Chunk_alloc (compact_fl) <= Bhsize_wosize (3) - && Chunk_size (Chunk_next (compact_fl)) - - Chunk_alloc (Chunk_next (compact_fl)) - <= Bhsize_wosize (3)){ - compact_fl = Chunk_next (compact_fl); - } - chunk = compact_fl; - while (Chunk_size (chunk) - Chunk_alloc (chunk) < size){ - chunk = Chunk_next (chunk); - CAMLassert (chunk != NULL); - } - adr = chunk + Chunk_alloc (chunk); - Chunk_alloc (chunk) += size; - return adr; -} - -static void do_compaction (intnat new_allocation_policy) -{ - char *ch, *chend; - CAMLassert (caml_gc_phase == Phase_idle); - caml_gc_message (0x10, "Compacting heap...\n"); - -#ifdef DEBUG - caml_heap_check (); -#endif - - /* Make sure the heap is in the right state for compaction: - - all free blocks are blue - - all other blocks are white and contain valid pointers - */ - caml_fl_reset_and_switch_policy (new_allocation_policy); - - /* First pass: removed in 4.12 thanks to the new closure representation. */ - - - /* Second pass: invert pointers. - Don't forget roots and weak pointers. - This is a mark-like pass. */ - { - caml_do_roots (caml_invert_root, 1); - /* The values to be finalised are not roots but should still be inverted */ - caml_final_invert_finalisable_values (); - /* Idem for memprof tracked blocks */ - caml_memprof_invert_tracked (); - - ch = caml_heap_start; - while (ch != NULL){ - word *p = (word *) ch; - chend = ch + Chunk_size (ch); - - while ((char *) p < chend){ - word q = *p; - mlsize_t wosz, i, first_field; - tag_t t; - - while (Is_gray_hd (q)) q = * dptr (q); - wosz = Wosize_hd (q); - if (Is_white_hd (q)){ - t = Tag_hd (q); - CAMLassert (t != Infix_tag); - if (t < No_scan_tag){ - value v = Val_hp (p); - if (t == Closure_tag){ - first_field = Start_env_closinfo (Closinfo_val (v)); - }else{ - first_field = 0; - } - for (i = first_field; i < wosz; i++){ - invert_pointer_at ((word *) &Field (v,i)); - } - } - } - p += Whsize_wosize (wosz); - } - ch = Chunk_next (ch); - } - /* Invert weak pointers. */ - { - value *pp = &caml_ephe_list_head; - value p; - word q; - size_t sz, i; - - while (1){ - p = *pp; - if (p == (value) NULL) break; - q = Hd_val (p); - while (Is_gray_hd (q)) q = * dptr (q); - CAMLassert (Is_white_hd (q)); - sz = Wosize_hd (q); - for (i = 1; i < sz; i++){ - if (Field (p,i) != caml_ephe_none){ - invert_pointer_at ((word *) &(Field (p,i))); - } - } - invert_pointer_at ((word *) pp); - pp = &Field (p, 0); - } - } - } - - - /* Third pass: reallocate virtually; revert pointers. - This is a sweep-like pass. */ - { - init_compact_allocate (); - ch = caml_heap_start; - while (ch != NULL){ - word *p = (word *) ch; - - chend = ch + Chunk_size (ch); - while ((char *) p < chend){ - header_t h = Hd_hp (p); - size_t sz; - - while (Is_gray_hd (h)) h = * dptr (h); - sz = Whsize_hd (h); - - CAMLassert (!Is_black_hd (h)); - CAMLassert (!Is_gray_hd (h)); - if (Is_white_hd (h)){ - word q; - tag_t t; - char *newadr; - - t = Tag_hd (h); - CAMLassert (t != Infix_tag); - - newadr = compact_allocate (Bsize_wsize (sz)); - q = *p; - while (Is_gray_hd (q)){ - word *pp = dptr (q); - q = *pp; - *pp = (word) Val_hp (newadr); - } - CAMLassert (q == h); - *p = q; - - if (t == Closure_tag){ - /* Revert the infix pointers to this block. */ - mlsize_t i, startenv; - value v; - - v = Val_hp (p); - startenv = Start_env_closinfo (Closinfo_val (v)); - i = 0; - while (1){ - int arity = Arity_closinfo (Field (v, i+1)); - i += 2 + (arity != 0 && arity != 1); - if (i >= startenv) break; - - /* Revert the inverted list for infix header at offset [i]. */ - q = Field (v, i); - while (Is_gray_hd (q)){ - word *pp = dptr (q); - q = *pp; - *pp = (word) Val_hp ((header_t *) &Field (Val_hp (newadr), i)); - } - CAMLassert (Tag_hd (q) == Infix_tag); - Field (v, i) = q; - ++i; - } - } - } - p += sz; - } - ch = Chunk_next (ch); - } - } - - - /* Fourth pass: reallocate and move objects. - Use the exact same allocation algorithm as pass 3. */ - { - init_compact_allocate (); - ch = caml_heap_start; - while (ch != NULL){ - word *p = (word *) ch; - - chend = ch + Chunk_size (ch); - while ((char *) p < chend){ - word q = *p; - if (Color_hd (q) == Caml_white){ - size_t sz = Bhsize_hd (q); - char *newadr = compact_allocate (sz); - memmove (newadr, p, sz); - p += Wsize_bsize (sz); - }else{ - CAMLassert (Color_hd (q) == Caml_blue); - p += Whsize_hd (q); - } - } - ch = Chunk_next (ch); - } - } - - /* Shrink the heap if needed. */ - { - /* Find the amount of live data and the unshrinkable free space. */ - asize_t live = 0; - asize_t free = 0; - asize_t wanted; - - ch = caml_heap_start; - while (ch != NULL){ - if (Chunk_alloc (ch) != 0){ - live += Wsize_bsize (Chunk_alloc (ch)); - free += Wsize_bsize (Chunk_size (ch) - Chunk_alloc (ch)); - } - ch = Chunk_next (ch); - } - - /* Add up the empty chunks until there are enough, then remove the - other empty chunks. */ - wanted = caml_percent_free * (live / 100 + 1); - ch = caml_heap_start; - while (ch != NULL){ - char *next_chunk = Chunk_next (ch); /* Chunk_next (ch) will be erased */ - - if (Chunk_alloc (ch) == 0){ - if (free < wanted){ - free += Wsize_bsize (Chunk_size (ch)); - }else{ - caml_shrink_heap (ch); - } - } - ch = next_chunk; - } - } - - /* Rebuild the free list. This is the right time for a change of - allocation policy, since we are rebuilding the allocator's data - structures from scratch. */ - { - ch = caml_heap_start; - caml_fl_init_merge (); - while (ch != NULL){ - if (Chunk_size (ch) > Chunk_alloc (ch)){ - caml_make_free_blocks ((value *) (ch + Chunk_alloc (ch)), - Wsize_bsize (Chunk_size(ch)-Chunk_alloc(ch)), 1, - Caml_white); - } - ch = Chunk_next (ch); - } - } - ++ Caml_state->stat_compactions; - caml_gc_message (0x10, "done.\n"); -} - -uintnat caml_percent_max; /* used in gc_ctrl.c and memory.c */ - -void caml_compact_heap (intnat new_allocation_policy) -{ - uintnat target_wsz, live; - - CAMLassert (Caml_state->young_ptr == Caml_state->young_alloc_end); - CAMLassert (Caml_state->ref_table->ptr == - Caml_state->ref_table->base); - CAMLassert (Caml_state->ephe_ref_table->ptr == - Caml_state->ephe_ref_table->base); - CAMLassert (Caml_state->custom_table->ptr == - Caml_state->custom_table->base); - - CAML_EV_BEGIN(EV_COMPACT_MAIN); - do_compaction (new_allocation_policy); - CAML_EV_END(EV_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 - it and it is not freed. - - In that case, we allocate a new chunk of the desired heap - size, chain it at the beginning of the heap (thus pretending - its address is smaller), and launch a second compaction. - This will move all data to this new chunk and free the - very large chunk. - - See PR#5389 - */ - /* We compute: - freewords = caml_fl_cur_wsz (exact) - heapwords = Wsize_bsize (caml_heap_size) (exact) - live = heapwords - freewords - wanted = caml_percent_free * (live / 100 + 1) (same as in do_compaction) - target_wsz = live + wanted - We add one page to make sure a small difference in counting sizes - won't make [do_compaction] keep the second block (and break all sorts - of invariants). - - We recompact if target_wsz < heap_size / 2 - */ - live = Caml_state->stat_heap_wsz - caml_fl_cur_wsz; - target_wsz = live + caml_percent_free * (live / 100 + 1) - + Wsize_bsize (Page_size); - target_wsz = caml_clip_heap_chunk_wsz (target_wsz); - -#ifdef HAS_HUGE_PAGES - if (caml_use_huge_pages - && Bsize_wsize (Caml_state->stat_heap_wsz) <= HUGE_PAGE_SIZE) - return; -#endif - - if (target_wsz < Caml_state->stat_heap_wsz / 2){ - /* Recompact. */ - char *chunk; - - caml_gc_message (0x10, "Recompacting heap (target=%" - ARCH_INTNAT_PRINTF_FORMAT "uk words)\n", - target_wsz / 1024); - - chunk = caml_alloc_for_heap (Bsize_wsize (target_wsz)); - if (chunk == NULL) return; - /* PR#5757: we need to make the new blocks blue, or they won't be - recognized as free by the recompaction. */ - caml_make_free_blocks ((value *) chunk, - Wsize_bsize (Chunk_size (chunk)), 0, Caml_blue); - if (caml_page_table_add (In_heap, chunk, chunk + Chunk_size (chunk)) != 0){ - caml_free_for_heap (chunk); - return; - } - Chunk_next (chunk) = caml_heap_start; - caml_heap_start = chunk; - ++ Caml_state->stat_heap_chunks; - Caml_state->stat_heap_wsz += Wsize_bsize (Chunk_size (chunk)); - if (Caml_state->stat_heap_wsz > Caml_state->stat_top_heap_wsz){ - Caml_state->stat_top_heap_wsz = Caml_state->stat_heap_wsz; - } - CAML_EV_BEGIN(EV_COMPACT_RECOMPACT); - do_compaction (-1); - CAMLassert (Caml_state->stat_heap_chunks == 1); - CAMLassert (Chunk_next (caml_heap_start) == NULL); - CAMLassert (Caml_state->stat_heap_wsz == Wsize_bsize (Chunk_size (chunk))); - CAML_EV_END(EV_COMPACT_RECOMPACT); - } -} - -void caml_compact_heap_maybe (void) -{ - /* Estimated free+garbage words in the heap: - FW = fl_size_at_phase_change + 3 * (caml_fl_cur_wsz - - caml_fl_wsz_at_phase_change) - FW = 3 * caml_fl_cur_wsz - 2 * caml_fl_wsz_at_phase_change - Estimated live words: LW = Caml_state->stat_heap_wsz - FW - Estimated free percentage: FP = 100 * FW / LW - We compact the heap if FP > caml_percent_max - */ - double fw, fp; - CAMLassert (caml_gc_phase == Phase_idle); - if (caml_percent_max >= 1000000) return; - if (Caml_state->stat_major_collections < 3) return; - if (Caml_state->stat_heap_wsz <= 2 * caml_clip_heap_chunk_wsz (0)) return; - -#ifdef HAS_HUGE_PAGES - if (caml_use_huge_pages - && Bsize_wsize (Caml_state->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; - - if (fw >= Caml_state->stat_heap_wsz){ - fp = 1000000.0; - }else{ - fp = 100.0 * fw / (Caml_state->stat_heap_wsz - fw); - if (fp > 1000000.0) fp = 1000000.0; - } - caml_gc_message (0x200, "FL size at phase change = %" - ARCH_INTNAT_PRINTF_FORMAT "u words\n", - (uintnat) caml_fl_wsz_at_phase_change); - caml_gc_message (0x200, "FL current size = %" - ARCH_INTNAT_PRINTF_FORMAT "u words\n", - (uintnat) caml_fl_cur_wsz); - caml_gc_message (0x200, "Estimated overhead = %" - ARCH_INTNAT_PRINTF_FORMAT "u%%\n", - (uintnat) fp); - if (fp >= caml_percent_max){ - caml_gc_message (0x200, "Automatic compaction triggered.\n"); - caml_empty_minor_heap (); /* minor heap must be empty for compaction */ - caml_finish_major_cycle (); - ++ Caml_state->stat_forced_major_collections; - - fw = caml_fl_cur_wsz; - fp = 100.0 * fw / (Caml_state->stat_heap_wsz - fw); - caml_gc_message (0x200, "Measured overhead: %" - ARCH_INTNAT_PRINTF_FORMAT "u%%\n", - (uintnat) fp); - if (fp >= caml_percent_max) - caml_compact_heap (-1); - else - caml_gc_message (0x200, "Automatic compaction aborted.\n"); - - } -} diff --git a/runtime/compare.c b/runtime/compare.c index 4a0eb6eac0..181877e1b8 100644 --- a/runtime/compare.c +++ b/runtime/compare.c @@ -127,55 +127,44 @@ static intnat do_compare_val(struct compare_stack* stk, if (Is_long(v2)) return Long_val(v1) - Long_val(v2); /* Subtraction above cannot overflow and cannot result in UNORDERED */ - if (!Is_in_value_area(v2)) - return LESS; switch (Tag_val(v2)) { - case Forward_tag: - v2 = Forward_val(v2); - continue; - case Custom_tag: { - int res; - int (*compare)(value v1, value v2) = Custom_ops_val(v2)->compare_ext; - if (compare == NULL) break; /* for backward compatibility */ - Caml_state->compare_unordered = 0; - res = compare(v1, v2); - if (Caml_state->compare_unordered && !total) return UNORDERED; - if (res != 0) return res; - goto next_item; - } - default: /*fallthrough*/; - } + case Forward_tag: + v2 = Forward_val(v2); + continue; + case Custom_tag: { + int res; + int (*compare)(value v1, value v2) = Custom_ops_val(v2)->compare_ext; + if (compare == NULL) break; /* for backward compatibility */ + Caml_state->compare_unordered = 0; + res = compare(v1, v2); + if (Caml_state->compare_unordered && !total) return UNORDERED; + if (res != 0) return res; + goto next_item; + } + default: /*fallthrough*/; + } + return LESS; /* v1 long < v2 block */ } if (Is_long(v2)) { - if (!Is_in_value_area(v1)) - return GREATER; switch (Tag_val(v1)) { - case Forward_tag: - v1 = Forward_val(v1); - continue; - case Custom_tag: { - int res; - int (*compare)(value v1, value v2) = Custom_ops_val(v1)->compare_ext; - if (compare == NULL) break; /* for backward compatibility */ - Caml_state->compare_unordered = 0; - res = compare(v1, v2); - if (Caml_state->compare_unordered && !total) return UNORDERED; - if (res != 0) return res; - goto next_item; - } - default: /*fallthrough*/; - } + case Forward_tag: + v1 = Forward_val(v1); + continue; + case Custom_tag: { + int res; + int (*compare)(value v1, value v2) = Custom_ops_val(v1)->compare_ext; + if (compare == NULL) break; /* for backward compatibility */ + Caml_state->compare_unordered = 0; + res = compare(v1, v2); + if (Caml_state->compare_unordered && !total) return UNORDERED; + if (res != 0) return res; + goto next_item; + } + default: /*fallthrough*/; + } return GREATER; /* v1 block > v2 long */ } - /* If one of the objects is outside the heap (but is not an atom), - use address comparison. Since both addresses are 2-aligned, - shift lsb off to avoid overflow in subtraction. */ - if (! Is_in_value_area(v1) || ! Is_in_value_area(v2)) { - if (v1 == v2) goto next_item; - return (v1 >> 1) - (v2 >> 1); - /* Subtraction above cannot result in UNORDERED */ - } t1 = Tag_val(v1); t2 = Tag_val(v2); if (t1 != t2) { @@ -253,6 +242,9 @@ static intnat do_compare_val(struct compare_stack* stk, case Infix_tag: compare_free_stack(stk); caml_invalid_argument("compare: functional value"); + case Cont_tag: + compare_free_stack(stk); + caml_invalid_argument("compare: continuation value"); case Object_tag: { intnat oid1 = Oid_val(v1); intnat oid2 = Oid_val(v2); @@ -288,8 +280,8 @@ static intnat do_compare_val(struct compare_stack* stk, if (sz1 > 1) { sp++; if (sp >= stk->limit) sp = compare_resize_stack(stk, sp); - sp->v1 = &Field(v1, 1); - sp->v2 = &Field(v2, 1); + sp->v1 = Op_val(v1) + 1; + sp->v2 = Op_val(v2) + 1; sp->count = sz1 - 1; } /* Continue comparison with first field */ diff --git a/runtime/custom.c b/runtime/custom.c index 8568b5875a..6c45898a9f 100644 --- a/runtime/custom.c +++ b/runtime/custom.c @@ -23,13 +23,14 @@ #include "caml/gc_ctrl.h" #include "caml/memory.h" #include "caml/mlvalues.h" +#include "caml/shared_heap.h" #include "caml/signals.h" uintnat caml_custom_major_ratio = Custom_major_ratio_def; uintnat caml_custom_minor_ratio = Custom_minor_ratio_def; uintnat caml_custom_minor_max_bsz = Custom_minor_max_bsz_def; -static value alloc_custom_gen (struct custom_operations * ops, +static value alloc_custom_gen (const struct custom_operations * ops, uintnat bsz, mlsize_t mem, mlsize_t max_major, @@ -49,6 +50,9 @@ static value alloc_custom_gen (struct custom_operations * ops, result = caml_alloc_small(wosize, Custom_tag); Custom_ops_val(result) = ops; if (ops->finalize != NULL || mem != 0) { + /* Remember that the block needs processing after minor GC. */ + add_to_custom_table (&Caml_state->minor_tables->custom, result, mem, max_major); +#if 0 /* XXX TODO KC */ if (mem > mem_minor) { caml_adjust_gc_speed (mem - mem_minor, max_major); } @@ -62,20 +66,23 @@ static value alloc_custom_gen (struct custom_operations * ops, if (max_minor == 0) max_minor = 1; Caml_state->extra_heap_resources_minor += (double) mem_minor / (double) max_minor; - if (Caml_state->extra_heap_resources_minor > 1.0) - caml_minor_collection (); + if (Caml_state->extra_heap_resources_minor > 1.0) { + caml_request_minor_gc (); + caml_gc_dispatch (); + } } +#endif } } else { result = caml_alloc_shr(wosize, Custom_tag); Custom_ops_val(result) = ops; - caml_adjust_gc_speed(mem, max_major); - caml_check_urgent_gc(Val_unit); + /* !!caml_adjust_gc_speed(mem, max_major); */ + result = caml_check_urgent_gc(result); } CAMLreturn(result); } -CAMLexport value caml_alloc_custom(struct custom_operations * ops, +CAMLexport value caml_alloc_custom(const struct custom_operations * ops, uintnat bsz, mlsize_t mem, mlsize_t max) @@ -83,10 +90,11 @@ CAMLexport value caml_alloc_custom(struct custom_operations * ops, return alloc_custom_gen (ops, bsz, mem, max, mem, max); } -CAMLexport value caml_alloc_custom_mem(struct custom_operations * ops, +CAMLexport value caml_alloc_custom_mem(const struct custom_operations * ops, uintnat bsz, mlsize_t mem) { + mlsize_t mem_minor = mem < caml_custom_minor_max_bsz ? mem : caml_custom_minor_max_bsz; mlsize_t max_major = @@ -99,20 +107,20 @@ CAMLexport value caml_alloc_custom_mem(struct custom_operations * ops, the major GC takes 1.5 cycles (previous cycle + marking phase) before it starts to deallocate dead blocks allocated during the previous cycle. [heap_size / 150] is really [heap_size * (2/3) / 100] (but faster). */ - Bsize_wsize (Caml_state->stat_heap_wsz) / 150 * caml_custom_major_ratio; + caml_heap_size(Caml_state->shared_heap) / 150 * caml_custom_major_ratio; mlsize_t max_minor = Bsize_wsize (Caml_state->minor_heap_wsz) / 100 * caml_custom_minor_ratio; return alloc_custom_gen (ops, bsz, mem, max_major, mem_minor, max_minor); } struct custom_operations_list { - struct custom_operations * ops; + const struct custom_operations * ops; struct custom_operations_list * next; }; static struct custom_operations_list * custom_ops_table = NULL; -CAMLexport void caml_register_custom_operations(struct custom_operations * ops) +CAMLexport void caml_register_custom_operations(const struct custom_operations * ops) { struct custom_operations_list * l = caml_stat_alloc(sizeof(struct custom_operations_list)); @@ -127,7 +135,7 @@ struct custom_operations * caml_find_custom_operations(char * ident) { struct custom_operations_list * l; for (l = custom_ops_table; l != NULL; l = l->next) - if (strcmp(l->ops->identifier, ident) == 0) return l->ops; + if (strcmp(l->ops->identifier, ident) == 0) return (struct custom_operations*)l->ops; return NULL; } @@ -138,7 +146,7 @@ struct custom_operations * caml_final_custom_operations(final_fun fn) struct custom_operations_list * l; struct custom_operations * ops; for (l = custom_ops_final_table; l != NULL; l = l->next) - if (l->ops->finalize == fn) return l->ops; + if (l->ops->finalize == fn) return (struct custom_operations*)l->ops; ops = caml_stat_alloc(sizeof(struct custom_operations)); ops->identifier = "_final"; ops->finalize = fn; @@ -155,10 +163,11 @@ struct custom_operations * caml_final_custom_operations(final_fun fn) return ops; } -extern struct custom_operations caml_int32_ops, - caml_nativeint_ops, - caml_int64_ops, - caml_ba_ops; +extern const struct custom_operations + caml_int32_ops, + caml_nativeint_ops, + caml_int64_ops, + caml_ba_ops; void caml_init_custom_operations(void) { diff --git a/runtime/debugger.c b/runtime/debugger.c index 050389e21d..8f6a40a711 100644 --- a/runtime/debugger.c +++ b/runtime/debugger.c @@ -28,12 +28,14 @@ #include "caml/config.h" #include "caml/debugger.h" #include "caml/misc.h" +#include "caml/memory.h" #include "caml/osdeps.h" #include "caml/skiplist.h" int caml_debugger_in_use = 0; uintnat caml_event_count; int caml_debugger_fork_mode = 1; /* parent by default */ +caml_root marshal_flags; #if !defined(HAS_SOCKETS) || defined(NATIVE_CODE) @@ -77,11 +79,9 @@ void caml_debugger_cleanup_fork(void) #include "caml/intext.h" #include "caml/io.h" #include "caml/mlvalues.h" -#include "caml/stacks.h" +#include "caml/fiber.h" #include "caml/sys.h" -static value marshal_flags = Val_emptylist; - static int sock_domain; /* Socket domain for the debugger */ static union { /* Socket address for the debugger */ struct sockaddr s_gen; @@ -178,12 +178,13 @@ void caml_debugger_init(void) size_t a_len; char * port, * p; struct hostent * host; + value flags; int n; - caml_register_global_root(&marshal_flags); - marshal_flags = caml_alloc(2, Tag_cons); - Store_field(marshal_flags, 0, Val_int(1)); /* Marshal.Closures */ - Store_field(marshal_flags, 1, Val_emptylist); + flags = caml_alloc(2, Tag_cons); + Store_field(flags, 0, Val_int(1)); /* Marshal.Closures */ + Store_field(flags, 1, Val_emptylist); + marshal_flags = caml_create_root(flags); a = caml_secure_getenv(T("CAML_DEBUG_SOCKET")); address = a ? caml_stat_strdup_of_os(a) : NULL; @@ -249,7 +250,7 @@ void caml_debugger_init(void) } open_connection(); caml_debugger_in_use = 1; - Caml_state->trap_barrier = Caml_state->stack_high; + Caml_state->trap_barrier_off = 2; /* Bigger than default caml_trap_sp_off (1) */ } static value getval(struct channel *chan) @@ -267,13 +268,15 @@ static void putval(struct channel *chan, value val) static void safe_output_value(struct channel *chan, value val) { - struct longjmp_buffer raise_buf, * saved_external_raise; + struct longjmp_buffer raise_buf; + struct caml_exception_context exception_ctx = {&raise_buf, CAML_LOCAL_ROOTS}; + struct caml_exception_context* saved_external_raise; /* Catch exceptions raised by [caml_output_val] */ saved_external_raise = Caml_state->external_raise; if (sigsetjmp(raise_buf.buf, 0) == 0) { - Caml_state->external_raise = &raise_buf; - caml_output_val(chan, val, marshal_flags); + Caml_state->external_raise = &exception_ctx; + caml_output_val(chan, val, caml_read_root(marshal_flags)); } else { /* Send wrong magic number, will cause [caml_input_value] to fail */ caml_really_putblock(chan, "\000\000\000\000", 4); @@ -354,13 +357,14 @@ void caml_debugger(enum event_kind event, value param) value *frame, *newframe; intnat i, pos; value val; + value* stack_high = Stack_high(Caml_state->current_stack); int frag; struct code_fragment *cf; if (dbg_socket == -1) return; /* Not connected to a debugger. */ /* Reset current frame */ - frame = Caml_state->extern_sp + 1; + frame = Caml_state->current_stack->sp + 1; /* Report the event to the debugger */ switch(event) { @@ -402,7 +406,7 @@ void caml_debugger(enum event_kind event, value param) } caml_putword(dbg_out, caml_event_count); if (event == EVENT_COUNT || event == BREAKPOINT) { - caml_putword(dbg_out, Caml_state->stack_high - frame); + caml_putword(dbg_out, stack_high - frame); cf = caml_find_code_fragment_by_pc((char*) Pc(frame)); CAMLassert(cf != NULL); caml_putword(dbg_out, cf->fragnum); @@ -463,11 +467,11 @@ void caml_debugger(enum event_kind event, value param) #endif break; case REQ_INITIAL_FRAME: - frame = Caml_state->extern_sp + 1; + frame = Caml_state->current_stack->sp + 1; /* Fall through */ case REQ_GET_FRAME: - caml_putword(dbg_out, Caml_state->stack_high - frame); - if (frame < Caml_state->stack_high && + caml_putword(dbg_out, stack_high - frame); + if (frame < stack_high && (cf = caml_find_code_fragment_by_pc((char*) Pc(frame))) != NULL) { caml_putword(dbg_out, cf->fragnum); caml_putword(dbg_out, (char*) Pc(frame) - cf->code_start); @@ -479,17 +483,17 @@ void caml_debugger(enum event_kind event, value param) break; case REQ_SET_FRAME: i = caml_getword(dbg_in); - frame = Caml_state->stack_high - i; + frame = stack_high - i; break; case REQ_UP_FRAME: i = caml_getword(dbg_in); newframe = frame + Extra_args(frame) + i + 3; - if (newframe >= Caml_state->stack_high || + if (newframe >= stack_high || (cf = caml_find_code_fragment_by_pc((char *) Pc(newframe))) == NULL) { caml_putword(dbg_out, -1); } else { frame = newframe; - caml_putword(dbg_out, Caml_state->stack_high - frame); + caml_putword(dbg_out, stack_high - frame); caml_putword(dbg_out, cf->fragnum); caml_putword(dbg_out, (char*) Pc(frame) - cf->code_start); } @@ -497,7 +501,7 @@ void caml_debugger(enum event_kind event, value param) break; case REQ_SET_TRAP_BARRIER: i = caml_getword(dbg_in); - Caml_state->trap_barrier = Caml_state->stack_high - i; + Caml_state->trap_barrier_off = -i; break; case REQ_GET_LOCAL: i = caml_getword(dbg_in); @@ -511,11 +515,11 @@ void caml_debugger(enum event_kind event, value param) break; case REQ_GET_GLOBAL: i = caml_getword(dbg_in); - putval(dbg_out, Field(caml_global_data, i)); + putval(dbg_out, Field(caml_read_root(caml_global_data), i)); caml_flush(dbg_out); break; case REQ_GET_ACCU: - putval(dbg_out, *Caml_state->extern_sp); + putval(dbg_out, *Caml_state->current_stack->sp); caml_flush(dbg_out); break; case REQ_GET_HEADER: @@ -528,7 +532,7 @@ void caml_debugger(enum event_kind event, value param) i = caml_getword(dbg_in); if (Tag_val(val) != Double_array_tag) { caml_putch(dbg_out, 0); - putval(dbg_out, Field(val, i)); + putval(dbg_out, Op_val(val)[i]); } else { double d = Double_flat_field(val, i); caml_putch(dbg_out, 1); diff --git a/runtime/domain.c b/runtime/domain.c index c6cb4cd2f6..0f65d35f82 100644 --- a/runtime/domain.c +++ b/runtime/domain.c @@ -16,75 +16,1568 @@ #define CAML_INTERNALS +#include <stdio.h> +#include <unistd.h> +#include <pthread.h> +#include <string.h> +#include "caml/alloc.h" +#include "caml/domain.h" #include "caml/domain_state.h" +#include "caml/platform.h" +#include "caml/custom.h" +#include "caml/major_gc.h" +#include "caml/shared_heap.h" #include "caml/memory.h" +#include "caml/fail.h" +#include "caml/globroots.h" +#include "caml/signals.h" +#include "caml/alloc.h" +#include "caml/startup.h" +#include "caml/fiber.h" +#include "caml/callback.h" +#include "caml/minor_gc.h" +#include "caml/eventlog.h" +#include "caml/gc_ctrl.h" +#include "caml/osdeps.h" +#include "caml/weak.h" +#include "caml/finalise.h" +#include "caml/gc_ctrl.h" -CAMLexport caml_domain_state* Caml_state; +#define BT_IN_BLOCKING_SECTION 0 +#define BT_ENTERING_OCAML 1 +#define BT_TERMINATE 2 +#define BT_INIT 3 -void caml_init_domain () +/* Since we support both heavyweight OS threads and lightweight + userspace threads, the word "thread" is ambiguous. This file deals + with OS-level threads, called "domains". +*/ + + +/* control of interrupts */ +struct interruptor { + atomic_uintnat* interrupt_word; + caml_plat_mutex lock; + caml_plat_cond cond; + + int running; + int terminating; + /* unlike the domain ID, this ID number is not reused */ + uintnat unique_id; + + /* Queue of domains trying to send interrupts here */ + struct interrupt* qhead; + struct interrupt* qtail; /* defined only when qhead != NULL */ + + /* Next pointer for wait queues. + Touched only when the queue is locked */ + struct interruptor* next; +}; +/* returns 0 on failure, if the target has terminated. */ +CAMLcheckresult +int caml_send_interrupt(struct interruptor* self, + struct interruptor* target, + domain_rpc_handler handler, + void* data); +void caml_handle_incoming_interrupts(void); + + +struct dom_internal { + /* readonly fields, initialised and never modified */ + atomic_uintnat* interrupt_word_address; + int id; + struct domain state; + struct interruptor interruptor; + + /* backup thread */ + int backup_thread_running; + pthread_t backup_thread; + atomic_uintnat backup_thread_msg; + caml_plat_mutex domain_lock; + caml_plat_cond domain_cond; + + /* readonly */ + uintnat tls_area; + uintnat tls_area_end; + uintnat minor_heap_area; + uintnat minor_heap_area_end; +}; +typedef struct dom_internal dom_internal; + +static uintnat handle_incoming(struct interruptor* s); + +static caml_plat_mutex all_domains_lock = CAML_PLAT_MUTEX_INITIALIZER; +static caml_plat_cond all_domains_cond = CAML_PLAT_COND_INITIALIZER(&all_domains_lock); +static atomic_uintnat /* dom_internal* */ stw_leader = 0; +static struct dom_internal all_domains[Max_domains]; + +CAMLexport atomic_uintnat caml_num_domains_running; + +CAMLexport uintnat caml_minor_heaps_base; +CAMLexport uintnat caml_minor_heaps_end; +static __thread dom_internal* domain_self; + +static int64_t startup_timestamp; + +struct interrupt { + /* immutable fields */ + domain_rpc_handler handler; + void* data; + + atomic_uintnat acknowledged; + + /* accessed only when target's lock held */ + struct interrupt* next; +}; + +#ifdef __APPLE__ +/* OSX has issues with dynamic loading + exported TLS. + This is slower but works */ +CAMLexport pthread_key_t caml_domain_state_key; +static pthread_once_t key_once = PTHREAD_ONCE_INIT; + +static void caml_make_domain_state_key () +{ + (void) pthread_key_create (&caml_domain_state_key, NULL); +} + +void caml_init_domain_state_key () +{ + pthread_once(&key_once, caml_make_domain_state_key); +} + +#else +CAMLexport __thread caml_domain_state* Caml_state; +#endif + +asize_t caml_norm_minor_heap_size (intnat wsize) +{ + asize_t page_size = caml_mem_round_up_pages(1); + asize_t bs, max; + if (wsize < Minor_heap_min) wsize = Minor_heap_min; + bs = caml_mem_round_up_pages(Bsize_wsize (wsize)); + + Assert(page_size * 2 < Minor_heap_max); + max = Minor_heap_max - page_size * 2; + + if (bs > max) bs = max; + + return Wsize_bsize(bs); +} + +int caml_reallocate_minor_heap(asize_t wsize) +{ + caml_domain_state* domain_state = Caml_state; + Assert(domain_state->young_ptr == domain_state->young_end); + + /* free old minor heap. + instead of unmapping the heap, we decommit it, so there's + no race whereby other code could attempt to reuse the memory. */ + caml_mem_decommit((void*)domain_self->minor_heap_area, + domain_self->minor_heap_area_end - domain_self->minor_heap_area); + + wsize = caml_norm_minor_heap_size(wsize); + + if (!caml_mem_commit((void*)domain_self->minor_heap_area, Bsize_wsize(wsize))) { + return -1; + } + +#ifdef DEBUG + { + uintnat* p = (uintnat*)domain_self->minor_heap_area; + for (; p < (uintnat*)(domain_self->minor_heap_area + Bsize_wsize(wsize)); p++) + *p = Debug_uninit_align; + } +#endif + + domain_state->minor_heap_wsz = wsize; + + domain_state->young_start = (char*)domain_self->minor_heap_area; + domain_state->young_end = (char*)(domain_self->minor_heap_area + Bsize_wsize(wsize)); + domain_state->young_limit = (uintnat) domain_state->young_start; + domain_state->young_ptr = domain_state->young_end; + return 0; +} + +/* must be run on the domain's thread */ +static void create_domain(uintnat initial_minor_heap_wsize) { + int i; + dom_internal* d = 0; + Assert (domain_self == 0); + + caml_plat_lock(&all_domains_lock); + + /* wait until any in-progress STW sections end */ + while (atomic_load_acq(&stw_leader)) caml_plat_wait(&all_domains_cond); + + for (i = 0; i < Max_domains && !d; i++) { + struct interruptor* s = &all_domains[i].interruptor; + caml_plat_lock(&s->lock); + if (!s->running) { + d = &all_domains[i]; + if (!d->interrupt_word_address) { + caml_domain_state* domain_state; + atomic_uintnat* young_limit; + /* never been started before, so set up minor heap */ + if (!caml_mem_commit((void*)d->tls_area, (d->tls_area_end - d->tls_area))) { + /* give up now: if we couldn't get memory for this domain, we're + unlikely to have better luck with any other */ + d = 0; + caml_plat_unlock(&s->lock); + break; + } + domain_state = (caml_domain_state*)(d->tls_area); + young_limit = (atomic_uintnat*)&domain_state->young_limit; + d->interrupt_word_address = young_limit; + atomic_store_rel(young_limit, (uintnat)domain_state->young_start); + s->interrupt_word = young_limit; + } + Assert(s->qhead == NULL); + s->running = 1; + atomic_fetch_add(&caml_num_domains_running, 1); + } + caml_plat_unlock(&s->lock); + } + if (d) { + caml_domain_state* domain_state; + d->state.internals = d; + domain_self = d; + SET_Caml_state((void*)(d->tls_area)); + domain_state = (caml_domain_state*)(d->tls_area); + caml_plat_lock(&d->domain_lock); + + domain_state->id = d->id; + domain_state->unique_id = d->interruptor.unique_id; + d->state.state = domain_state; + domain_state->critical_section_nesting = 0; + + if (caml_init_signal_stack() < 0) { + goto init_signal_stack_failure; + } + + domain_state->young_start = domain_state->young_end = + domain_state->young_ptr = 0; + domain_state->minor_tables = caml_alloc_minor_tables(); + if(domain_state->minor_tables == NULL) { + goto alloc_minor_tables_failure; + } + + d->state.state->shared_heap = caml_init_shared_heap(); + if(d->state.state->shared_heap == NULL) { + goto init_shared_heap_failure; + } + + if (caml_init_major_gc(domain_state) < 0) { + goto init_major_gc_failure; + } + + if(caml_reallocate_minor_heap(initial_minor_heap_wsize) < 0) { + goto reallocate_minor_heap_failure; + } + + domain_state->dls_root = caml_create_root_noexc(Val_unit); + if(domain_state->dls_root == NULL) { + goto create_root_failure; + } + + domain_state->stack_cache = caml_alloc_stack_cache(); + if(domain_state->stack_cache == NULL) { + goto create_stack_cache_failure; + } + + domain_state->current_stack = + caml_alloc_main_stack(Stack_size / sizeof(value)); + if(domain_state->current_stack == NULL) { + goto alloc_main_stack_failure; + } + + domain_state->backtrace_buffer = NULL; +#ifndef NATIVE_CODE + domain_state->external_raise = NULL; + domain_state->trap_sp_off = 1; +#endif + + domain_state->eventlog_enabled = 0; + domain_state->eventlog_paused = 0; + domain_state->eventlog_startup_pid = 0; + domain_state->eventlog_startup_timestamp = 0; + domain_state->eventlog_out = NULL; + + goto domain_init_complete; + + caml_free_stack(domain_state->current_stack); +alloc_main_stack_failure: +create_stack_cache_failure: + caml_delete_root(domain_state->dls_root); +create_root_failure: +reallocate_minor_heap_failure: + caml_teardown_major_gc(); +init_major_gc_failure: + caml_teardown_shared_heap(d->state.state->shared_heap); +init_shared_heap_failure: + caml_free_minor_tables(domain_state->minor_tables); + domain_state->minor_tables = NULL; +alloc_minor_tables_failure: + caml_free_signal_stack(); +init_signal_stack_failure: + domain_self = NULL; + + } +domain_init_complete: + caml_plat_unlock(&all_domains_lock); +} + +CAMLexport void caml_reset_domain_lock(void) +{ + dom_internal* self = domain_self; + // This is only used to reset the domain_lock state on fork. + caml_plat_mutex_init(&self->domain_lock); + caml_plat_cond_init(&self->domain_cond, &self->domain_lock); + + return; +} + +void caml_init_domains(uintnat minor_heap_wsz) { + int i; + uintnat size; + void* heaps_base; + + /* sanity check configuration */ + if (caml_mem_round_up_pages(Minor_heap_max) != Minor_heap_max) + caml_fatal_error("Minor_heap_max misconfigured for this platform"); + + /* reserve memory space for minor heaps */ + size = (uintnat)Minor_heap_max * Max_domains; + + heaps_base = caml_mem_map(size*2, size*2, 1 /* reserve_only */); + if (!heaps_base) caml_raise_out_of_memory(); + + caml_minor_heaps_base = (uintnat) heaps_base; + caml_minor_heaps_end = (uintnat) heaps_base + size; + + for (i = 0; i < Max_domains; i++) { + struct dom_internal* dom = &all_domains[i]; + uintnat domain_minor_heap_base; + + caml_plat_mutex_init(&dom->interruptor.lock); + caml_plat_cond_init(&dom->interruptor.cond, + &dom->interruptor.lock); + dom->interruptor.qhead = dom->interruptor.qtail = NULL; + dom->interruptor.running = 0; + dom->interruptor.terminating = 0; + dom->interruptor.unique_id = i; + dom->id = i; + + caml_plat_mutex_init(&dom->domain_lock); + caml_plat_cond_init(&dom->domain_cond, &dom->domain_lock); + dom->backup_thread_running = 0; + dom->backup_thread_msg = BT_INIT; + + domain_minor_heap_base = caml_minor_heaps_base + + (uintnat)Minor_heap_max * (uintnat)i; + dom->tls_area = domain_minor_heap_base; + dom->tls_area_end = + caml_mem_round_up_pages(dom->tls_area + + sizeof(caml_domain_state)); + dom->minor_heap_area = /* skip guard page */ + caml_mem_round_up_pages(dom->tls_area_end + 1); + dom->minor_heap_area_end = + domain_minor_heap_base + Minor_heap_max; + } + + + create_domain(minor_heap_wsz); + if (!domain_self) caml_fatal_error("Failed to create main domain"); + + caml_init_signal_handling(); + startup_timestamp = caml_time_counter(); +} + +void caml_init_domain_self(int domain_id) { + Assert (domain_id >= 0 && domain_id < Max_domains); + domain_self = &all_domains[domain_id]; + SET_Caml_state(domain_self->state.state); +} + +enum domain_status { Dom_starting, Dom_started, Dom_failed }; +struct domain_startup_params { + struct interruptor* parent; + enum domain_status status; + caml_root callback; + dom_internal* newdom; + uintnat unique_id; +}; + +static void* backup_thread_func(void* v) +{ + dom_internal* di = (dom_internal*)v; + uintnat msg; + struct interruptor* s = &di->interruptor; + + domain_self = di; + SET_Caml_state((void*)(di->tls_area)); + + /* TODO: how does the backup thread interact with the eventlog infra? + * caml_ev_tag_self_as_backup_thread(); */ + + msg = atomic_load_acq (&di->backup_thread_msg); + while (msg != BT_TERMINATE) { + Assert (msg <= BT_TERMINATE); + switch (msg) { + case BT_IN_BLOCKING_SECTION: + /* Handle interrupts on behalf of the main thread: + * - must hold domain_lock to handle interrupts + * - need to guarantee no blocking so that backup thread + * can be signalled from caml_leave_blocking_section + */ + if (caml_incoming_interrupts_queued()) { + if (caml_plat_try_lock(&di->domain_lock)) { + caml_handle_incoming_interrupts(); + caml_plat_unlock(&di->domain_lock); + } + } + /* Wait safely if there is nothing to do. + * Will be woken from caml_leave_blocking_section + */ + caml_plat_lock(&s->lock); + msg = atomic_load_acq (&di->backup_thread_msg); + if (msg == BT_IN_BLOCKING_SECTION && + !caml_incoming_interrupts_queued()) + caml_plat_wait(&s->cond); + caml_plat_unlock(&s->lock); + break; + case BT_ENTERING_OCAML: + /* Main thread wants to enter OCaml + * Will be woken from caml_enter_blocking_section + * or domain_terminate + */ + caml_plat_lock(&di->domain_lock); + msg = atomic_load_acq (&di->backup_thread_msg); + if (msg == BT_ENTERING_OCAML) + caml_plat_wait(&di->domain_cond); + caml_plat_unlock(&di->domain_lock); + break; + default: + cpu_relax(); + break; + }; + msg = atomic_load_acq (&di->backup_thread_msg); + } + + /* doing terminate */ + atomic_store_rel(&di->backup_thread_msg, BT_INIT); + + return 0; +} + +static void install_backup_thread (dom_internal* di) +{ + int err; + + if (di->backup_thread_running == 0) { + Assert (di->backup_thread_msg == BT_INIT || /* Using fresh domain */ + di->backup_thread_msg == BT_TERMINATE); /* Reusing domain */ + + while (atomic_load_acq(&di->backup_thread_msg) != BT_INIT) { + /* Give a chance for backup thread on this domain to terminate */ + caml_plat_unlock (&di->domain_lock); + cpu_relax (); + caml_plat_lock (&di->domain_lock); + } + + atomic_store_rel(&di->backup_thread_msg, BT_ENTERING_OCAML); + err = pthread_create (&di->backup_thread, 0, backup_thread_func, (void*)di); + if (err) + caml_failwith("failed to create domain backup thread"); + di->backup_thread_running = 1; + pthread_detach(di->backup_thread); + } +} + +static void caml_domain_stop_default(void) +{ + return; +} + +static void caml_domain_start_default(void) +{ + return; +} + +CAMLexport void (*caml_domain_start_hook)(void) = + caml_domain_start_default; + +CAMLexport void (*caml_domain_stop_hook)(void) = + caml_domain_stop_default; + +static void domain_terminate(); + +static void* domain_thread_func(void* v) +{ + struct domain_startup_params* p = v; + caml_root callback = p->callback; + + create_domain(caml_params->init_minor_heap_wsz); + p->newdom = domain_self; + + caml_plat_lock(&p->parent->lock); + if (domain_self) { + p->status = Dom_started; + p->unique_id = domain_self->interruptor.unique_id; + } else { + p->status = Dom_failed; + } + caml_plat_broadcast(&p->parent->cond); + caml_plat_unlock(&p->parent->lock); + /* cannot access p below here */ + + if (domain_self) { + install_backup_thread(domain_self); + caml_gc_log("Domain starting (unique_id = %"ARCH_INTNAT_PRINTF_FORMAT"u)", + domain_self->interruptor.unique_id); + caml_domain_start_hook(); + caml_callback(caml_read_root(callback), Val_unit); + caml_delete_root(callback); + domain_terminate(); + } else { + caml_gc_log("Failed to create domain"); + } + return 0; +} + +#define Domainthreadptr_val(val) ((struct domain_thread**)Data_custom_val(val)) + +CAMLprim value caml_domain_spawn(value callback) +{ + CAMLparam1 (callback); + struct domain_startup_params p; + pthread_t th; + int err; + + CAML_EV_BEGIN(EV_DOMAIN_SPAWN); + p.parent = &domain_self->interruptor; + p.status = Dom_starting; + + p.callback = caml_create_root(callback); + + err = pthread_create(&th, 0, domain_thread_func, (void*)&p); + if (err) { + caml_failwith("failed to create domain thread"); + } + + caml_plat_lock(&domain_self->interruptor.lock); + while (p.status == Dom_starting) { + if (handle_incoming(&domain_self->interruptor) == 0) + caml_plat_wait(&domain_self->interruptor.cond); + } + caml_plat_unlock(&domain_self->interruptor.lock); + + if (p.status == Dom_started) { + /* successfully created a domain. + p.callback is now owned by that domain */ + pthread_detach(th); + } else { + Assert (p.status == Dom_failed); + /* failed */ + pthread_join(th, 0); + caml_delete_root(p.callback); + caml_failwith("failed to allocate domain"); + } + install_backup_thread(domain_self); + CAML_EV_END(EV_DOMAIN_SPAWN); + CAMLreturn (Val_long(p.unique_id)); +} + +CAMLprim value caml_ml_domain_join(value domain) +{ + caml_failwith("domain.join unimplemented"); +} + +struct domain* caml_domain_self() +{ + return domain_self ? &domain_self->state : 0; +} + +struct domain* caml_owner_of_young_block(value v) { + int heap_id; + Assert(Is_young(v)); + heap_id = ((uintnat)v - caml_minor_heaps_base) / Minor_heap_max; + return &all_domains[heap_id].state; +} + +struct domain* caml_domain_of_id(int id) +{ + return &all_domains[id].state; +} + +CAMLprim value caml_ml_domain_id(value unit) +{ + return Val_int(domain_self->interruptor.unique_id); +} + +static const uintnat INTERRUPT_MAGIC = (uintnat)(-1); + +static void interrupt_domain(dom_internal* d) { + atomic_store_rel(d->interrupt_word_address, INTERRUPT_MAGIC); +} + +static struct { + atomic_uintnat domains_still_running; + atomic_uintnat num_domains_still_processing; + void (*callback)(struct domain*, void*, int participating_count, struct domain** others_participating); + void* data; + int leave_when_done; + int num_domains; + atomic_uintnat barrier; + void (*enter_spin_callback)(struct domain*, void*); + void* enter_spin_data; + void (*leave_spin_callback)(struct domain*, void*); + void* leave_spin_data; + + struct interrupt reqs[Max_domains]; + struct domain* participating[Max_domains]; +} stw_request = { + ATOMIC_UINTNAT_INIT(0), + ATOMIC_UINTNAT_INIT(0), + NULL, + NULL, + 0, + 0, + ATOMIC_UINTNAT_INIT(0), + NULL, + NULL, + NULL, + NULL, + { { 0 } }, + { 0 } +}; + +/* sense-reversing barrier */ +#define BARRIER_SENSE_BIT 0x100000 + +barrier_status caml_global_barrier_begin() +{ + uintnat b = 1 + atomic_fetch_add(&stw_request.barrier, 1); + return b; +} + +int caml_global_barrier_is_final(barrier_status b) +{ + return ((b & ~BARRIER_SENSE_BIT) == stw_request.num_domains); +} + +void caml_global_barrier_end(barrier_status b) +{ + uintnat sense = b & BARRIER_SENSE_BIT; + if (caml_global_barrier_is_final(b)) { + /* last domain into the barrier, flip sense */ + atomic_store_rel(&stw_request.barrier, sense ^ BARRIER_SENSE_BIT); + } else { + /* wait until another domain flips the sense */ + SPIN_WAIT { + uintnat barrier = atomic_load_acq(&stw_request.barrier); + if ((barrier & BARRIER_SENSE_BIT) != sense) break; + } + } +} + +void caml_global_barrier() +{ + barrier_status b = caml_global_barrier_begin(); + caml_global_barrier_end(b); +} + +int caml_global_barrier_num_domains() +{ + return stw_request.num_domains; +} + +int caml_global_barrier_leave_when_done() +{ + return stw_request.leave_when_done; +} + +static void decrement_stw_domains_still_processing() +{ + /* we check if we are the last to leave a stw section + if so, clear the stw_leader to allow the new stw sections to start. + */ + intnat am_last = atomic_fetch_add(&stw_request.num_domains_still_processing, -1) == 1; + + if( am_last ) { + /* release the STW lock to allow new STW sections */ + caml_plat_lock(&all_domains_lock); + atomic_store_rel(&stw_leader, 0); + caml_plat_broadcast(&all_domains_cond); + caml_gc_log("clearing stw leader"); + caml_plat_unlock(&all_domains_lock); + } +} + +static void caml_poll_gc_work(); +static void stw_handler(struct domain* domain, void* unused2, interrupt* done) +{ +#ifdef DEBUG + caml_domain_state* domain_state = Caml_state; +#endif + + CAML_EV_BEGIN(EV_STW_HANDLER); + caml_acknowledge_interrupt(done); + CAML_EV_BEGIN(EV_STW_API_BARRIER); + { + SPIN_WAIT { + if (atomic_load_acq(&stw_request.domains_still_running) == 0) + break; + caml_handle_incoming_interrupts(); + + if (stw_request.enter_spin_callback) + stw_request.enter_spin_callback(domain, stw_request.enter_spin_data); + } + } + CAML_EV_END(EV_STW_API_BARRIER); + + #ifdef DEBUG + domain_state->inside_stw_handler = 1; + #endif + stw_request.callback(domain, stw_request.data, stw_request.num_domains, stw_request.participating); + #ifdef DEBUG + domain_state->inside_stw_handler = 0; + #endif + + decrement_stw_domains_still_processing(); + + if( !stw_request.leave_when_done ) { + SPIN_WAIT { + if (atomic_load_acq(&stw_request.num_domains_still_processing) == 0) + break; + + if (stw_request.leave_spin_callback) + stw_request.leave_spin_callback(domain, stw_request.leave_spin_data); + } + } + + CAML_EV_END(EV_STW_HANDLER); + + /* poll the GC to check for deferred work + we do this here because blocking or waiting threads only execute + the interrupt handler and do not poll for deferred work*/ + caml_poll_gc_work(); +} + +/* This runs the passed handler on all running domains but must only be run on *one* domain + inside of a global barrier during a stop-the-world phase. */ +void caml_run_on_all_running_domains_during_stw(void (*handler)(struct domain*, void*), void* data) { + int i; + + for (i = 0; i < Max_domains; i++) { + struct interruptor* interruptor = &all_domains[i].interruptor; + + if( interruptor->running ) { + handler(&all_domains[i].state, data); + } + } +} + +#ifdef DEBUG +int caml_domain_is_in_stw() { + caml_domain_state* domain_state = Caml_state; + + return domain_state->inside_stw_handler; +} +#endif + +static int caml_send_partial_interrupt( + struct interruptor* target, + domain_rpc_handler handler, + void* data, + struct interrupt* req); +static void caml_wait_interrupt_acknowledged(struct interruptor* self, struct interrupt* req); + +int caml_try_run_on_all_domains_with_spin_work( + void (*handler)(struct domain*, void*, int, struct domain**), void* data, + void (*leader_setup)(struct domain*), + void (*enter_spin_callback)(struct domain*, void*), void* enter_spin_data, + void (*leave_spin_callback)(struct domain*, void*), void* leave_spin_data, + int leave_when_done + ) +{ +#ifdef DEBUG + caml_domain_state* domain_state = Caml_state; +#endif + int i; + uintnat domains_participating = 0; + + caml_gc_log("requesting STW"); + + // Don't take the lock if there's already a stw leader + if (atomic_load_acq(&stw_leader)) { + caml_handle_incoming_interrupts(); + return 0; + } + + /* Try to take the lock by setting ourselves as the stw_leader. + If it fails, handle interrupts (probably participating in + an STW section) and return. */ + caml_plat_lock(&all_domains_lock); + if (atomic_load_acq(&stw_leader)) { + caml_plat_unlock(&all_domains_lock); + caml_handle_incoming_interrupts(); + return 0; + } else { + atomic_store_rel(&stw_leader, (uintnat)domain_self); + } + caml_plat_unlock(&all_domains_lock); + + CAML_EV_BEGIN(EV_STW_LEADER); + caml_gc_log("causing STW"); + + /* setup all fields for this stw_request, must have those needed + for domains waiting at the enter spin barrier */ + stw_request.enter_spin_callback = enter_spin_callback; + stw_request.enter_spin_data = enter_spin_data; + stw_request.callback = handler; + stw_request.data = data; + stw_request.leave_spin_callback = leave_spin_callback; + stw_request.leave_spin_data = leave_spin_data; + stw_request.leave_when_done = leave_when_done; + atomic_store_rel(&stw_request.barrier, 0); + atomic_store_rel(&stw_request.domains_still_running, 1); + + if( leader_setup ) { + leader_setup(&domain_self->state); + } + + /* Next, interrupt all domains, counting how many domains received + the interrupt (i.e. are not terminated and are participating in + this STW section). */ + { + struct interrupt* reqs = stw_request.reqs; + struct domain** participating = stw_request.participating; + + for (i = 0; i < Max_domains; i++) { + if (&all_domains[i] == domain_self) { + participating[domains_participating] = &domain_self->state; + domains_participating++; + continue; + } + if (caml_send_partial_interrupt( + &all_domains[i].interruptor, + stw_handler, + 0, + &reqs[domains_participating])) { + participating[domains_participating] = &all_domains[i].state; + domains_participating++; + } + } + + for(i = 0; i < domains_participating ; i++) { + if( participating[i] && &domain_self->state != participating[i] ) { + caml_wait_interrupt_acknowledged(&domain_self->interruptor, &reqs[i]); + } + } + } + + Assert(domains_participating > 0); + + /* setup the domain_participating fields */ + stw_request.num_domains = domains_participating; + atomic_store_rel(&stw_request.num_domains_still_processing, + domains_participating); + + /* release from the enter barrier */ + atomic_store_rel(&stw_request.domains_still_running, 0); + + #ifdef DEBUG + domain_state->inside_stw_handler = 1; + #endif + handler(&domain_self->state, data, domains_participating, stw_request.participating); + #ifdef DEBUG + domain_state->inside_stw_handler = 0; + #endif + + decrement_stw_domains_still_processing(); + + if( !leave_when_done ) { + SPIN_WAIT { + if (atomic_load_acq(&stw_request.num_domains_still_processing) == 0) + break; + } + } + + CAML_EV_END(EV_STW_LEADER); + /* other domains might not have finished stw_handler yet, but they + will finish as soon as they notice num_domains_still_processing + == 0, which will remain the case until they have responded to + another interrupt from caml_run_on_all_domains */ + return 1; +} + +int caml_try_run_on_all_domains(void (*handler)(struct domain*, void*, int, struct domain**), void* data, void (*leader_setup)(struct domain*), int leave_when_done) +{ + return caml_try_run_on_all_domains_with_spin_work(handler, data, leader_setup, 0, 0, 0, 0, leave_when_done); +} + +void caml_interrupt_self() { + interrupt_domain(domain_self); +} + +/* Arrange for a major GC slice to be performed on the current domain + as soon as possible */ +void caml_request_major_slice (void) +{ + Caml_state->requested_major_slice = 1; + caml_interrupt_self(); +} + +/* Arrange for a minor GC to be performed on the current domain + as soon as possible */ +void caml_request_minor_gc (void) { - if (Caml_state != NULL) + Caml_state->requested_minor_gc = 1; + caml_interrupt_self(); +} + +static void caml_poll_gc_work() +{ + CAMLalloc_point_here; + + if (((uintnat)Caml_state->young_ptr - Bhsize_wosize(Max_young_wosize) < + (uintnat)Caml_state->young_start) || + Caml_state->requested_minor_gc) { + /* out of minor heap or collection forced */ + CAML_EV_BEGIN(EV_MINOR); + Caml_state->requested_minor_gc = 0; + caml_empty_minor_heaps_once(); + CAML_EV_END(EV_MINOR); + + /* FIXME: a domain will only ever call finalizers if its minor + heap triggers the minor collection + Care may be needed with finalizers running when the domain + is waiting in a critical_section or in a blocking section + and serviced by the backup thread. + */ + CAML_EV_BEGIN(EV_MINOR_FINALIZED); + caml_final_do_calls(); + CAML_EV_END(EV_MINOR_FINALIZED); + } + + if (Caml_state->requested_major_slice) { + CAML_EV_BEGIN(EV_MAJOR); + Caml_state->requested_major_slice = 0; + caml_major_collection_slice(AUTO_TRIGGERED_MAJOR_SLICE); + CAML_EV_END(EV_MAJOR); + } +} + +void caml_handle_gc_interrupt() +{ + atomic_uintnat* young_limit = domain_self->interrupt_word_address; + CAMLalloc_point_here; + + CAML_EV_BEGIN(EV_INTERRUPT_GC); + if (atomic_load_acq(young_limit) == INTERRUPT_MAGIC) { + /* interrupt */ + CAML_EV_BEGIN(EV_INTERRUPT_REMOTE); + while (atomic_load_acq(young_limit) == INTERRUPT_MAGIC) { + uintnat i = INTERRUPT_MAGIC; + atomic_compare_exchange_strong(young_limit, &i, (uintnat)Caml_state->young_start); + } + caml_handle_incoming_interrupts(); + CAML_EV_END(EV_INTERRUPT_REMOTE); + } + + caml_poll_gc_work(); + CAML_EV_END(EV_INTERRUPT_GC); +} + +CAMLexport inline int caml_bt_is_in_blocking_section(void) +{ + dom_internal* self = domain_self; + uintnat status = atomic_load_acq(&self->backup_thread_msg); + if (status == BT_IN_BLOCKING_SECTION) + return 1; + else + return 0; + +} + +CAMLexport void caml_acquire_domain_lock(void) +{ + dom_internal* self = domain_self; + caml_plat_lock(&self->domain_lock); + return; +} + +CAMLexport void caml_bt_enter_ocaml(void) +{ + dom_internal* self = domain_self; + + Assert(caml_domain_alone() || self->backup_thread_running); + + if (self->backup_thread_running) { + atomic_store_rel(&self->backup_thread_msg, BT_ENTERING_OCAML); + } + + return; +} + +CAMLexport void caml_release_domain_lock(void) +{ + dom_internal* self = domain_self; + caml_plat_unlock(&self->domain_lock); + return; +} + +CAMLexport void caml_bt_exit_ocaml(void) +{ + dom_internal* self = domain_self; + + Assert(caml_domain_alone() || self->backup_thread_running); + + if (self->backup_thread_running) { + atomic_store_rel(&self->backup_thread_msg, BT_IN_BLOCKING_SECTION); + /* Wakeup backup thread if it is sleeping */ + caml_plat_signal(&self->domain_cond); + } + + + return; +} + +static void caml_enter_blocking_section_default(void) +{ + caml_bt_exit_ocaml(); + caml_release_domain_lock(); + return; +} + +static void caml_leave_blocking_section_default(void) +{ + caml_bt_enter_ocaml(); + caml_acquire_domain_lock(); + return; +} + + +CAMLexport void (*caml_enter_blocking_section_hook)(void) = + caml_enter_blocking_section_default; +CAMLexport void (*caml_leave_blocking_section_hook)(void) = + caml_leave_blocking_section_default; + +CAMLexport void caml_leave_blocking_section() { + caml_leave_blocking_section_hook(); + caml_process_pending_signals(); +} + +CAMLexport void caml_enter_blocking_section() { + + caml_process_pending_signals(); + caml_enter_blocking_section_hook(); +} + +void caml_print_stats () { + struct gc_stats s; +#if defined(COLLECT_STATS) && defined(NATIVE_CODE) + struct detailed_stats ds; + caml_domain_state* st; + uint64_t total; + int i; +#endif + + caml_gc_stat(Val_unit); + caml_sample_gc_stats(&s); + fprintf(stderr,"**** GC stats ****\n"); + fprintf(stderr, "Minor words:\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u\n", + (uintnat)s.minor_words); + fprintf(stderr, "Promoted words:\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u\n", + (uintnat)s.promoted_words); + fprintf(stderr, "Major words:\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u\n", + (uintnat)s.major_words); + fprintf(stderr, "Minor collections:\t%"ARCH_INTNAT_PRINTF_FORMAT"u\n", + (uintnat)s.minor_collections); + fprintf(stderr, "Major collections:\t%"ARCH_INTNAT_PRINTF_FORMAT"u\n", + Caml_state->stat_major_collections); + +#if defined(COLLECT_STATS) && defined(NATIVE_CODE) + memset(&ds,0,sizeof(struct detailed_stats)); + for (i=0; i<Max_domains; i++) { + st = all_domains[i].state.state; + if (st) { + ds.allocations += st->allocations; + + ds.mutable_stores += st->mutable_stores; + ds.immutable_stores += st->immutable_stores; + + ds.mutable_loads += st->mutable_loads; + ds.immutable_loads += st->immutable_loads; + + ds.extcall_noalloc += st->extcall_noalloc; + ds.extcall_alloc += st->extcall_alloc; + ds.extcall_alloc_stackargs += st->extcall_alloc_stackargs; + + ds.tailcall_imm += st->tailcall_imm; + ds.tailcall_ind += st->tailcall_ind; + ds.call_imm += st->call_imm; + ds.call_ind += st->call_ind; + + ds.stackoverflow_checks += st->stackoverflow_checks; + } + } + fprintf(stderr, "\n**** Other stats ****\n"); + fprintf(stderr, "Allocations:\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u\n", ds.allocations); + + total = ds.mutable_loads + ds.immutable_loads; + fprintf(stderr, "\nLoads:\t\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u\n", total); + fprintf(stderr, "Mutable loads:\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u (%.2lf%%)\n", ds.mutable_loads, (double)ds.mutable_loads * 100.0 / total); + fprintf(stderr, "Immutable loads:\t%"ARCH_INTNAT_PRINTF_FORMAT"u (%.2lf%%)\n", ds.immutable_loads, (double)ds.immutable_loads * 100.0 / total); + + total = ds.mutable_stores + ds.immutable_stores; + fprintf(stderr, "\nStores:\t\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u\n", total); + fprintf(stderr, "Mutable stores:\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u (%.2lf%%)\n", ds.mutable_stores, (double)ds.mutable_stores * 100.0 / total); + fprintf(stderr, "Immutable stores:\t%"ARCH_INTNAT_PRINTF_FORMAT"u (%.2lf%%)\n", ds.immutable_stores, (double)ds.immutable_stores * 100.0 / total); + + total = ds.extcall_noalloc + ds.extcall_alloc + ds.extcall_alloc_stackargs; + fprintf(stderr, "\nExternal calls:\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u\n", total); + fprintf(stderr, "NoAlloc:\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u (%.2lf%%)\n", ds.extcall_noalloc, (double)ds.extcall_noalloc * 100.0 / total); + fprintf(stderr, "Alloc:\t\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u (%.2lf%%)\n", ds.extcall_alloc, (double)ds.extcall_alloc * 100.0 / total); + fprintf(stderr, "Alloc + stack args:\t%"ARCH_INTNAT_PRINTF_FORMAT"u (%.2lf%%)\n", ds.extcall_alloc_stackargs, (double)ds.extcall_alloc_stackargs * 100.0 / total); + + total = ds.tailcall_imm + ds.tailcall_ind + ds.call_imm + ds.call_ind; + fprintf(stderr, "\nCalls:\t\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u\n", total); + fprintf(stderr, "Imm tail:\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u (%.2lf%%)\n", ds.tailcall_imm, (double)ds.tailcall_imm * 100.0 / total); + fprintf(stderr, "Ind tail:\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u (%.2lf%%)\n", ds.tailcall_ind, (double)ds.tailcall_ind * 100.0 / total); + fprintf(stderr, "Imm non-tail:\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u (%.2lf%%)\n", ds.call_imm, (double)ds.call_imm * 100.0 / total); + fprintf(stderr, "Ind non-tail:\t\t%"ARCH_INTNAT_PRINTF_FORMAT"u (%.2lf%%)\n", ds.call_ind, (double)ds.call_ind * 100.0 / total); + + fprintf(stderr, "\nStackoverflow checks:\t%"ARCH_INTNAT_PRINTF_FORMAT"u (%.2lf%%)\n", ds.stackoverflow_checks, (double)ds.stackoverflow_checks * 100.0 / total); + +#endif +} + +CAMLexport int caml_domain_rpc(struct domain* domain, + domain_rpc_handler handler, void* data) +{ + return caml_send_interrupt(&domain_self->interruptor, &domain->internals->interruptor, + handler, data); +} + + + +/* Generate functions for accessing domain state variables in debug mode */ +#ifdef DEBUG + #define DOMAIN_STATE(type, name) \ + type get_##name() { return Caml_state->name; } + #include "caml/domain_state.tbl" + #undef DOMAIN_STATE +#endif + +/* Sending interrupts between domains. + + To avoid deadlock, some rules are important: + + - Don't hold interruptor locks for long + - Don't hold two interruptor locks at the same time + - Continue to handle incoming interrupts even when waiting for a response */ + +/* must be called with s->lock held */ +static uintnat handle_incoming(struct interruptor* s) +{ + uintnat handled = 0; + Assert (s->running); + while (s->qhead != NULL) { + struct interrupt* req = s->qhead; + s->qhead = req->next; + /* Unlock s while the handler runs, to allow other + domains to send us messages. This is necessary to + avoid deadlocks, since the handler might send + interrupts */ + caml_plat_unlock(&s->lock); + + req->handler(caml_domain_self(), req->data, req); + + caml_plat_lock(&s->lock); + handled++; + } + return handled; +} + +void caml_acknowledge_interrupt(struct interrupt* req) +{ + atomic_store_rel(&req->acknowledged, 1); +} + +static void acknowledge_all_pending_interrupts() +{ + Assert(Caml_state->critical_section_nesting == 0); + while (Caml_state->pending_interrupts) { + interrupt* curr = Caml_state->pending_interrupts; + Caml_state->pending_interrupts = curr->next; + caml_acknowledge_interrupt(curr); + } +} + +static void handover_ephemerons(caml_domain_state* domain_state) +{ + if (domain_state->ephe_info->todo == 0 && + domain_state->ephe_info->live == 0) + return; + + caml_add_to_orphaned_ephe_list(domain_state->ephe_info); + if (domain_state->ephe_info->todo != 0) { + caml_ephe_todo_list_emptied(); + } + domain_state->ephe_info->live = 0; + domain_state->ephe_info->todo = 0; +} + +static void handover_finalisers(caml_domain_state* domain_state) +{ + struct caml_final_info* f = domain_state->final_info; + + if (f->todo_head != NULL || f->first.size != 0 || f->last.size != 0) { + /* have some final structures */ + if (caml_gc_phase != Phase_sweep_and_mark_main) { + /* Force a major GC to simplify constraints for + * handing over ephemerons. */ + caml_gc_major(Val_unit); + } + caml_add_orphaned_finalisers (f); + /* Create a dummy final info */ + domain_state->final_info = caml_alloc_final_info(); + } + caml_final_domain_terminate(domain_state); +} + +int caml_domain_is_terminating () +{ + struct interruptor* s = &domain_self->interruptor; + return s->terminating; +} + +static void domain_terminate() +{ + caml_domain_state* domain_state = domain_self->state.state; + struct interruptor* s = &domain_self->interruptor; + int finished = 0; + + caml_gc_log("Domain terminating"); + caml_delete_root(domain_state->dls_root); + s->terminating = 1; + + while (!finished) { + caml_orphan_allocated_words(); + caml_finish_sweeping(); + + caml_empty_minor_heaps_once(); + + caml_finish_marking(); + handover_ephemerons(domain_state); + handover_finalisers(domain_state); + + caml_plat_lock(&s->lock); + + /* The interaction of termination and major GC is quite subtle. + * + * At the end of the major GC, we decide the number of domains to mark and + * sweep for the next cycle. If the following [handle_incoming] participates + * in a major GC cycle, then we need to finish marking and sweeping again in + * order to decrement the globals [num_domains_to_mark] and + * [num_domains_to_sweep] (see major_gc.c). Luckily, if the following + * [handle_incoming] does participate in a major GC cycle, then + * [Caml_state->sweeping_done] will be set to 0 making conditional check to + * fail, which forces this domain to finish marking and sweeping again. + */ + + if (handle_incoming(s) == 0 && + Caml_state->marking_done && + Caml_state->sweeping_done) { + + finished = 1; + s->terminating = 0; + s->running = 0; + s->unique_id += Max_domains; + + /* signal the interruptor condition variable + * because the backup thread may be waiting on it + */ + caml_plat_broadcast(&s->cond); + Assert (domain_self->backup_thread_running); + domain_self->backup_thread_running = 0; + } + caml_plat_unlock(&s->lock); + } + caml_sample_gc_collect(domain_state); + + caml_stat_free(domain_state->final_info); + // run the domain termination hook + caml_domain_stop_hook(); + caml_stat_free(domain_state->ephe_info); + caml_teardown_major_gc(); + caml_teardown_shared_heap(domain_state->shared_heap); + domain_state->shared_heap = 0; + caml_free_minor_tables(domain_state->minor_tables); + domain_state->minor_tables = 0; + caml_free_signal_stack(); + + if(domain_state->current_stack != NULL) { + caml_free_stack(domain_state->current_stack); + } + + if (Caml_state->critical_section_nesting) { + Caml_state->critical_section_nesting = 0; + acknowledge_all_pending_interrupts(); + } + + atomic_store_rel(&domain_self->backup_thread_msg, BT_TERMINATE); + caml_plat_signal(&domain_self->domain_cond); + caml_plat_unlock(&domain_self->domain_lock); + + caml_plat_assert_all_locks_unlocked(); + /* This is the last thing we do because we need to be able to rely + on caml_domain_alone (which uses caml_num_domains_running) in at least + the shared_heap lockfree fast paths */ + atomic_fetch_add(&caml_num_domains_running, -1); +} + +int caml_incoming_interrupts_queued() +{ + return domain_self->interruptor.qhead != NULL; +} + +static inline void handle_incoming_interrupts(struct interruptor* s, int otherwise_relax) +{ + if (s->qhead != NULL) { + caml_plat_lock(&s->lock); + handle_incoming(s); + caml_plat_unlock(&s->lock); + } else if (otherwise_relax) { + cpu_relax(); + } +} + +static void handle_incoming_otherwise_relax (struct interruptor* self) +{ + handle_incoming_interrupts(self, 1); +} + +void caml_handle_incoming_interrupts() +{ + handle_incoming_interrupts(&domain_self->interruptor, 0); +} + +static void caml_wait_interrupt_acknowledged (struct interruptor* self, + struct interrupt* req) +{ + int i; + + /* Often, interrupt handlers are fast, so spin for a bit before waiting */ + for (i=0; i<1000; i++) { + if (atomic_load_acq(&req->acknowledged)) { + return; + } + cpu_relax(); + } + + { + SPIN_WAIT { + if (atomic_load_acq(&req->acknowledged)) + return; + handle_incoming_otherwise_relax(self); + } + } + + return; +} + +int caml_send_partial_interrupt( + struct interruptor* target, + domain_rpc_handler handler, + void* data, + struct interrupt* req) +{ + req->handler = handler; + req->data = data; + atomic_store_rel(&req->acknowledged, 0); + req->next = NULL; + + caml_plat_lock(&target->lock); + if (!target->running) { + caml_plat_unlock(&target->lock); + return 0; + } + + /* add to wait queue */ + if (target->qhead) { + /* queue was nonempty */ + target->qtail->next = req; + target->qtail = req; + } else { + /* queue was empty */ + target->qhead = target->qtail = req; + } + /* Signal the condition variable, in case the target is + itself waiting for an interrupt to be processed elsewhere */ + caml_plat_broadcast(&target->cond); // OPT before/after unlock? elide? + caml_plat_unlock(&target->lock); + + atomic_store_rel(target->interrupt_word, INTERRUPT_MAGIC); //FIXME dup + + return 1; +} + +int caml_send_interrupt(struct interruptor* self, + struct interruptor* target, + domain_rpc_handler handler, + void* data) +{ + struct interrupt req; + if (!caml_send_partial_interrupt(target, handler, data, &req)) + return 0; + caml_wait_interrupt_acknowledged(self, &req); + return 1; +} + + +CAMLprim value caml_ml_domain_critical_section(value delta) +{ + intnat crit = Caml_state->critical_section_nesting + Long_val(delta); + Caml_state->critical_section_nesting = crit; + if (crit < 0) { + caml_fatal_error("invalid critical section nesting"); + } else if (crit == 0) { + acknowledge_all_pending_interrupts(); + } + return Val_unit; +} + +#define Chunk_size 0x400 + +CAMLprim value caml_ml_domain_yield(value unused) +{ + struct interruptor* s = &domain_self->interruptor; + int found_work = 1; + intnat left; + + if (Caml_state->critical_section_nesting == 0) { + caml_failwith("Domain.Sync.wait must be called from within a critical section"); + } + + caml_plat_lock(&s->lock); + while (!Caml_state->pending_interrupts) { + if (handle_incoming(s) == 0 && !found_work) { + CAML_EV_BEGIN(EV_DOMAIN_IDLE_WAIT); + caml_plat_wait(&s->cond); + CAML_EV_END(EV_DOMAIN_IDLE_WAIT); + } else { + caml_plat_unlock(&s->lock); + left = caml_opportunistic_major_collection_slice(Chunk_size); + if (left == Chunk_size) + found_work = 0; + caml_plat_lock(&s->lock); + } + } + caml_plat_unlock(&s->lock); + + return Val_unit; +} + +static void handle_ml_interrupt(struct domain* d, void* unique_id_p, interrupt* req) +{ + if (d->internals->interruptor.unique_id != *(uintnat*)unique_id_p) { + caml_acknowledge_interrupt(req); return; + } + if (d->state->critical_section_nesting > 0) { + req->next = d->state->pending_interrupts; + d->state->pending_interrupts = req; + } else { + caml_acknowledge_interrupt(req); + } +} + +CAMLprim value caml_ml_domain_interrupt(value domain) +{ + CAMLparam1 (domain); + uintnat unique_id = (uintnat)Long_val(domain); + struct interruptor* target = + &all_domains[unique_id % Max_domains].interruptor; - Caml_state = - (caml_domain_state*)caml_stat_alloc_noexc(sizeof(caml_domain_state)); - if (Caml_state == NULL) - caml_fatal_error ("cannot initialize domain state"); - - Caml_state->young_limit = NULL; - Caml_state->exception_pointer = NULL; - - Caml_state->young_ptr = NULL; - Caml_state->young_base = NULL; - Caml_state->young_start = NULL; - Caml_state->young_end = NULL; - Caml_state->young_alloc_start = NULL; - Caml_state->young_alloc_mid = NULL; - Caml_state->young_alloc_end = NULL; - Caml_state->young_trigger = NULL; - Caml_state->minor_heap_wsz = 0; - Caml_state->in_minor_collection = 0; - Caml_state->extra_heap_resources_minor = 0; - caml_alloc_minor_tables(); - - Caml_state->stack_low = NULL; - Caml_state->stack_high = NULL; - Caml_state->stack_threshold = NULL; - Caml_state->extern_sp = NULL; - Caml_state->trapsp = NULL; - Caml_state->trap_barrier = NULL; - Caml_state->external_raise = NULL; - Caml_state->exn_bucket = Val_unit; - - Caml_state->top_of_stack = NULL; - Caml_state->bottom_of_stack = NULL; /* no stack initially */ - Caml_state->last_return_address = 1; /* not in OCaml code initially */ - Caml_state->gc_regs = NULL; - - Caml_state->stat_minor_words = 0.0; - Caml_state->stat_promoted_words = 0.0; - Caml_state->stat_major_words = 0.0; - Caml_state->stat_minor_collections = 0; - Caml_state->stat_major_collections = 0; - Caml_state->stat_heap_wsz = 0; - Caml_state->stat_top_heap_wsz = 0; - Caml_state->stat_compactions = 0; - Caml_state->stat_forced_major_collections = 0; - Caml_state->stat_heap_chunks = 0; - - Caml_state->backtrace_active = 0; - Caml_state->backtrace_pos = 0; - Caml_state->backtrace_buffer = NULL; - Caml_state->backtrace_last_exn = Val_unit; - - Caml_state->compare_unordered = 0; - Caml_state->local_roots = NULL; - Caml_state->requested_major_slice = 0; - Caml_state->requested_minor_gc = 0; - - Caml_state->eventlog_enabled = 0; - Caml_state->eventlog_paused = 0; - Caml_state->eventlog_startup_pid = 0; - Caml_state->eventlog_startup_timestamp = 0; - Caml_state->eventlog_out = NULL; + CAML_EV_BEGIN(EV_DOMAIN_SEND_INTERRUPT); + if (!caml_send_interrupt(&domain_self->interruptor, target, &handle_ml_interrupt, &unique_id)) { + /* the domain might have terminated, but that's fine */ + } + CAML_EV_END(EV_DOMAIN_SEND_INTERRUPT); + + CAMLreturn (Val_unit); +} + +CAMLprim int64_t caml_ml_domain_ticks_unboxed(value unused) +{ + return caml_time_counter() - startup_timestamp; +} + +CAMLprim value caml_ml_domain_ticks(value unused) +{ + return caml_copy_int64(caml_ml_domain_ticks_unboxed(unused)); +} + +CAMLprim value caml_ml_domain_yield_until(value t) +{ + int64_t ts = Int64_val(t) + startup_timestamp; + struct interruptor* s = &domain_self->interruptor; + value ret = Val_int(1); /* Domain.Sync.Notify */ + int res; + intnat left; + int found_work = 1; + + if (Caml_state->critical_section_nesting == 0){ + caml_failwith("Domain.Sync.wait_until must be called from within a critical section"); + } + + caml_plat_lock(&s->lock); + + while (!Caml_state->pending_interrupts) { + if (ts < caml_time_counter ()) { + ret = Val_int(0); /* Domain.Sync.Timeout */ + break; + } else if (handle_incoming(s) == 0 && !found_work) { + CAML_EV_BEGIN(EV_DOMAIN_IDLE_WAIT); + res = caml_plat_timedwait(&s->cond, ts); + CAML_EV_END(EV_DOMAIN_IDLE_WAIT); + if (res) { + ret = Val_int(0); /* Domain.Sync.Timeout */ + break; + } + } else { + caml_plat_unlock(&s->lock); + left = caml_opportunistic_major_collection_slice(Chunk_size); + if (left == Chunk_size) + found_work = 0; + caml_plat_lock(&s->lock); + } + } + + caml_plat_unlock(&s->lock); + + return ret; +} + +CAMLprim value caml_ml_domain_cpu_relax(value t) +{ + struct interruptor* self = &domain_self->interruptor; + handle_incoming_otherwise_relax (self); + return Val_unit; +} + +CAMLprim value caml_domain_dls_set(value t) +{ + CAMLnoalloc; + caml_modify_root(Caml_state->dls_root, t); + return Val_unit; +} + +CAMLprim value caml_domain_dls_get(value unused) +{ + CAMLnoalloc; + return caml_read_root(Caml_state->dls_root); } diff --git a/runtime/dynlink_nat.c b/runtime/dynlink_nat.c index 6a824d35aa..0bd8b0e0d4 100644 --- a/runtime/dynlink_nat.c +++ b/runtime/dynlink_nat.c @@ -25,6 +25,8 @@ #include "caml/intext.h" #include "caml/osdeps.h" #include "caml/fail.h" +#include "frame_descriptors.h" +#include "caml/globroots.h" #include "caml/signals.h" #ifdef WITH_SPACETIME #include "caml/spacetime.h" @@ -54,6 +56,8 @@ static void *getsym(void *handle, const char *module, const char *name){ return sym; } +extern char caml_globals_map[]; + CAMLprim value caml_natdynlink_getmap(value unit) { return caml_input_value_from_block(caml_globals_map, INT_MAX); @@ -119,16 +123,12 @@ CAMLprim value caml_natdynlink_run(value handle_v, value symbol) { sym = optsym("__gc_roots"); if (NULL != sym) caml_register_dyn_global(sym); - sym = optsym("__data_begin"); - sym2 = optsym("__data_end"); - if (NULL != sym && NULL != sym2) - caml_page_table_add(In_static_data, sym, sym2); - sym = optsym("__code_begin"); sym2 = optsym("__code_end"); - if (NULL != sym && NULL != sym2) + if (NULL != sym && NULL != sym2) { caml_register_code_fragment((char *) sym, (char *) sym2, DIGEST_LATER, NULL); + } if( caml_natdynlink_hook != NULL ) caml_natdynlink_hook(handle,unit); diff --git a/runtime/extern.c b/runtime/extern.c index 34143f7493..e66ef985f1 100644 --- a/runtime/extern.c +++ b/runtime/extern.c @@ -480,210 +480,9 @@ static void writecode64(int code, intnat val) } #endif -/* Marshaling integers */ - -Caml_inline void extern_int(intnat n) -{ - if (n >= 0 && n < 0x40) { - write(PREFIX_SMALL_INT + n); - } else if (n >= -(1 << 7) && n < (1 << 7)) { - writecode8(CODE_INT8, n); - } else if (n >= -(1 << 15) && n < (1 << 15)) { - writecode16(CODE_INT16, n); -#ifdef ARCH_SIXTYFOUR - } else if (n < -((intnat)1 << 30) || n >= ((intnat)1 << 30)) { - if (extern_flags & COMPAT_32) - extern_failwith("output_value: integer cannot be read back on " - "32-bit platform"); - writecode64(CODE_INT64, n); -#endif - } else { - writecode32(CODE_INT32, n); - } -} - -/* Marshaling references to previously-marshaled blocks */ - -Caml_inline void extern_shared_reference(uintnat d) -{ - if (d < 0x100) { - writecode8(CODE_SHARED8, d); - } else if (d < 0x10000) { - writecode16(CODE_SHARED16, d); -#ifdef ARCH_SIXTYFOUR - } else if (d >= (uintnat)1 << 32) { - writecode64(CODE_SHARED64, d); -#endif - } else { - writecode32(CODE_SHARED32, d); - } -} - -/* Marshaling block headers */ - -Caml_inline void extern_header(mlsize_t sz, tag_t tag) -{ - if (tag < 16 && sz < 8) { - write(PREFIX_SMALL_BLOCK + tag + (sz << 4)); - } else { - header_t hd = Make_header(sz, tag, Caml_white); -#ifdef ARCH_SIXTYFOUR - if (sz > 0x3FFFFF && (extern_flags & COMPAT_32)) - extern_failwith("output_value: array cannot be read back on " - "32-bit platform"); - if (hd < (uintnat)1 << 32) - writecode32(CODE_BLOCK32, hd); - else - writecode64(CODE_BLOCK64, hd); -#else - writecode32(CODE_BLOCK32, hd); -#endif - } -} - -/* Marshaling strings */ - -Caml_inline void extern_string(value v, mlsize_t len) -{ - if (len < 0x20) { - write(PREFIX_SMALL_STRING + len); - } else if (len < 0x100) { - writecode8(CODE_STRING8, len); - } else { -#ifdef ARCH_SIXTYFOUR - if (len > 0xFFFFFB && (extern_flags & COMPAT_32)) - extern_failwith("output_value: string cannot be read back on " - "32-bit platform"); - if (len < (uintnat)1 << 32) - writecode32(CODE_STRING32, len); - else - writecode64(CODE_STRING64, len); -#else - writecode32(CODE_STRING32, len); -#endif - } - writeblock(String_val(v), len); -} - -/* Marshaling FP numbers */ - -Caml_inline void extern_double(value v) -{ - write(CODE_DOUBLE_NATIVE); - writeblock_float8((double *) v, 1); -} - -/* Marshaling FP arrays */ - -Caml_inline void extern_double_array(value v, mlsize_t nfloats) -{ - if (nfloats < 0x100) { - writecode8(CODE_DOUBLE_ARRAY8_NATIVE, nfloats); - } else { -#ifdef ARCH_SIXTYFOUR - if (nfloats > 0x1FFFFF && (extern_flags & COMPAT_32)) - extern_failwith("output_value: float array cannot be read back on " - "32-bit platform"); - if (nfloats < (uintnat) 1 << 32) - writecode32(CODE_DOUBLE_ARRAY32_NATIVE, nfloats); - else - writecode64(CODE_DOUBLE_ARRAY64_NATIVE, nfloats); -#else - writecode32(CODE_DOUBLE_ARRAY32_NATIVE, nfloats); -#endif - } - writeblock_float8((double *) v, nfloats); -} - -/* Marshaling custom blocks */ - -Caml_inline void extern_custom(value v, - /*out*/ uintnat * sz_32, - /*out*/ uintnat * sz_64) -{ - char * size_header; - char const * ident = Custom_ops_val(v)->identifier; - void (*serialize)(value v, uintnat * bsize_32, uintnat * bsize_64) - = Custom_ops_val(v)->serialize; - const struct custom_fixed_length* fixed_length - = Custom_ops_val(v)->fixed_length; - if (serialize == NULL) - extern_invalid_argument("output_value: abstract value (Custom)"); - if (fixed_length == NULL) { - write(CODE_CUSTOM_LEN); - writeblock(ident, strlen(ident) + 1); - /* Reserve 12 bytes for the lengths (sz_32 and sz_64). */ - if (extern_ptr + 12 >= extern_limit) grow_extern_output(12); - size_header = extern_ptr; - extern_ptr += 12; - serialize(v, sz_32, sz_64); - /* Store length before serialized block */ - store32(size_header, *sz_32); - store64(size_header + 4, *sz_64); - } else { - write(CODE_CUSTOM_FIXED); - writeblock(ident, strlen(ident) + 1); - serialize(v, sz_32, sz_64); - if (*sz_32 != fixed_length->bsize_32 || - *sz_64 != fixed_length->bsize_64) - caml_fatal_error( - "output_value: incorrect fixed sizes specified by %s", - ident); - } -} - -/* Marshaling code pointers */ - -static void extern_code_pointer(char * codeptr) -{ - struct code_fragment * cf; - const char * digest; - - cf = caml_find_code_fragment_by_pc(codeptr); - if (cf != NULL) { - if ((extern_flags & CLOSURES) == 0) - extern_invalid_argument("output_value: functional value"); - digest = (const char *) caml_digest_of_code_fragment(cf); - if (digest == NULL) - extern_invalid_argument("output_value: private function"); - writecode32(CODE_CODEPOINTER, codeptr - cf->code_start); - writeblock(digest, 16); - } else { - extern_invalid_argument("output_value: abstract value (outside heap)"); - } -} - -/* Marshaling the non-environment part of closures */ - -#ifdef NO_NAKED_POINTERS -Caml_inline mlsize_t extern_closure_up_to_env(value v) -{ - mlsize_t startenv, i; - value info; - - startenv = Start_env_closinfo(Closinfo_val(v)); - i = 0; - do { - /* The infix header */ - if (i > 0) extern_int(Long_val(Field(v, i++))); - /* The default entry point */ - extern_code_pointer((char *) Field(v, i++)); - /* The closure info. */ - info = Field(v, i++); - extern_int(Long_val(info)); - /* The direct entry point if arity is neither 0 nor 1 */ - if (Arity_closinfo(info) != 0 && Arity_closinfo(info) != 1) { - extern_code_pointer((char *) Field(v, i++)); - } - } while (i < startenv); - CAMLassert(i == startenv); - return startenv; -} -#endif - /* Marshal the given value in the output buffer */ -int caml_extern_allow_out_of_heap = 0; +int caml_extern_allow_out_of_heap = 0; /* TODO: not implemented in multicore */ static void extern_rec(value v) { @@ -696,14 +495,25 @@ static void extern_rec(value v) while(1) { if (Is_long(v)) { - extern_int(Long_val(v)); - } - else if (! (Is_in_value_area(v) || caml_extern_allow_out_of_heap)) { - /* Naked pointer outside the heap: try to marshal it as a code pointer, - otherwise fail. */ - extern_code_pointer((char *) v); - } - else { + intnat n = Long_val(v); + if (n >= 0 && n < 0x40) { + write(PREFIX_SMALL_INT + n); + } else if (n >= -(1 << 7) && n < (1 << 7)) { + writecode8(CODE_INT8, n); + } else if (n >= -(1 << 15) && n < (1 << 15)) { + writecode16(CODE_INT16, n); +#ifdef ARCH_SIXTYFOUR + } else if (n < -((intnat)1 << 30) || n >= ((intnat)1 << 30)) { + if (extern_flags & COMPAT_32) + extern_failwith("output_value: integer cannot be read back on " + "32-bit platform"); + writecode64(CODE_INT64, n); +#endif + } else + writecode32(CODE_INT32, n); + goto next_item; + } else { + /* NB: in multicore we do not guard for extern_allow_out_of_heap */ header_t hd = Hd_val(v); tag_t tag = Tag_hd(hd); mlsize_t sz = Wosize_hd(hd); @@ -711,11 +521,9 @@ static void extern_rec(value v) if (tag == Forward_tag) { value f = Forward_val (v); if (Is_block (f) - && (!Is_in_value_area(f) || Tag_val (f) == Forward_tag + && ( Tag_val (f) == Forward_tag || Tag_val (f) == Lazy_tag -#ifdef FLAT_FLOAT_ARRAY || Tag_val (f) == Double_tag -#endif )){ /* Do not short-circuit the pointer. */ }else{ @@ -726,29 +534,68 @@ static void extern_rec(value v) /* Atoms are treated specially for two reasons: they are not allocated in the externed block, and they are automatically shared. */ if (sz == 0) { - extern_header(0, tag); + if (tag < 16) { + write(PREFIX_SMALL_BLOCK + tag); + } else { +#ifdef WITH_PROFINFO + writecode32(CODE_BLOCK32, Hd_no_profinfo(hd)); +#else + writecode32(CODE_BLOCK32, hd); +#endif + } goto next_item; } /* Check if object already seen */ if (! (extern_flags & NO_SHARING)) { if (extern_lookup_position(v, &pos, &h)) { - extern_shared_reference(obj_counter - pos); + uintnat d = obj_counter - pos; + if (d < 0x100) { + writecode8(CODE_SHARED8, d); + } else if (d < 0x10000) { + writecode16(CODE_SHARED16, d); +#ifdef ARCH_SIXTYFOUR + } else if (d >= (uintnat)1 << 32) { + writecode64(CODE_SHARED64, d); +#endif + } else { + writecode32(CODE_SHARED32, d); + } goto next_item; } } + /* Output the contents of the object */ switch(tag) { case String_tag: { mlsize_t len = caml_string_length(v); - extern_string(v, len); + if (len < 0x20) { + write(PREFIX_SMALL_STRING + len); + } else if (len < 0x100) { + writecode8(CODE_STRING8, len); + } else { +#ifdef ARCH_SIXTYFOUR + if (len > 0xFFFFFB && (extern_flags & COMPAT_32)) + extern_failwith("output_value: string cannot be read back on " + "32-bit platform"); + if (len < (uintnat)1 << 32) + writecode32(CODE_STRING32, len); + else + writecode64(CODE_STRING64, len); +#else + writecode32(CODE_STRING32, len); +#endif + } + writeblock(String_val(v), len); size_32 += 1 + (len + 4) / 4; size_64 += 1 + (len + 8) / 8; extern_record_location(v, h); break; } case Double_tag: { - CAMLassert(sizeof(double) == 8); - extern_double(v); + if (sizeof(double) != 8) + extern_invalid_argument("output_value: non-standard floats"); + write(CODE_DOUBLE_NATIVE); + writeblock_float8((double *) v, 1); size_32 += 1 + 2; size_64 += 1 + 1; extern_record_location(v, h); @@ -756,9 +603,25 @@ static void extern_rec(value v) } case Double_array_tag: { mlsize_t nfloats; - CAMLassert(sizeof(double) == 8); + if (sizeof(double) != 8) + extern_invalid_argument("output_value: non-standard floats"); nfloats = Wosize_val(v) / Double_wosize; - extern_double_array(v, nfloats); + if (nfloats < 0x100) { + writecode8(CODE_DOUBLE_ARRAY8_NATIVE, nfloats); + } else { +#ifdef ARCH_SIXTYFOUR + if (nfloats > 0x1FFFFF && (extern_flags & COMPAT_32)) + extern_failwith("output_value: float array cannot be read back on " + "32-bit platform"); + if (nfloats < (uintnat) 1 << 32) + writecode32(CODE_DOUBLE_ARRAY32_NATIVE, nfloats); + else + writecode64(CODE_DOUBLE_ARRAY64_NATIVE, nfloats); +#else + writecode32(CODE_DOUBLE_ARRAY32_NATIVE, nfloats); +#endif + } + writeblock_float8((double *) v, nfloats); size_32 += 1 + nfloats * 2; size_64 += 1 + nfloats; extern_record_location(v, h); @@ -767,53 +630,85 @@ static void extern_rec(value v) case Abstract_tag: extern_invalid_argument("output_value: abstract value (Abstract)"); break; + case Closure_tag: + caml_failwith("Serializing closures is broken in multicore"); + break; case Infix_tag: writecode32(CODE_INFIXPOINTER, Infix_offset_hd(hd)); v = v - Infix_offset_hd(hd); /* PR#5772 */ continue; case Custom_tag: { uintnat sz_32, sz_64; - extern_custom(v, &sz_32, &sz_64); + char * size_header; + char const * ident = Custom_ops_val(v)->identifier; + void (*serialize)(value v, uintnat * bsize_32, + uintnat * bsize_64) + = Custom_ops_val(v)->serialize; + const struct custom_fixed_length* fixed_length + = Custom_ops_val(v)->fixed_length; + if (serialize == NULL) + extern_invalid_argument("output_value: abstract value (Custom)"); + if (fixed_length == NULL) { + write(CODE_CUSTOM_LEN); + writeblock(ident, strlen(ident) + 1); + /* Reserve 12 bytes for the lengths (sz_32 and sz_64). */ + if (extern_ptr + 12 >= extern_limit) grow_extern_output(12); + size_header = extern_ptr; + extern_ptr += 12; + serialize(v, &sz_32, &sz_64); + /* Store length before serialized block */ + store32(size_header, sz_32); + store64(size_header + 4, sz_64); + } else { + write(CODE_CUSTOM_FIXED); + writeblock(ident, strlen(ident) + 1); + serialize(v, &sz_32, &sz_64); + if (sz_32 != fixed_length->bsize_32 || + sz_64 != fixed_length->bsize_64) + caml_fatal_error( + "output_value: incorrect fixed sizes specified by %s", + ident); + } size_32 += 2 + ((sz_32 + 3) >> 2); /* header + ops + data */ size_64 += 2 + ((sz_64 + 7) >> 3); extern_record_location(v, h); break; } -#ifdef NO_NAKED_POINTERS - case Closure_tag: { - mlsize_t i; - extern_header(sz, tag); - size_32 += 1 + sz; - size_64 += 1 + sz; - extern_record_location(v, h); - i = extern_closure_up_to_env(v); - if (i >= sz) goto next_item; - /* Remember that we still have to serialize fields i + 1 ... sz - 1 */ - if (i < sz - 1) { - sp++; - if (sp >= extern_stack_limit) sp = extern_resize_stack(sp); - sp->v = &Field(v, i + 1); - sp->count = sz - i - 1; - } - /* Continue serialization with the first environment field */ - v = Field(v, i); - continue; - } -#endif default: { - extern_header(sz, tag); + value field0; + if (tag < 16 && sz < 8) { + write(PREFIX_SMALL_BLOCK + tag + (sz << 4)); + } else { +#ifdef ARCH_SIXTYFOUR +#ifdef WITH_PROFINFO + header_t hd_erased = Hd_no_profinfo(hd); +#else + header_t hd_erased = hd; +#endif + if (sz > 0x3FFFFF && (extern_flags & COMPAT_32)) + extern_failwith("output_value: array cannot be read back on " + "32-bit platform"); + if (hd_erased < (uintnat)1 << 32) + writecode32(CODE_BLOCK32, Whitehd_hd (hd_erased)); + else + writecode64(CODE_BLOCK64, Whitehd_hd (hd_erased)); +#else + writecode32(CODE_BLOCK32, Whitehd_hd (hd)); +#endif + } size_32 += 1 + sz; size_64 += 1 + sz; + field0 = Field(v, 0); extern_record_location(v, h); /* Remember that we still have to serialize fields 1 ... sz - 1 */ if (sz > 1) { sp++; if (sp >= extern_stack_limit) sp = extern_resize_stack(sp); - sp->v = &Field(v, 1); - sp->count = sz - 1; + sp->v = &Field(v,1); + sp->count = sz-1; } /* Continue serialization with the first field */ - v = Field(v, 0); + v = field0; continue; } } @@ -908,9 +803,9 @@ CAMLprim value caml_output_value(value vchan, value v, value flags) CAMLparam3 (vchan, v, flags); struct channel * channel = Channel(vchan); - Lock(channel); - caml_output_val(channel, v, flags); - Unlock(channel); + With_mutex(&channel-> mutex, { + caml_output_val(channel, v, flags); + } ); CAMLreturn (Val_unit); } @@ -1139,15 +1034,12 @@ CAMLprim value caml_obj_reachable_words(value v) extern_init_position_table(); sp = extern_stack; size = 0; + /* In multicore we don't distinguish + between major heap blocks and out-of-heap blocks + so we end up counting out-of-heap blocks too. */ while (1) { if (Is_long(v)) { /* Tagged integers contribute 0 to the size, nothing to do */ - } else if (! Is_in_heap_or_young(v)) { - /* Out-of-heap blocks contribute 0 to the size, nothing to do */ - /* However, in no-naked-pointers mode, we don't distinguish - between major heap blocks and out-of-heap blocks, - and the test above is always false, - so we end up counting out-of-heap blocks too. */ } else if (extern_lookup_position(v, &pos, &h)) { /* Already seen and counted, nothing to do */ } else { diff --git a/runtime/fail_byt.c b/runtime/fail_byt.c index b2e8d8b78f..d876c0f146 100644 --- a/runtime/fail_byt.c +++ b/runtime/fail_byt.c @@ -29,14 +29,25 @@ #include "caml/mlvalues.h" #include "caml/printexc.h" #include "caml/signals.h" -#include "caml/stacks.h" +#include "caml/fiber.h" CAMLexport void caml_raise(value v) { - Unlock_exn(); - Caml_state->exn_bucket = v; - if (Caml_state->external_raise == NULL) caml_fatal_uncaught_exception(v); - siglongjmp(Caml_state->external_raise->buf, 1); + caml_domain_state* domain_state = Caml_state; + if (domain_state->external_raise == NULL) caml_fatal_uncaught_exception(v); + *domain_state->external_raise->exn_bucket = v; + while (domain_state->local_roots != Caml_state->external_raise->local_roots) { + struct caml__mutex_unwind* m; + Assert(domain_state->local_roots != NULL); + m = domain_state->local_roots->mutexes; + while (m) { + /* unlocked in reverse order of locking */ + caml_plat_unlock(m->mutex); + m = m->next; + } + domain_state->local_roots = domain_state->local_roots->next; + } + siglongjmp(domain_state->external_raise->jmp->buf, 1); } CAMLexport void caml_raise_constant(value tag) @@ -60,7 +71,7 @@ CAMLexport void caml_raise_with_args(value tag, int nargs, value args[]) { CAMLparam1 (tag); CAMLxparamN (args, nargs); - value bucket; + CAMLlocal1(bucket); int i; CAMLassert(1 + nargs <= Max_young_wosize); @@ -91,15 +102,15 @@ CAMLexport void caml_raise_with_string(value tag, char const *msg) */ static void check_global_data(char const *exception_name) { - if (caml_global_data == 0) { - fprintf(stderr, "Fatal error: exception %s\n", exception_name); + if (caml_global_data == 0 || !Is_block(caml_read_root(caml_global_data))) { + fprintf(stderr, "Fatal error: exception %s during initialisation\n", exception_name); exit(2); } } static void check_global_data_param(char const *exception_name, char const *msg) { - if (caml_global_data == 0) { + if (caml_global_data == 0 || !Is_block(caml_read_root(caml_global_data))) { fprintf(stderr, "Fatal error: exception %s(\"%s\")\n", exception_name, msg); exit(2); } @@ -108,7 +119,7 @@ static void check_global_data_param(char const *exception_name, char const *msg) Caml_inline value caml_get_failwith_tag (char const *msg) { check_global_data_param("Failure", msg); - return Field(caml_global_data, FAILURE_EXN); + return Field(caml_read_root(caml_global_data), FAILURE_EXN); } CAMLexport void caml_failwith (char const *msg) @@ -127,7 +138,7 @@ CAMLexport void caml_failwith_value (value msg) Caml_inline value caml_get_invalid_argument_tag (char const *msg) { check_global_data_param("Invalid_argument", msg); - return Field(caml_global_data, INVALID_EXN); + return Field(caml_read_root(caml_global_data), INVALID_EXN); } CAMLexport void caml_invalid_argument (char const *msg) @@ -151,43 +162,57 @@ CAMLexport void caml_array_bound_error(void) CAMLexport void caml_raise_out_of_memory(void) { check_global_data("Out_of_memory"); - caml_raise_constant(Field(caml_global_data, OUT_OF_MEMORY_EXN)); + caml_raise_constant(Field(caml_read_root(caml_global_data), + OUT_OF_MEMORY_EXN)); } CAMLexport void caml_raise_stack_overflow(void) { check_global_data("Stack_overflow"); - caml_raise_constant(Field(caml_global_data, STACK_OVERFLOW_EXN)); + caml_raise_constant(Field(caml_read_root(caml_global_data), + STACK_OVERFLOW_EXN)); } CAMLexport void caml_raise_sys_error(value msg) { check_global_data_param("Sys_error", String_val(msg)); - caml_raise_with_arg(Field(caml_global_data, SYS_ERROR_EXN), msg); + caml_raise_with_arg(Field(caml_read_root(caml_global_data), + SYS_ERROR_EXN), msg); } CAMLexport void caml_raise_end_of_file(void) { check_global_data("End_of_file"); - caml_raise_constant(Field(caml_global_data, END_OF_FILE_EXN)); + caml_raise_constant(Field(caml_read_root(caml_global_data), + END_OF_FILE_EXN)); } CAMLexport void caml_raise_zero_divide(void) { check_global_data("Division_by_zero"); - caml_raise_constant(Field(caml_global_data, ZERO_DIVIDE_EXN)); + caml_raise_constant(Field(caml_read_root(caml_global_data), + ZERO_DIVIDE_EXN)); } CAMLexport void caml_raise_not_found(void) { check_global_data("Not_found"); - caml_raise_constant(Field(caml_global_data, NOT_FOUND_EXN)); + caml_raise_constant(Field(caml_read_root(caml_global_data), + NOT_FOUND_EXN)); } CAMLexport void caml_raise_sys_blocked_io(void) { check_global_data("Sys_blocked_io"); - caml_raise_constant(Field(caml_global_data, SYS_BLOCKED_IO)); + caml_raise_constant(Field(caml_read_root(caml_global_data), + SYS_BLOCKED_IO)); +} + +CAMLexport void caml_raise_continuation_already_taken(void) +{ + check_global_data("Continuation_already_taken"); + caml_raise_constant(Field(caml_read_root(caml_global_data), + CONTINUATION_ALREADY_TAKEN_EXN)); } value caml_raise_if_exception(value res) @@ -201,8 +226,15 @@ int caml_is_special_exception(value exn) { a more readable textual representation of some exceptions. It is better to fall back to the general, less readable representation than to abort with a fatal error as above. */ - if (caml_global_data == 0) return 0; - return exn == Field(caml_global_data, MATCH_FAILURE_EXN) - || exn == Field(caml_global_data, ASSERT_FAILURE_EXN) - || exn == Field(caml_global_data, UNDEFINED_RECURSIVE_MODULE_EXN); + + value f; + + if (caml_global_data == 0 || !Is_block(caml_read_root(caml_global_data))) { + return 0; + } + + f = caml_read_root(caml_global_data); + return exn == Field(f, MATCH_FAILURE_EXN) + || exn == Field(f, ASSERT_FAILURE_EXN) + || exn == Field(f, UNDEFINED_RECURSIVE_MODULE_EXN); } diff --git a/runtime/fail_nat.c b/runtime/fail_nat.c index 380578ac47..26e1d5e400 100644 --- a/runtime/fail_nat.c +++ b/runtime/fail_nat.c @@ -20,7 +20,6 @@ #include <stdio.h> #include <signal.h> #include "caml/alloc.h" -#include "caml/domain.h" #include "caml/fail.h" #include "caml/io.h" #include "caml/gc.h" @@ -48,25 +47,35 @@ extern caml_generated_constant caml_exn_Sys_blocked_io, caml_exn_Stack_overflow, caml_exn_Assert_failure, - caml_exn_Undefined_recursive_module; + caml_exn_Undefined_recursive_module, + caml_exn_Unhandled, + caml_exn_Continuation_already_taken; /* Exception raising */ -CAMLnoreturn_start - extern void caml_raise_exception (caml_domain_state* state, value bucket) -CAMLnoreturn_end; +extern void caml_raise_exception (caml_domain_state* state, value bucket) Noreturn; /* Used by the stack overflow handler -> deactivate ASAN (see segv_handler in signals_nat.c). */ CAMLno_asan void caml_raise(value v) { - Unlock_exn(); - if (Caml_state->exception_pointer == NULL) caml_fatal_uncaught_exception(v); - - while (Caml_state->local_roots != NULL && - (char *) Caml_state->local_roots < Caml_state->exception_pointer) { - Caml_state->local_roots = Caml_state->local_roots->next; + char* exception_pointer; + if (Caml_state->c_stack == 0) + caml_fatal_uncaught_exception(v); + + exception_pointer = (char*)Caml_state->c_stack; + while (CAML_LOCAL_ROOTS != NULL && + (char *) CAML_LOCAL_ROOTS < exception_pointer) { + struct caml__mutex_unwind* m; + Assert(CAML_LOCAL_ROOTS != NULL); + m = CAML_LOCAL_ROOTS->mutexes; + while (m) { + /* unlocked in reverse order of locking */ + caml_plat_unlock(m->mutex); + m = m->next; + } + CAML_LOCAL_ROOTS = CAML_LOCAL_ROOTS->next; } caml_raise_exception(Caml_state, v); @@ -96,11 +105,10 @@ void caml_raise_with_args(value tag, int nargs, value args[]) { CAMLparam1 (tag); CAMLxparamN (args, nargs); - value bucket; + CAMLlocal1 (bucket); int i; - CAMLassert(1 + nargs <= Max_young_wosize); - bucket = caml_alloc_small (1 + nargs, 0); + bucket = caml_alloc (1 + nargs, 0); Field(bucket, 0) = tag; for (i = 0; i < nargs; i++) Field(bucket, 1 + i) = args[i]; caml_raise(bucket); @@ -173,6 +181,11 @@ void caml_raise_sys_blocked_io(void) caml_raise_constant((value) caml_exn_Sys_blocked_io); } +void caml_raise_continuation_already_taken(void) +{ + caml_raise_constant((value) caml_exn_Continuation_already_taken); +} + value caml_raise_if_exception(value res) { if (Is_exception_result(res)) caml_raise(Extract_exception(res)); @@ -183,20 +196,20 @@ value caml_raise_if_exception(value res) do a GC before the exception is raised (lack of stack descriptors for the ccall to [caml_array_bound_error]). */ -static const value * caml_array_bound_error_exn = NULL; - void caml_array_bound_error(void) { - if (caml_array_bound_error_exn == NULL) { - caml_array_bound_error_exn = - caml_named_value("Pervasives.array_bound_error"); - if (caml_array_bound_error_exn == NULL) { + static atomic_uintnat exn_cache = ATOMIC_UINTNAT_INIT(0); + const value* exn = (const value*)atomic_load_acq(&exn_cache); + if (!exn) { + exn = caml_named_value("Pervasives.array_bound_error"); + if (!exn) { fprintf(stderr, "Fatal error: exception " - "Invalid_argument(\"index out of bounds\")\n"); + "Invalid_argument(\"index out of bounds\")\n"); exit(2); } + atomic_store_rel(&exn_cache, (uintnat)exn); } - caml_raise(*caml_array_bound_error_exn); + caml_raise(*exn); } int caml_is_special_exception(value exn) { diff --git a/runtime/fiber.c b/runtime/fiber.c new file mode 100644 index 0000000000..70fc1aa4da --- /dev/null +++ b/runtime/fiber.c @@ -0,0 +1,514 @@ +#define CAML_INTERNALS + +#include <string.h> +#include <unistd.h> +#include "caml/misc.h" +#include "caml/fiber.h" +#include "caml/gc_ctrl.h" +#include "caml/instruct.h" +#include "caml/fail.h" +#include "caml/alloc.h" +#include "caml/platform.h" +#include "caml/fix_code.h" +#include "caml/minor_gc.h" +#include "caml/major_gc.h" +#include "caml/shared_heap.h" +#include "caml/memory.h" +#include "caml/startup_aux.h" +#ifdef NATIVE_CODE +#include "caml/stack.h" +#include "frame_descriptors.h" +#endif + +#ifdef DEBUG +#define fiber_debug_log(...) caml_gc_log(__VA_ARGS__) +#else +#define fiber_debug_log(...) +#endif + +struct stack_info** caml_alloc_stack_cache () { + int i; + + struct stack_info** stack_cache = + (struct stack_info**)caml_stat_alloc_noexc(sizeof(struct stack_info*)*NUM_STACK_SIZE_CLASSES); + if (stack_cache == NULL) + return NULL; + + for(i = 0; i < NUM_STACK_SIZE_CLASSES; i++) + stack_cache[i] = NULL; + + return stack_cache; +} + +static inline struct stack_info* alloc_for_stack (mlsize_t wosize) +{ + return caml_stat_alloc_noexc(sizeof(struct stack_info) + + sizeof(value) * wosize + + 8 /* for alignment */ + + sizeof(struct stack_handler)); +} + +static inline struct stack_info** stack_cache_bucket (mlsize_t wosize) { + mlsize_t size_bucket_wsz = caml_fiber_wsz; + struct stack_info** size_bucket = Caml_state->stack_cache; + struct stack_info** end = size_bucket + NUM_STACK_SIZE_CLASSES; + + /* wosize is in stack cache bucket n iff wosize == caml_fiber_wsz * 2**n */ + while (size_bucket < end) { + if (wosize == size_bucket_wsz) + return size_bucket; + ++size_bucket; + size_bucket_wsz += size_bucket_wsz; + } + + return NULL; +} + +static struct stack_info* alloc_size_class_stack_noexc(mlsize_t wosize, struct stack_info** size_bucket, value hval, value hexn, value heff) +{ + struct stack_info* stack; + struct stack_handler* hand; + + CAML_STATIC_ASSERT(sizeof(struct stack_info) % sizeof(value) == 0); + CAML_STATIC_ASSERT(sizeof(struct stack_handler) % sizeof(value) == 0); + + if (size_bucket != NULL && *size_bucket != NULL) { + stack = *size_bucket; + *size_bucket = (struct stack_info*)stack->exception_ptr; + CAMLassert(stack->size_bucket == stack_cache_bucket(wosize)); + hand = stack->handler; + } else { + /* couldn't get a cached stack, so have to create one */ + stack = alloc_for_stack(wosize); + if (stack == NULL) { + return NULL; + } + + stack->size_bucket = size_bucket; + + /* Ensure 16-byte alignment because some architectures require it */ + hand = (struct stack_handler*) + (((uintnat)stack + sizeof(struct stack_info) + sizeof(value) * wosize + 8) + & ((uintnat)-1 << 4)); + stack->handler = hand; + } + + hand->handle_value = hval; + hand->handle_exn = hexn; + hand->handle_effect = heff; + hand->parent = NULL; + stack->sp = (value*)hand; + stack->exception_ptr = NULL; + stack->magic = 42; + CAMLassert(Stack_high(stack) - Stack_base(stack) == wosize || + Stack_high(stack) - Stack_base(stack) == wosize + 1); + return stack; + +} + +/* allocate a stack with at least "wosize" usable words of stack */ +static struct stack_info* alloc_stack_noexc(mlsize_t wosize, value hval, value hexn, value heff) +{ + struct stack_info** size_bucket = stack_cache_bucket (wosize); + return alloc_size_class_stack_noexc(wosize, size_bucket, hval, hexn, heff); +} + +#ifdef NATIVE_CODE + +value caml_alloc_stack (value hval, value hexn, value heff) { + struct stack_info* stack = alloc_size_class_stack_noexc(caml_fiber_wsz, Caml_state->stack_cache, hval, hexn, heff); + + if (!stack) caml_raise_out_of_memory(); + + fiber_debug_log ("Allocate stack=%p of %lu words", stack, caml_fiber_wsz); + + return Val_ptr(stack); +} + +void caml_get_stack_sp_pc (struct stack_info* stack, char** sp /* out */, uintnat* pc /* out */) +{ + char* p = (char*)stack->sp; + + p += sizeof(value); + *sp = p; + *pc = Saved_return_address(*sp); +} + +static inline void scan_stack_frames(scanning_action f, void* fdata, struct stack_info* stack, value* gc_regs) +{ + char * sp; + uintnat retaddr; + value * regs; + frame_descr * d; + uintnat h; + int n, ofs; + unsigned short * p; + value *root; + caml_frame_descrs fds = caml_get_frame_descrs(); + + sp = (char*)stack->sp; + +next_chunk: + if (sp == (char*)Stack_high(stack)) return; + + retaddr = *(uintnat*)sp; + sp += sizeof(value); + + regs = gc_regs; + + while(1) { + /* Find the descriptor corresponding to the return address */ + h = Hash_retaddr(retaddr, fds.mask); + while(1) { + d = fds.descriptors[h]; + if (d->retaddr == retaddr) break; + h = (h+1) & fds.mask; + } + if (d->frame_size != 0xFFFF) { + /* Scan the roots in this frame */ + for (p = d->live_ofs, n = d->num_live; n > 0; n--, p++) { + ofs = *p; + if (ofs & 1) { + root = regs + (ofs >> 1); + } else { + root = (value *)(sp + ofs); + } + f (fdata, *root, root); + } + /* Move to next frame */ + sp += (d->frame_size & 0xFFFC); + retaddr = Saved_return_address(sp); + /* XXX KC: disabled already scanned optimization. */ + } else { + /* This marks the top of an ML stack chunk. Move sp to the previous stack + * chunk. This includes skipping over the trap frame (2 words). */ + sp += 2 * sizeof(value); /* trap frame */ + regs = *(value**)sp; + sp += 2 * sizeof(value); /* DWARF and gc_regs */ + goto next_chunk; + } + } +} + +void caml_scan_stack(scanning_action f, void* fdata, struct stack_info* stack, value* gc_regs) +{ + while (stack != NULL) { + scan_stack_frames(f, fdata, stack, gc_regs); + + f(fdata, Stack_handle_value(stack), &Stack_handle_value(stack)); + f(fdata, Stack_handle_exception(stack), &Stack_handle_exception(stack)); + f(fdata, Stack_handle_effect(stack), &Stack_handle_effect(stack)); + + stack = Stack_parent(stack); + } +} + +void caml_maybe_expand_stack () +{ + struct stack_info* stk = Caml_state->current_stack; + uintnat stack_available = + (value*)stk->sp - Stack_base(stk); + uintnat stack_needed = + Stack_threshold / sizeof(value) + + 8 /* for words pushed by caml_start_program */; + + if (stack_available < stack_needed) + if (!caml_try_realloc_stack (stack_needed)) + caml_raise_stack_overflow(); + + if (Caml_state->gc_regs_buckets == NULL) { + /* ensure there is at least one gc_regs bucket available before + running any OCaml code */ + value* bucket = caml_stat_alloc(sizeof(value) * Wosize_gc_regs); + bucket[0] = 0; /* no next bucket */ + Caml_state->gc_regs_buckets = bucket; + } +} + +#else /* End NATIVE_CODE, begin BYTE_CODE */ + +caml_root caml_global_data; + +CAMLprim value caml_alloc_stack(value hval, value hexn, value heff) +{ + struct stack_info* stack = alloc_size_class_stack_noexc(caml_fiber_wsz, Caml_state->stack_cache, hval, hexn, heff); + value* sp; + + if (!stack) caml_raise_out_of_memory(); + + sp = Stack_high(stack); + // ? + sp -= 1; + sp[0] = Val_long(1); /* trapsp ?? */ + + stack->sp = sp; + + return Val_ptr(stack); +} + +CAMLprim value caml_ensure_stack_capacity(value required_space) +{ + asize_t req = Long_val(required_space); + if (Caml_state->current_stack->sp - req < Stack_base(Caml_state->current_stack)) + if (!caml_try_realloc_stack(req)) + caml_raise_stack_overflow(); + return Val_unit; +} + +void caml_change_max_stack_size (uintnat new_max_size) +{ + asize_t size = Stack_high(Caml_state->current_stack) - Caml_state->current_stack->sp + + Stack_threshold / sizeof (value); + + if (new_max_size < size) new_max_size = size; + if (new_max_size != caml_max_stack_size){ + caml_gc_log ("Changing stack limit to %luk bytes", + new_max_size * sizeof (value) / 1024); + } + caml_max_stack_size = new_max_size; +} + +/* + Root scanning. + + Used by the GC to find roots on the stacks of running or runnable fibers. +*/ + +void caml_scan_stack(scanning_action f, void* fdata, struct stack_info* stack, value* v_gc_regs) +{ + value *low, *high, *sp; + + while (stack != NULL) { + Assert(stack->magic == 42); + + high = Stack_high(stack); + low = stack->sp; + for (sp = low; sp < high; sp++) { + f(fdata, *sp, sp); + } + + f(fdata, Stack_handle_value(stack), &Stack_handle_value(stack)); + f(fdata, Stack_handle_exception(stack), &Stack_handle_exception(stack)); + f(fdata, Stack_handle_effect(stack), &Stack_handle_effect(stack)); + + stack = Stack_parent(stack); + } +} + +#endif /* end BYTE_CODE */ + +/* + Stack management. + + Used by the interpreter to allocate stack space. +*/ + +#ifdef NATIVE_CODE +/* Update absolute exception pointers for new stack*/ +static void rewrite_exception_stack(struct stack_info *old_stack, value** exn_ptr, struct stack_info *new_stack) +{ + fiber_debug_log ("Old [%p, %p]", Stack_base(old_stack), Stack_high(old_stack)); + fiber_debug_log ("New [%p, %p]", Stack_base(new_stack), Stack_high(new_stack)); + if(exn_ptr) { + fiber_debug_log ("*exn_ptr=%p", *exn_ptr); + + while (Stack_base(old_stack) < *exn_ptr && *exn_ptr <= Stack_high(old_stack)) { +#ifdef DEBUG + value* old_val = *exn_ptr; +#endif + *exn_ptr = Stack_high(new_stack) - (Stack_high(old_stack) - *exn_ptr); + + fiber_debug_log ("Rewriting %p to %p", old_val, *exn_ptr); + + CAMLassert(Stack_base(new_stack) < *exn_ptr); + CAMLassert((value*)*exn_ptr <= Stack_high(new_stack)); + + exn_ptr = (value**)*exn_ptr; + } + fiber_debug_log ("finished with *exn_ptr=%p", *exn_ptr); + } else { + fiber_debug_log ("exn_ptr is null"); + } +} +#endif + +int caml_try_realloc_stack(asize_t required_space) +{ + struct stack_info *old_stack, *new_stack; + asize_t size; + int stack_used; + CAMLnoalloc; + + old_stack = Caml_state->current_stack; + stack_used = Stack_high(old_stack) - (value*)old_stack->sp; +#ifdef DEBUG + size = stack_used + stack_used / 16 + required_space; + if (size >= caml_max_stack_size) return 0; +#else + size = Stack_high(old_stack) - Stack_base(old_stack); + do { + if (size >= caml_max_stack_size) return 0; + size *= 2; + } while (size < stack_used + required_space); +#endif + if (size > 4096 / sizeof(value)) { + caml_gc_log ("Growing stack to %" + ARCH_INTNAT_PRINTF_FORMAT "uk bytes", + (uintnat) size * sizeof(value) / 1024); + } else { + caml_gc_log ("Growing stack to %" + ARCH_INTNAT_PRINTF_FORMAT "u bytes", + (uintnat) size * sizeof(value)); + } + + new_stack = alloc_stack_noexc(size, + Stack_handle_value(old_stack), + Stack_handle_exception(old_stack), + Stack_handle_effect(old_stack)); + if (!new_stack) return 0; + memcpy(Stack_high(new_stack) - stack_used, + Stack_high(old_stack) - stack_used, + stack_used * sizeof(value)); + new_stack->sp = Stack_high(new_stack) - stack_used; + Stack_parent(new_stack) = Stack_parent(old_stack); +#ifdef NATIVE_CODE + rewrite_exception_stack(old_stack, (value**)&Caml_state->exn_handler, new_stack); +#endif + + /* Update stack pointers in Caml_state->c_stack */ + { + struct c_stack_link* link; + for (link = Caml_state->c_stack; link; link = link->prev) { +#ifdef DEBUG + struct stack_info* cb = NULL; + /* Verify that all callback frames on this C stack belong to the + same fiber */ + if (link->stack == NULL) { + /* only possible for the first link, if it has not done any C calls yet */ + /* FIXME: at the moment, this is possible due to a couple of odd ways of entering C code + (via GC, etc.) */ + //CAMLassert(link == Caml_state->c_stack); + } else if (cb == NULL) { + /* first non-NULL stack */ + cb = link->stack; + } else { + CAMLassert(link->stack == cb); + } +#endif + if (link->stack == old_stack) { + link->stack = new_stack; + link->sp = (void*)((char*)Stack_high(new_stack) - ((char*)Stack_high(old_stack) - (char*)link->sp)); + } + } + } + + caml_free_stack(old_stack); + Caml_state->current_stack = new_stack; + return 1; +} + +struct stack_info* caml_alloc_main_stack (uintnat init_size) +{ + struct stack_info* stk = + alloc_stack_noexc(init_size, Val_unit, Val_unit, Val_unit); + return stk; +} + +void caml_free_stack (struct stack_info* stack) +{ + CAMLnoalloc; + CAMLassert(stack->magic == 42); + if (stack->size_bucket != NULL) { + stack->exception_ptr = (void*)(*stack->size_bucket); + *stack->size_bucket = stack; +#ifdef DEBUG + memset(Stack_base(stack), 0x42, (Stack_high(stack)-Stack_base(stack))*sizeof(value)); +#endif + } else { +#ifdef DEBUG + memset(stack, 0x42, (char*)stack->handler - (char*)stack); +#endif + caml_stat_free(stack); + } +} + +CAMLprim value caml_clone_continuation (value cont) +{ + CAMLparam1(cont); + CAMLlocal1(new_cont); + intnat stack_used; + struct stack_info *source, *orig_source, *target, *ret_stack; + struct stack_info **link = &ret_stack; + + new_cont = caml_alloc_1(Cont_tag, Val_ptr(NULL)); + orig_source = source = Ptr_val(caml_continuation_use(cont)); + do { + CAMLnoalloc; + stack_used = Stack_high(source) - (value*)source->sp; + target = alloc_stack_noexc(Stack_high(source) - Stack_base(source), + Stack_handle_value(source), + Stack_handle_exception(source), + Stack_handle_effect(source)); + if (!target) caml_raise_out_of_memory(); + memcpy(Stack_high(target) - stack_used, Stack_high(source) - stack_used, + stack_used * sizeof(value)); +#ifdef NATIVE_CODE + { + /* rewrite exception pointer in the caml context on the new stack */ + target->exception_ptr = source->exception_ptr; + rewrite_exception_stack(source, (value**)&target->exception_ptr, target); + } +#endif + target->sp = Stack_high(target) - stack_used; + *link = target; + link = &Stack_parent(target); + source = Stack_parent(source); + } while (source != NULL); + caml_continuation_replace(cont, orig_source); + caml_continuation_replace(new_cont, ret_stack); + CAMLreturn (new_cont); +} + +CAMLprim value caml_continuation_use_noexc (value cont) +{ + value v; + value null_stk = Val_ptr(NULL); + CAMLnoalloc; + + fiber_debug_log("cont: is_block(%d) tag_val(%ul) is_young(%d)", Is_block(cont), Tag_val(cont), Is_young(cont)); + CAMLassert(Is_block(cont) && Tag_val(cont) == Cont_tag); + + /* this forms a barrier between execution and any other domains + that might be marking this continuation */ + if (!Is_young(cont) ) caml_darken_cont(cont); + + /* at this stage the stack is assured to be marked */ + v = Op_val(cont)[0]; + + if (caml_domain_alone()) { + Field(cont, 0) = null_stk; + return v; + } + + if (atomic_compare_exchange_strong(Op_atomic_val(cont), &v, null_stk)) { + return v; + } else { + return null_stk; + } +} + +CAMLprim value caml_continuation_use (value cont) +{ + value v = caml_continuation_use_noexc(cont); + if (v == Val_ptr(NULL)) + caml_raise_continuation_already_taken(); + return v; +} + +void caml_continuation_replace(value cont, struct stack_info* stk) +{ + value n = Val_ptr(NULL); + int b = atomic_compare_exchange_strong(Op_atomic_val(cont), &n, Val_ptr(stk)); + CAMLassert(b); + (void)b; /* squash unused warning */ +} diff --git a/runtime/finalise.c b/runtime/finalise.c index 455f91aed9..f77b30aa5a 100644 --- a/runtime/finalise.c +++ b/runtime/finalise.c @@ -15,93 +15,50 @@ #define CAML_INTERNALS -/* Handling of finalised values. */ +#include <string.h> #include "caml/callback.h" -#include "caml/compact.h" +#include "caml/eventlog.h" #include "caml/fail.h" #include "caml/finalise.h" +#include "caml/memory.h" #include "caml/minor_gc.h" -#include "caml/mlvalues.h" +#include "caml/misc.h" #include "caml/roots.h" -#include "caml/signals.h" -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) -#include "caml/spacetime.h" -#endif - -struct final { - value fun; - value val; - int offset; -}; - -struct finalisable { - struct final *table; - uintnat old; - uintnat young; - uintnat size; -}; -/* [0..old) : finalisable set, the values are in the major heap - [old..young) : recent set, the values could be in the minor heap - [young..size) : free space - - The element of the finalisable set are moved to the finalising set - below when the value are unreachable (for the first or last time). - -*/ - -static struct finalisable finalisable_first = {NULL,0,0,0}; -static struct finalisable finalisable_last = {NULL,0,0,0}; - -struct to_do { - struct to_do *next; - int size; - struct final item[1]; /* variable size */ -}; - -static struct to_do *to_do_hd = NULL; -static struct to_do *to_do_tl = NULL; -/* - to_do_hd: head of the list of finalisation functions that can be run. - to_do_tl: tail of the list of finalisation functions that can be run. - - It is the finalising set. -*/ - -static int running_finalisation_function = 0; +#include "caml/shared_heap.h" /* [size] is a number of elements for the [to_do.item] array */ -static void alloc_to_do (int size) +static void alloc_todo (struct domain* d, int size) { - struct to_do *result = caml_stat_alloc_noexc (sizeof (struct to_do) + - size * sizeof (struct final)); + struct final_todo *result = + caml_stat_alloc_noexc (sizeof (struct final_todo) + + size * sizeof (struct final)); + struct caml_final_info *f = d->state->final_info; if (result == NULL) caml_fatal_error ("out of memory"); result->next = NULL; result->size = size; - if (to_do_tl == NULL){ - to_do_hd = result; - to_do_tl = result; - if(!running_finalisation_function) caml_set_action_pending(); - }else{ - CAMLassert (to_do_tl->next == NULL); - to_do_tl->next = result; - to_do_tl = result; + if (f->todo_tail == NULL) { + f->todo_head = result; + f->todo_tail = result; + } else { + CAMLassert (f->todo_tail->next == NULL); + f->todo_tail->next = result; + f->todo_tail = result; } } /* Find white finalisable values, move them to the finalising set, and - darken them (if darken_value is true). -*/ -static void generic_final_update (struct finalisable * final, int darken_value) + darken them (if darken_value is true). */ +static void generic_final_update (struct domain* d, struct finalisable *final, int darken_value) { uintnat i, j, k; uintnat todo_count = 0; + struct caml_final_info *f = d->state->final_info; CAMLassert (final->old <= final->young); - for (i = 0; i < final->old; i++){ + for (i = 0; i < final->old; i++) { CAMLassert (Is_block (final->table[i].val)); - CAMLassert (Is_in_heap (final->table[i].val)); - if (Is_white_val (final->table[i].val)){ + if (is_unmarked (final->table[i].val)) { ++ todo_count; } } @@ -115,24 +72,23 @@ static void generic_final_update (struct finalisable * final, int darken_value) (alive or in the minor heap), next available slot. - k : index in to_do_tl, next available slot. */ - if (todo_count > 0){ - alloc_to_do (todo_count); + if (todo_count > 0) { + alloc_todo (d, todo_count); j = k = 0; for (i = 0; i < final->old; i++){ CAMLassert (Is_block (final->table[i].val)); - CAMLassert (Is_in_heap (final->table[i].val)); CAMLassert (Tag_val (final->table[i].val) != Forward_tag); - if(Is_white_val (final->table[i].val)){ + if (is_unmarked (final->table[i].val)) { /** dead */ - to_do_tl->item[k] = final->table[i]; - if(!darken_value){ + f->todo_tail->item[k] = final->table[i]; + if (!darken_value) { /* The value is not darken so the finalisation function is called with unit not with the value */ - to_do_tl->item[k].val = Val_unit; - to_do_tl->item[k].offset = 0; + f->todo_tail->item[k].val = Val_unit; + f->todo_tail->item[k].offset = 0; }; k++; - }else{ + } else { /** alive */ final->table[j++] = final->table[i]; } @@ -140,159 +96,139 @@ static void generic_final_update (struct finalisable * final, int darken_value) CAMLassert (i == final->old); CAMLassert (k == todo_count); final->old = j; - for(;i < final->young; i++){ + for ( ; i < final->young; i++) { final->table[j++] = final->table[i]; } final->young = j; - to_do_tl->size = k; - if(darken_value){ - for (i = 0; i < k; i++){ + f->todo_tail->size = k; + if (darken_value) { + for (i = 0; i < k; i++) { /* Note that item may already be dark due to multiple entries in the final table. */ - caml_darken (to_do_tl->item[i].val, NULL); + caml_darken (NULL, f->todo_tail->item[i].val, NULL); } } } } -void caml_final_update_mark_phase (){ - generic_final_update(&finalisable_first, /* darken_value */ 1); +int caml_final_update_first (struct domain* d) +{ + struct caml_final_info *f = d->state->final_info; + if (!f->updated_first) { + CAML_EV_BEGIN(EV_FINALISE_UPDATE_FIRST); + generic_final_update (d, &f->first, /* darken_value */ 1); + CAML_EV_END(EV_FINALISE_UPDATE_FIRST); + f->updated_first = 1; + return 1; + } + return 0; } -void caml_final_update_clean_phase (){ - generic_final_update(&finalisable_last, /* darken_value */ 0); +int caml_final_update_last (struct domain* d) +{ + struct caml_final_info *f = d->state->final_info; + if (!f->updated_last) { + CAML_EV_BEGIN(EV_FINALISE_UPDATE_LAST); + generic_final_update (d, &f->last, /* darken_value */ 0); + CAML_EV_END(EV_FINALISE_UPDATE_LAST); + f->updated_last = 1; + return 1; + } + return 0; } -/* Call the finalisation functions for the finalising set. - Note that this function must be reentrant. -*/ -value caml_final_do_calls_exn (void) +void caml_final_do_calls () { struct final f; value res; -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - void* saved_spacetime_trie_node_ptr; -#endif + struct domain *d = caml_domain_self(); + struct caml_final_info *fi = d->state->final_info; - if (!running_finalisation_function && to_do_hd != NULL){ - if (caml_finalise_begin_hook != NULL) (*caml_finalise_begin_hook) (); + if (fi->running_finalisation_function) return; + if (fi->todo_head != NULL) { caml_gc_message (0x80, "Calling finalisation functions.\n"); - while (1){ - while (to_do_hd != NULL && to_do_hd->size == 0){ - struct to_do *next_hd = to_do_hd->next; - caml_stat_free (to_do_hd); - to_do_hd = next_hd; - if (to_do_hd == NULL) to_do_tl = NULL; + while (1) { + while (fi->todo_head != NULL && fi->todo_head->size == 0) { + struct final_todo *next_head = fi->todo_head->next; + caml_stat_free (fi->todo_head); + fi->todo_head = next_head; + if (fi->todo_head == NULL) fi->todo_tail = NULL; } - if (to_do_hd == NULL) break; - CAMLassert (to_do_hd->size > 0); - -- to_do_hd->size; - f = to_do_hd->item[to_do_hd->size]; - running_finalisation_function = 1; -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - /* We record the finaliser's execution separately. - (The code of [caml_callback_exn] will do the hard work of finding - the correct place in the trie.) */ - saved_spacetime_trie_node_ptr = caml_spacetime_trie_node_ptr; - caml_spacetime_trie_node_ptr = caml_spacetime_finaliser_trie_root; -#endif + if (fi->todo_head == NULL) break; + CAMLassert (fi->todo_head->size > 0); + --fi->todo_head->size; + f = fi->todo_head->item[fi->todo_head->size]; + fi->running_finalisation_function = 1; res = caml_callback_exn (f.fun, f.val + f.offset); -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - caml_spacetime_trie_node_ptr = saved_spacetime_trie_node_ptr; -#endif - running_finalisation_function = 0; - if (Is_exception_result (res)) return res; + fi->running_finalisation_function = 0; + if (Is_exception_result(res)) caml_raise (Extract_exception (res)); } caml_gc_message (0x80, "Done calling finalisation functions.\n"); - if (caml_finalise_end_hook != NULL) (*caml_finalise_end_hook) (); } - return Val_unit; } /* Call a scanning_action [f] on [x]. */ -#define Call_action(f,x) (*(f)) ((x), &(x)) - -/* Call [*f] on the closures of the finalisable set and - the closures and values of the finalising set. - This is called by the major GC [caml_darken_all_roots] - and by the compactor through [caml_do_roots] -*/ -void caml_final_do_roots (scanning_action f) +#define Call_action(f,d,x) (*(f)) ((d), (x), &(x)) + +/* Called my major_gc for marking roots */ +void caml_final_do_roots (scanning_action act, void* fdata, struct domain* domain, int do_val) { uintnat i; - struct to_do *todo; - - CAMLassert (finalisable_first.old <= finalisable_first.young); - for (i = 0; i < finalisable_first.young; i++){ - Call_action (f, finalisable_first.table[i].fun); - }; - - CAMLassert (finalisable_last.old <= finalisable_last.young); - for (i = 0; i < finalisable_last.young; i++){ - Call_action (f, finalisable_last.table[i].fun); - }; - - for (todo = to_do_hd; todo != NULL; todo = todo->next){ - for (i = 0; i < todo->size; i++){ - Call_action (f, todo->item[i].fun); - Call_action (f, todo->item[i].val); - } + struct final_todo *todo; + struct caml_final_info *f = domain->state->final_info; + + CAMLassert (f->first.old <= f->first.young); + for (i = 0; i < f->first.young; i++) { + Call_action (act, fdata, f->first.table[i].fun); + if (do_val) + Call_action (act, fdata, f->first.table[i].val); } -} -/* Call caml_invert_root on the values of the finalisable set. This is called - directly by the compactor. -*/ -void caml_final_invert_finalisable_values () -{ - uintnat i; + CAMLassert (f->last.old <= f->last.young); + for (i = 0; i < f->last.young; i++) { + Call_action (act, fdata, f->last.table[i].fun); + if (do_val) + Call_action (act, fdata, f->last.table[i].val); + } - CAMLassert (finalisable_first.old <= finalisable_first.young); - for (i = 0; i < finalisable_first.young; i++){ - caml_invert_root(finalisable_first.table[i].val, - &finalisable_first.table[i].val); - }; - - CAMLassert (finalisable_last.old <= finalisable_last.young); - for (i = 0; i < finalisable_last.young; i++){ - caml_invert_root(finalisable_last.table[i].val, - &finalisable_last.table[i].val); - }; + for (todo = f->todo_head; todo != NULL; todo = todo->next) { + for (i = 0; i < todo->size; i++) { + Call_action (act, fdata, todo->item[i].fun); + Call_action (act, fdata, todo->item[i].val); + } + } } -/* Call [caml_oldify_one] on the closures and values of the recent set. - This is called by the minor GC through [caml_oldify_local_roots]. -*/ -void caml_final_oldify_young_roots () +/* Called by minor gc for marking roots */ +void caml_final_do_young_roots (scanning_action act, void* fdata, struct domain* d, int do_last_val) { uintnat i; + struct caml_final_info *f = d->state->final_info; - CAMLassert (finalisable_first.old <= finalisable_first.young); - for (i = finalisable_first.old; i < finalisable_first.young; i++){ - caml_oldify_one(finalisable_first.table[i].fun, - &finalisable_first.table[i].fun); - caml_oldify_one(finalisable_first.table[i].val, - &finalisable_first.table[i].val); + CAMLassert (f->first.old <= f->first.young); + for (i = f->first.old; i < f->first.young; i++) { + Call_action (act, fdata, f->first.table[i].fun); + Call_action (act, fdata, f->first.table[i].val); } - CAMLassert (finalisable_last.old <= finalisable_last.young); - for (i = finalisable_last.old; i < finalisable_last.young; i++){ - caml_oldify_one(finalisable_last.table[i].fun, - &finalisable_last.table[i].fun); + CAMLassert (f->last.old <= f->last.old); + for (i = f->last.old; i < f->last.young; i++) { + Call_action (act, fdata, f->last.table[i].fun); + if (do_last_val) + Call_action (act, fdata, f->last.table[i].val); } - } -static void generic_final_minor_update (struct finalisable * final) +static void generic_final_minor_update (struct domain* d, struct finalisable * final) { uintnat i, j, k; uintnat todo_count = 0; + struct caml_final_info *fi = d->state->final_info; CAMLassert (final->old <= final->young); for (i = final->old; i < final->young; i++){ CAMLassert (Is_block (final->table[i].val)); - CAMLassert (Is_in_heap_or_young (final->table[i].val)); - if (Is_young(final->table[i].val) && Hd_val(final->table[i].val) != 0){ + if (Is_young(final->table[i].val) && caml_get_header_val(final->table[i].val) != 0){ ++ todo_count; } } @@ -305,22 +241,21 @@ static void generic_final_minor_update (struct finalisable * final) next available slot. - k : index in to_do_tl, next available slot. */ - if (todo_count > 0){ - alloc_to_do (todo_count); + if (todo_count > 0) { + alloc_todo (d, todo_count); k = 0; j = final->old; - for (i = final->old; i < final->young; i++){ + for (i = final->old; i < final->young; i++) { CAMLassert (Is_block (final->table[i].val)); - CAMLassert (Is_in_heap_or_young (final->table[i].val)); CAMLassert (Tag_val (final->table[i].val) != Forward_tag); - if(Is_young(final->table[i].val) && Hd_val(final->table[i].val) != 0){ + if (Is_young(final->table[j].val) && caml_get_header_val(final->table[i].val) != 0) { /** dead */ - to_do_tl->item[k] = final->table[i]; + fi->todo_tail->item[k] = final->table[i]; /* The finalisation function is called with unit not with the value */ - to_do_tl->item[k].val = Val_unit; - to_do_tl->item[k].offset = 0; + fi->todo_tail->item[k].val = Val_unit; + fi->todo_tail->item[k].offset = 0; k++; - }else{ + } else { /** alive */ final->table[j++] = final->table[i]; } @@ -328,119 +263,119 @@ static void generic_final_minor_update (struct finalisable * final) CAMLassert (i == final->young); CAMLassert (k == todo_count); final->young = j; - to_do_tl->size = todo_count; + fi->todo_tail->size = todo_count; } /** update the minor value to the copied major value */ - for (i = final->old; i < final->young; i++){ + for (i = final->old; i < final->young; i++) { CAMLassert (Is_block (final->table[i].val)); - CAMLassert (Is_in_heap_or_young (final->table[i].val)); if (Is_young(final->table[i].val)) { - CAMLassert (Hd_val(final->table[i].val) == 0); - final->table[i].val = Field(final->table[i].val,0); + CAMLassert (caml_get_header_val(final->table[i].val) == 0); + final->table[i].val = Op_val(final->table[i].val)[0]; } } +} - /** check invariant */ - CAMLassert (final->old <= final->young); - for (i = 0; i < final->young; i++){ - CAMLassert( Is_in_heap(final->table[i].val) ); - }; - +void caml_final_update_last_minor (struct domain* d) +{ + generic_final_minor_update(d, &d->state->final_info->last); } -/* At the end of minor collection update the finalise_last roots in - minor heap when moved to major heap or moved them to the finalising - set when dead. -*/ -void caml_final_update_minor_roots () +void caml_final_empty_young (struct domain* d) { - generic_final_minor_update(&finalisable_last); + struct caml_final_info *f = d->state->final_info; + f->first.old = f->first.young; + f->last.old = f->last.young; } -/* Empty the recent set into the finalisable set. - This is called at the end of each minor collection. - The minor heap must be empty when this is called. -*/ -void caml_final_empty_young (void) +void caml_final_merge_finalisable (struct finalisable *source, struct finalisable *target) { - finalisable_first.old = finalisable_first.young; - finalisable_last.old = finalisable_last.young; + uintnat new_size; + + CAMLassert (source->old == source->young); + if (target->young + source->young >= target->size) { + new_size = 2 * (target->young + source->young); + if (target->table == NULL) { + target->table = caml_stat_alloc (new_size * sizeof (struct final)); + CAMLassert (target->old == 0); + CAMLassert (target->young == 0); + target->size = new_size; + } else { + target->table = caml_stat_resize (target->table, + new_size * sizeof (struct final)); + target->size = new_size; + } + } + memmove(target->table + source->young, target->table, + source->young * sizeof (struct final)); + memcpy(target->table, source->table, source->young * sizeof (struct final)); + target->old += source->young; + target->young += source->young; } -/* Put (f,v) in the recent set. */ static void generic_final_register (struct finalisable *final, value f, value v) { - if (!Is_block (v) - || !Is_in_heap_or_young(v) - || Tag_val (v) == Lazy_tag + uintnat new_size; + + if (!Is_block(v) || Tag_val(v) == Lazy_tag #ifdef FLAT_FLOAT_ARRAY - || Tag_val (v) == Double_tag + || Tag_val(v) == Double_tag #endif - || Tag_val (v) == Forward_tag) { + || Tag_val(v) == Forward_tag) { caml_invalid_argument ("Gc.finalise"); } CAMLassert (final->old <= final->young); - if (final->young >= final->size){ - if (final->table == NULL){ - uintnat new_size = 30; + if (final->young >= final->size) { + if (final->table == NULL) { + new_size = 30; final->table = caml_stat_alloc (new_size * sizeof (struct final)); CAMLassert (final->old == 0); CAMLassert (final->young == 0); final->size = new_size; - }else{ - uintnat new_size = final->size * 2; + } else { + new_size = final->size * 2; final->table = caml_stat_resize (final->table, - new_size * sizeof (struct final)); + new_size * sizeof (struct final)); final->size = new_size; } } CAMLassert (final->young < final->size); final->table[final->young].fun = f; - if (Tag_val (v) == Infix_tag){ + if (Tag_val(v) == Infix_tag) { final->table[final->young].offset = Infix_offset_val (v); final->table[final->young].val = v - Infix_offset_val (v); - }else{ + } else { final->table[final->young].offset = 0; final->table[final->young].val = v; } ++ final->young; - } -CAMLprim value caml_final_register (value f, value v){ - generic_final_register(&finalisable_first, f, v); + +CAMLprim value caml_final_register (value f, value v) +{ + generic_final_register (&Caml_state->final_info->first, f, v); return Val_unit; } -CAMLprim value caml_final_register_called_without_value (value f, value v){ - generic_final_register(&finalisable_last, f, v); +CAMLprim value caml_final_register_called_without_value (value f, value v) +{ + generic_final_register (&Caml_state->final_info->last, f, v); return Val_unit; } CAMLprim value caml_final_release (value unit) { - running_finalisation_function = 0; - /* Some finalisers might be waiting. */ - if (to_do_tl != NULL) - caml_set_action_pending(); + Caml_state->final_info->running_finalisation_function = 0; return Val_unit; } -static void gen_final_invariant_check(struct finalisable *final){ - uintnat i; - - CAMLassert (final->old <= final->young); - for (i = 0; i < final->old; i++){ - CAMLassert( Is_in_heap(final->table[i].val) ); - }; - for (i = final->old; i < final->young; i++){ - CAMLassert( Is_in_heap_or_young(final->table[i].val) ); - }; -} - -void caml_final_invariant_check(void){ - gen_final_invariant_check(&finalisable_first); - gen_final_invariant_check(&finalisable_last); +struct caml_final_info* caml_alloc_final_info () +{ + struct caml_final_info* f = + caml_stat_alloc_noexc (sizeof(struct caml_final_info)); + if(f != NULL) + memset (f, 0, sizeof(struct caml_final_info)); + return f; } diff --git a/runtime/fix_code.c b/runtime/fix_code.c index aa059be5df..1d52a7c62d 100644 --- a/runtime/fix_code.c +++ b/runtime/fix_code.c @@ -101,12 +101,13 @@ int* caml_init_opcode_nargs(void) l[APPTERM1] = l[APPTERM2] = l[APPTERM3] = l[RETURN] = l[GRAB] = l[PUSHGETGLOBAL] = l[GETGLOBAL] = l[SETGLOBAL] = l[PUSHATOM] = l[ATOM] = l[MAKEBLOCK1] = l[MAKEBLOCK2] = - l[MAKEBLOCK3] = l[MAKEFLOATBLOCK] = l[GETFIELD] = + l[MAKEBLOCK3] = l[MAKEFLOATBLOCK] = l[GETFIELD] = l[GETMUTABLEFIELD] = l[GETFLOATFIELD] = l[SETFIELD] = l[SETFLOATFIELD] = l[BRANCH] = l[BRANCHIF] = l[BRANCHIFNOT] = l[PUSHTRAP] = l[C_CALL1] = l[C_CALL2] = l[C_CALL3] = l[C_CALL4] = l[C_CALL5] = l[CONSTINT] = l[PUSHCONSTINT] = l[OFFSETINT] = - l[OFFSETREF] = l[OFFSETCLOSURE] = l[PUSHOFFSETCLOSURE] = 1; + l[OFFSETREF] = l[OFFSETCLOSURE] = l[PUSHOFFSETCLOSURE] = + l[RESUMETERM] = l[REPERFORMTERM] = 1; /* Instructions with two operands */ l[APPTERM] = l[CLOSURE] = l[PUSHGETGLOBALFIELD] = diff --git a/runtime/floats.c b/runtime/floats.c index 7b8d04a11a..7fe8f74212 100644 --- a/runtime/floats.c +++ b/runtime/floats.c @@ -36,7 +36,7 @@ #include "caml/mlvalues.h" #include "caml/misc.h" #include "caml/reverse.h" -#include "caml/stacks.h" +#include "caml/fiber.h" #if defined(HAS_LOCALE) || defined(__MINGW32__) @@ -82,8 +82,8 @@ CAMLexport double caml_Double_val(value val) union { value v[2]; double d; } buffer; CAMLassert(sizeof(double) == 2 * sizeof(value)); - buffer.v[0] = Field(val, 0); - buffer.v[1] = Field(val, 1); + buffer.v[0] = Op_val(val)[0]; + buffer.v[1] = Op_val(val)[1]; return buffer.d; } @@ -93,8 +93,8 @@ CAMLexport void caml_Store_double_val(value val, double dbl) CAMLassert(sizeof(double) == 2 * sizeof(value)); buffer.d = dbl; - Field(val, 0) = buffer.v[0]; - Field(val, 1) = buffer.v[1]; + Op_val(val)[0] = buffer.v[0]; + Op_val(val)[1] = buffer.v[1]; } #endif @@ -149,11 +149,7 @@ CAMLexport value caml_copy_double(double d) { value res; -#define Setup_for_gc -#define Restore_after_gc - Alloc_small(res, Double_wosize, Double_tag); -#undef Setup_for_gc -#undef Restore_after_gc + Alloc_small(res, Double_wosize, Double_tag, { caml_handle_gc_interrupt(); }); Store_double_val(res, d); return res; } diff --git a/runtime/frame_descriptors.c b/runtime/frame_descriptors.c new file mode 100644 index 0000000000..2d9de561f9 --- /dev/null +++ b/runtime/frame_descriptors.c @@ -0,0 +1,180 @@ +#define CAML_INTERNALS + +#include "frame_descriptors.h" +#include "caml/platform.h" +#include "caml/major_gc.h" /* for caml_major_cycles_completed */ +#include "caml/memory.h" +#include <stddef.h> + +/* Defined in code generated by ocamlopt */ +extern intnat * caml_frametable[]; + +typedef struct link { + intnat* frametable; + struct link *next; +} link; + +#define iter_list(list,lnk) \ + for (lnk = list; lnk != NULL; lnk = lnk->next) + +static frame_descr * next_frame_descr(frame_descr * d) { + unsigned char num_allocs = 0, *p; + CAMLassert(d->retaddr >= 4096); + /* Skip to end of live_ofs */ + p = (unsigned char*)&d->live_ofs[d->num_live]; + /* Skip alloc_lengths if present */ + if (d->frame_size & 2) { + num_allocs = *p; + p += num_allocs + 1; + } + /* Skip debug info if present */ + if (d->frame_size & 1 && + d->frame_size != (unsigned short)-1) { + /* Align to 32 bits */ + p = Align_to(p, uint32_t); + p += sizeof(uint32_t) * (d->frame_size & 2 ? num_allocs : 1); + } + /* Align to word size */ + p = Align_to(p, void*); + return ((frame_descr*) p); +} + +caml_frame_descrs build_frame_descriptors(link* frametables) +{ + intnat num_descr, tblsize, i, j, len; + intnat * tbl; + frame_descr * d; + uintnat h; + link *lnk; + caml_frame_descrs table; + + /* Count the frame descriptors */ + num_descr = 0; + iter_list(frametables,lnk) { + num_descr += *lnk->frametable; + } + + /* The size of the hashtable is a power of 2 greater or equal to + 2 times the number of descriptors */ + tblsize = 4; + while (tblsize < 2 * num_descr) tblsize *= 2; + + /* Allocate the hash table */ + table.descriptors = caml_stat_alloc(tblsize * sizeof(frame_descr*)); + table.mask = tblsize - 1; + for (i = 0; i < tblsize; i++) table.descriptors[i] = NULL; + + /* Fill the hash table */ + iter_list(frametables,lnk) { + tbl = lnk->frametable; + len = *tbl; + d = (frame_descr *)(tbl + 1); + for (j = 0; j < len; j++) { + h = Hash_retaddr(d->retaddr, tblsize - 1); + while (table.descriptors[h] != NULL) { + h = (h+1) & table.mask; + } + table.descriptors[h] = d; + d = next_frame_descr(d); + } + } + return table; +} + +static caml_plat_mutex descr_mutex; +static link* frametables; + +/* Memory used by frametables is only freed once a GC cycle has + completed, because other threads access the frametable at + unpredictable times. */ +struct frametable_version { + caml_frame_descrs table; + + /* after this cycle has completed, + the previous table should be deallocated. + Set to No_need_to_free after prev is freed */ + atomic_uintnat free_prev_after_cycle; + struct frametable_version* prev; +}; +#define No_need_to_free ((uintnat)(-1)) + +/* Only modified when holding descr_mutex, but read without locking */ +static atomic_uintnat current_frametable = ATOMIC_UINTNAT_INIT(0); + +static link *cons(intnat *frametable, link *tl) { + link *lnk = caml_stat_alloc(sizeof(link)); + lnk->frametable = frametable; + lnk->next = tl; + return lnk; +} + +void caml_init_frame_descriptors(void) +{ + int i; + struct frametable_version *ft; + + caml_plat_mutex_init(&descr_mutex); + + caml_plat_lock(&descr_mutex); + for (i = 0; caml_frametable[i] != 0; i++) + frametables = cons(caml_frametable[i], frametables); + + ft = caml_stat_alloc(sizeof(*ft)); + ft->table = build_frame_descriptors(frametables); + atomic_store_rel(&ft->free_prev_after_cycle, No_need_to_free); + ft->prev = 0; + atomic_store_rel(¤t_frametable, (uintnat)ft); + caml_plat_unlock(&descr_mutex); +} + +void caml_register_frametable(intnat *table) +{ + struct frametable_version *ft, *old; + + caml_plat_lock(&descr_mutex); + + frametables = cons(table, frametables); + old = (struct frametable_version*)atomic_load_acq(¤t_frametable); + CAMLassert(old != NULL); + ft = caml_stat_alloc(sizeof(*ft)); + ft->table = build_frame_descriptors(frametables); + atomic_store_rel(&ft->free_prev_after_cycle, caml_major_cycles_completed); + ft->prev = old; + atomic_store_rel(¤t_frametable, (uintnat)ft); + + caml_plat_unlock(&descr_mutex); +} + +caml_frame_descrs caml_get_frame_descrs() +{ + struct frametable_version *ft = + (struct frametable_version*)atomic_load_acq(¤t_frametable); + CAMLassert(ft); + if (atomic_load_acq(&ft->free_prev_after_cycle) < caml_major_cycles_completed) { + /* it's now safe to free the old table */ + caml_plat_lock(&descr_mutex); + if (ft->prev != NULL) { + caml_stat_free(ft->prev->table.descriptors); + caml_stat_free(ft->prev); + ft->prev = NULL; + atomic_store_rel(&ft->free_prev_after_cycle, No_need_to_free); + } + caml_plat_unlock(&descr_mutex); + } + return ft->table; +} + +frame_descr* caml_find_frame_descr(caml_frame_descrs fds, uintnat pc) +{ + frame_descr * d; + uintnat h; + + h = Hash_retaddr(pc, fds.mask); + while (1) { + d = fds.descriptors[h]; + if (d == 0) return NULL; /* can happen if some code compiled without -g */ + if (d->retaddr == pc) break; + h = (h+1) & fds.mask; + } + return d; +} diff --git a/runtime/frame_descriptors.h b/runtime/frame_descriptors.h new file mode 100644 index 0000000000..c594f2e09e --- /dev/null +++ b/runtime/frame_descriptors.h @@ -0,0 +1,42 @@ +#ifndef CAML_FRAME_DESCRIPTORS_H +#define CAML_FRAME_DESCRIPTORS_H + +#include "caml/config.h" + +#define Hash_retaddr(addr, mask) \ + (((uintnat)(addr) >> 3) & (mask)) + +/* Structure of frame descriptors */ + +typedef struct { + uintnat retaddr; + unsigned short frame_size; + unsigned short num_live; + unsigned short live_ofs[1 /* num_live */]; + /* + If frame_size & 1, then debug info follows: + uint32_t debug_info_offset; + Debug info is stored as a relative offset to a debuginfo structure. */ +} frame_descr; + +/* Used to compute offsets in frame tables. + ty must have power-of-2 size */ +#define Align_to(p, ty) \ + (void*)(((uintnat)(p) + sizeof(ty) - 1) & -sizeof(ty)) + + +void caml_init_frame_descriptors(void); +void caml_register_frametable(intnat *table); + +typedef struct { + frame_descr** descriptors; + int mask; +} caml_frame_descrs; + +caml_frame_descrs caml_get_frame_descrs(void); + +/* Find the current table of frame descriptors. + The resulting structure is only valid until the next GC */ +frame_descr* caml_find_frame_descr(caml_frame_descrs fds, uintnat pc); + +#endif /* CAML_FRAME_DESCRIPTORS_H */ diff --git a/runtime/freelist.c b/runtime/freelist.c deleted file mode 100644 index 7f2d23caac..0000000000 --- a/runtime/freelist.c +++ /dev/null @@ -1,1858 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Damien Doligez, projet Para, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -#define FREELIST_DEBUG 0 -#if FREELIST_DEBUG -#include <stdio.h> -#endif - -#include <string.h> - -#include "caml/config.h" -#include "caml/custom.h" -#include "caml/freelist.h" -#include "caml/gc.h" -#include "caml/gc_ctrl.h" -#include "caml/memory.h" -#include "caml/major_gc.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/eventlog.h" - -/*************** declarations common to all policies ******************/ - -/* A block in a small free list is a [value] (integer representing a - pointer to the first word after the block's header). The end of the - list is NULL. -*/ -#define Val_NULL ((value) NULL) - -asize_t caml_fl_cur_wsz = 0; /* Number of words in the free set, - including headers but not fragments. */ - -value caml_fl_merge = Val_NULL; /* Current insertion pointer. Managed - jointly with [sweep_slice]. */ - -/* Next in list */ -#define Next_small(v) Field ((v), 0) - -/* Next in memory order */ -Caml_inline value Next_in_mem (value v) { - return (value) &Field ((v), Whsize_val (v)); -} - -#ifdef CAML_INSTR - -/* number of pointers followed to allocate from the free set */ -uintnat caml_instr_alloc_jump = 0; - -#define EV_ALLOC_JUMP(n) (caml_instr_alloc_jump += (n)) - -#endif /*CAML_INSTR*/ - - - -/********************* next-fit allocation policy *********************/ - -/* The free-list is kept sorted by increasing addresses. - This makes the merging of adjacent free blocks possible. - (See [nf_merge_block].) -*/ - -/* The sentinel can be located anywhere in memory, but it must not be - adjacent to any heap object. */ -static struct { - value filler1; /* Make sure the sentinel is never adjacent to any block. */ - header_t h; - value first_field; - value filler2; /* Make sure the sentinel is never adjacent to any block. */ -} nf_sentinel = {0, Make_header (0, 0, Caml_blue), Val_NULL, 0}; - -#define Nf_head (Val_bp (&(nf_sentinel.first_field))) - -static value nf_prev = Nf_head; /* Current allocation pointer. */ -static value nf_last = Val_NULL; /* Last block in the list. Only valid - just after [nf_allocate] returns NULL. */ - -#if defined (DEBUG) || FREELIST_DEBUG -static void nf_check (void) -{ - value cur; - int prev_found = 0, merge_found = 0; - uintnat size_found = 0; - - cur = Next_small (Nf_head); - while (cur != Val_NULL){ - size_found += Whsize_bp (cur); - CAMLassert (Is_in_heap (cur)); - if (cur == nf_prev) prev_found = 1; - if (cur == caml_fl_merge) merge_found = 1; - cur = Next_small (cur); - } - CAMLassert (prev_found || nf_prev == Nf_head); - CAMLassert (merge_found || caml_fl_merge == Nf_head); - CAMLassert (size_found == caml_fl_cur_wsz); -} - -#endif /* DEBUG || FREELIST_DEBUG */ - -/* [nf_allocate_block] is called by [nf_allocate]. Given a suitable free - block and the requested size, it allocates a new block from the free - block. There are three cases: - 0. The free block has the requested size. Detach the block from the - free-list and return it. - 1. The free block is 1 word longer than the requested size. Detach - the block from the free list. The remaining word cannot be linked: - turn it into an empty block (header only), and return the rest. - 2. The free block is large enough. Split it in two and return the right - block. - In all cases, the allocated block is right-justified in the free block: - it is located in the high-address words of the free block, so that - the linking of the free-list does not change in case 2. -*/ -static header_t *nf_allocate_block (mlsize_t wh_sz, value prev, value cur) -{ - header_t h = Hd_bp (cur); - CAMLassert (Whsize_hd (h) >= wh_sz); - if (Wosize_hd (h) < wh_sz + 1){ /* Cases 0 and 1. */ - caml_fl_cur_wsz -= Whsize_hd (h); - Next_small (prev) = Next_small (cur); - CAMLassert (Is_in_heap (Next_small (prev)) - || Next_small (prev) == Val_NULL); - if (caml_fl_merge == cur) caml_fl_merge = prev; -#ifdef DEBUG - nf_last = Val_NULL; -#endif - /* In case 1, the following creates the empty block correctly. - In case 0, it gives an invalid header to the block. The function - calling [nf_allocate] will overwrite it. */ - Hd_op (cur) = Make_header (0, 0, Caml_white); - }else{ /* Case 2. */ - caml_fl_cur_wsz -= wh_sz; - Hd_op (cur) = Make_header (Wosize_hd (h) - wh_sz, 0, Caml_blue); - } - nf_prev = prev; - return (header_t *) &Field (cur, Wosize_hd (h) - wh_sz); -} - -static header_t *nf_allocate (mlsize_t wo_sz) -{ - value cur = Val_NULL, prev; - CAMLassert (sizeof (char *) == sizeof (value)); - CAMLassert (wo_sz >= 1); - - CAMLassert (nf_prev != Val_NULL); - /* Search from [nf_prev] to the end of the list. */ - prev = nf_prev; - cur = Next_small (prev); - while (cur != Val_NULL){ - CAMLassert (Is_in_heap (cur)); - if (Wosize_bp (cur) >= wo_sz){ - return nf_allocate_block (Whsize_wosize (wo_sz), prev, cur); - } - prev = cur; - cur = Next_small (prev); - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (1)); - } - nf_last = prev; - /* Search from the start of the list to [nf_prev]. */ - prev = Nf_head; - cur = Next_small (prev); - while (prev != nf_prev){ - if (Wosize_bp (cur) >= wo_sz){ - return nf_allocate_block (Whsize_wosize (wo_sz), prev, cur); - } - prev = cur; - cur = Next_small (prev); - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (1)); - } - /* No suitable block was found. */ - return NULL; -} - -/* Location of the last fragment seen by the sweeping code. - This is a pointer to the first word after the fragment, which is - the header of the next block. - Note that [last_fragment] doesn't point to the fragment itself, - but to the block after it. -*/ -static header_t *nf_last_fragment; - -static void nf_init_merge (void) -{ - CAML_EV_ALLOC_FLUSH(); - nf_last_fragment = NULL; - caml_fl_merge = Nf_head; -#ifdef DEBUG - nf_check (); -#endif -} - -static void nf_init (void) -{ - Next_small (Nf_head) = Val_NULL; - nf_prev = Nf_head; - caml_fl_cur_wsz = 0; -} - -static void nf_reset (void) -{ - nf_init (); -} - -/* Note: the [limit] parameter is unused because we merge blocks one by one. */ -static header_t *nf_merge_block (value bp, char *limit) -{ - value prev, cur, adj; - header_t hd = Hd_val (bp); - mlsize_t prev_wosz; - - caml_fl_cur_wsz += Whsize_hd (hd); - - /* [merge_block] is now responsible for calling the finalization function. */ - if (Tag_hd (hd) == Custom_tag){ - void (*final_fun)(value) = Custom_ops_val(bp)->finalize; - if (final_fun != NULL) final_fun(bp); - } - -#ifdef DEBUG - caml_set_fields (bp, 0, Debug_free_major); -#endif - prev = caml_fl_merge; - cur = Next_small (prev); - /* The sweep code makes sure that this is the right place to insert - this block: */ - CAMLassert (Bp_val (prev) < Bp_val (bp) || prev == Nf_head); - CAMLassert (Bp_val (cur) > Bp_val (bp) || cur == Val_NULL); - - /* If [last_fragment] and [bp] are adjacent, merge them. */ - if (nf_last_fragment == Hp_val (bp)){ - mlsize_t bp_whsz = Whsize_val (bp); - if (bp_whsz <= Max_wosize){ - hd = Make_header (bp_whsz, 0, Caml_white); - bp = (value) nf_last_fragment; - Hd_val (bp) = hd; - caml_fl_cur_wsz += Whsize_wosize (0); - } - } - - /* If [bp] and [cur] are adjacent, remove [cur] from the free-list - and merge them. */ - adj = Next_in_mem (bp); - if (adj == cur){ - value next_cur = Next_small (cur); - mlsize_t cur_whsz = Whsize_val (cur); - - if (Wosize_hd (hd) + cur_whsz <= Max_wosize){ - Next_small (prev) = next_cur; - if (nf_prev == cur) nf_prev = prev; - hd = Make_header (Wosize_hd (hd) + cur_whsz, 0, Caml_blue); - Hd_val (bp) = hd; - adj = Next_in_mem (bp); -#ifdef DEBUG - nf_last = Val_NULL; - Next_small (cur) = (value) Debug_free_major; - Hd_val (cur) = Debug_free_major; -#endif - cur = next_cur; - } - } - /* If [prev] and [bp] are adjacent merge them, else insert [bp] into - the free-list if it is big enough. */ - prev_wosz = Wosize_val (prev); - if (Next_in_mem (prev) == bp && prev_wosz + Whsize_hd (hd) < Max_wosize){ - Hd_val (prev) = Make_header (prev_wosz + Whsize_hd (hd), 0, Caml_blue); -#ifdef DEBUG - Hd_val (bp) = Debug_free_major; -#endif - CAMLassert (caml_fl_merge == prev); - }else if (Wosize_hd (hd) != 0){ - Hd_val (bp) = Bluehd_hd (hd); - Next_small (bp) = cur; - Next_small (prev) = bp; - caml_fl_merge = bp; - }else{ - /* This is a fragment. Leave it in white but remember it for eventual - merging with the next block. */ - nf_last_fragment = (header_t *) bp; - caml_fl_cur_wsz -= Whsize_wosize (0); - } - return Hp_val (adj); -} - -/* This is a heap extension. We have to insert it in the right place - in the free-list. - [nf_add_blocks] can only be called right after a call to - [nf_allocate] that returned Val_NULL. - Most of the heap extensions are expected to be at the end of the - free list. (This depends on the implementation of [malloc].) - - [bp] must point to a list of blocks chained by their field 0, - terminated by Val_NULL, and field 1 of the first block must point to - the last block. -*/ -static void nf_add_blocks (value bp) -{ - value cur = bp; - CAMLassert (nf_last != Val_NULL); - CAMLassert (Next_small (nf_last) == Val_NULL); - do { - caml_fl_cur_wsz += Whsize_bp (cur); - cur = Field(cur, 0); - } while (cur != Val_NULL); - - if (Bp_val (bp) > Bp_val (nf_last)){ - Next_small (nf_last) = bp; - if (nf_last == caml_fl_merge && (char *) bp < caml_gc_sweep_hp){ - caml_fl_merge = Field (bp, 1); - } - }else{ - value prev; - - prev = Nf_head; - cur = Next_small (prev); - while (cur != Val_NULL && Bp_val (cur) < Bp_val (bp)){ - CAMLassert (Bp_val (prev) < Bp_val (bp) || prev == Nf_head); - prev = cur; - cur = Next_small (prev); - } - CAMLassert (Bp_val (prev) < Bp_val (bp) || prev == Nf_head); - CAMLassert (Bp_val (cur) > Bp_val (bp) || cur == Val_NULL); - Next_small (Field (bp, 1)) = cur; - Next_small (prev) = bp; - /* When inserting blocks between [caml_fl_merge] and [caml_gc_sweep_hp], - we must advance [caml_fl_merge] to the new block, so that [caml_fl_merge] - is always the last free-list block before [caml_gc_sweep_hp]. */ - if (prev == caml_fl_merge && (char *) bp < caml_gc_sweep_hp){ - caml_fl_merge = Field (bp, 1); - } - } -} - -static void nf_make_free_blocks - (value *p, mlsize_t size, int do_merge, int color) -{ - mlsize_t sz; - - while (size > 0){ - if (size > Whsize_wosize (Max_wosize)){ - sz = Whsize_wosize (Max_wosize); - }else{ - sz = size; - } - *(header_t *)p = Make_header (Wosize_whsize (sz), 0, color); - if (do_merge) nf_merge_block (Val_hp (p), NULL); - size -= sz; - p += sz; - } -} - -/******************** first-fit allocation policy *********************/ - -#define FLP_MAX 1000 -static value flp [FLP_MAX]; -static int flp_size = 0; -static value beyond = Val_NULL; - -/* The sentinel can be located anywhere in memory, but it must not be - adjacent to any heap object. */ -static struct { - value filler1; /* Make sure the sentinel is never adjacent to any block. */ - header_t h; - value first_field; - value filler2; /* Make sure the sentinel is never adjacent to any block. */ -} ff_sentinel = {0, Make_header (0, 0, Caml_blue), Val_NULL, 0}; - -#define Ff_head (Val_bp (&(ff_sentinel.first_field))) -static value ff_last = Val_NULL; /* Last block in the list. Only valid - just after [ff_allocate] returns NULL. */ - - -#if defined (DEBUG) || FREELIST_DEBUG -static void ff_check (void) -{ - value cur; - int flp_found = 0, merge_found = 0; - uintnat size_found = 0; - int sz = 0; - - cur = Next_small (Ff_head); - while (cur != Val_NULL){ - size_found += Whsize_bp (cur); - CAMLassert (Is_in_heap (cur)); - if (Wosize_bp (cur) > sz){ - sz = Wosize_bp (cur); - if (flp_found < flp_size){ - CAMLassert (Next_small (flp[flp_found]) == cur); - ++ flp_found; - }else{ - CAMLassert (beyond == Val_NULL - || Bp_val (cur) >= Bp_val (Next_small (beyond))); - } - } - if (cur == caml_fl_merge) merge_found = 1; - cur = Next_small (cur); - } - CAMLassert (flp_found == flp_size); - CAMLassert (merge_found || caml_fl_merge == Ff_head); - CAMLassert (size_found == caml_fl_cur_wsz); -} -#endif /* DEBUG || FREELIST_DEBUG */ - -/* [ff_allocate_block] is called by [ff_allocate]. Given a suitable free - block and the requested size, it allocates a new block from the free - block. There are three cases: - 0. The free block has the requested size. Detach the block from the - free-list and return it. - 1. The free block is 1 word longer than the requested size. Detach - the block from the free list. The remaining word cannot be linked: - turn it into an empty block (header only), and return the rest. - 2. The free block is large enough. Split it in two and return the right - block. - In all cases, the allocated block is right-justified in the free block: - it is located in the high-address words of the free block, so that - the linking of the free-list does not change in case 2. -*/ -static header_t *ff_allocate_block (mlsize_t wh_sz, int flpi, value prev, - value cur) -{ - header_t h = Hd_bp (cur); - CAMLassert (Whsize_hd (h) >= wh_sz); - if (Wosize_hd (h) < wh_sz + 1){ /* Cases 0 and 1. */ - caml_fl_cur_wsz -= Whsize_hd (h); - Next_small (prev) = Next_small (cur); - CAMLassert (Is_in_heap (Next_small (prev)) - || Next_small (prev) == Val_NULL); - if (caml_fl_merge == cur) caml_fl_merge = prev; -#ifdef DEBUG - ff_last = Val_NULL; -#endif - /* In case 1, the following creates the empty block correctly. - In case 0, it gives an invalid header to the block. The function - calling [ff_allocate] will overwrite it. */ - Hd_op (cur) = Make_header (0, 0, Caml_white); - if (flpi + 1 < flp_size && flp[flpi + 1] == cur){ - flp[flpi + 1] = prev; - }else if (flpi == flp_size - 1){ - beyond = (prev == Ff_head) ? Val_NULL : prev; - -- flp_size; - } - }else{ /* Case 2. */ - caml_fl_cur_wsz -= wh_sz; - Hd_op (cur) = Make_header (Wosize_hd (h) - wh_sz, 0, Caml_blue); - } - return (header_t *) &Field (cur, Wosize_hd (h) - wh_sz); -} - -static header_t *ff_allocate (mlsize_t wo_sz) -{ - value cur = Val_NULL, prev; - header_t *result; - int i; - mlsize_t sz, prevsz; - CAMLassert (sizeof (char *) == sizeof (value)); - CAMLassert (wo_sz >= 1); - - /* Search in the flp array. */ - for (i = 0; i < flp_size; i++){ - sz = Wosize_bp (Next_small (flp[i])); - if (sz >= wo_sz){ -#if FREELIST_DEBUG - if (i > 5) fprintf (stderr, "FLP: found at %d size=%d\n", i, wo_sz); -#endif - result = ff_allocate_block (Whsize_wosize (wo_sz), i, flp[i], - Next_small (flp[i])); - goto update_flp; - } - } - /* Extend the flp array. */ - if (flp_size == 0){ - prev = Ff_head; - prevsz = 0; - }else{ - prev = Next_small (flp[flp_size - 1]); - prevsz = Wosize_bp (prev); - if (beyond != Val_NULL) prev = beyond; - } - while (flp_size < FLP_MAX){ - cur = Next_small (prev); - if (cur == Val_NULL){ - ff_last = prev; - beyond = (prev == Ff_head) ? Val_NULL : prev; - return NULL; - }else{ - sz = Wosize_bp (cur); - if (sz > prevsz){ - flp[flp_size] = prev; - ++ flp_size; - if (sz >= wo_sz){ - beyond = cur; - i = flp_size - 1; -#if FREELIST_DEBUG - if (flp_size > 5){ - fprintf (stderr, "FLP: extended to %d\n", flp_size); - } -#endif - result = ff_allocate_block (Whsize_wosize (wo_sz), flp_size - 1, - prev, cur); - goto update_flp; - } - prevsz = sz; - } - } - prev = cur; - } - beyond = cur; - - /* The flp table is full. Do a slow first-fit search. */ -#if FREELIST_DEBUG - fprintf (stderr, "FLP: table is full -- slow first-fit\n"); -#endif - if (beyond != Val_NULL){ - prev = beyond; - }else{ - prev = flp[flp_size - 1]; - } - prevsz = Wosize_bp (Next_small (flp[FLP_MAX-1])); - CAMLassert (prevsz < wo_sz); - cur = Next_small (prev); - while (cur != Val_NULL){ - CAMLassert (Is_in_heap (cur)); - sz = Wosize_bp (cur); - if (sz < prevsz){ - beyond = cur; - }else if (sz >= wo_sz){ - return ff_allocate_block (Whsize_wosize (wo_sz), flp_size, prev, cur); - } - prev = cur; - cur = Next_small (prev); - } - ff_last = prev; - return NULL; - - update_flp: /* (i, sz) */ - /* The block at [i] was removed or reduced. Update the table. */ - CAMLassert (0 <= i && i < flp_size + 1); - if (i < flp_size){ - if (i > 0){ - prevsz = Wosize_bp (Next_small (flp[i-1])); - }else{ - prevsz = 0; - } - if (i == flp_size - 1){ - if (Wosize_bp (Next_small (flp[i])) <= prevsz){ - beyond = Next_small (flp[i]); - -- flp_size; - }else{ - beyond = Val_NULL; - } - }else{ - value buf [FLP_MAX]; - int j = 0; - mlsize_t oldsz = sz; - - prev = flp[i]; - while (prev != flp[i+1] && j < FLP_MAX - i){ - cur = Next_small (prev); - sz = Wosize_bp (cur); - if (sz > prevsz){ - buf[j++] = prev; - prevsz = sz; - if (sz >= oldsz){ - CAMLassert (sz == oldsz); - break; - } - } - prev = cur; - } -#if FREELIST_DEBUG - if (j > 2) fprintf (stderr, "FLP: update; buf size = %d\n", j); -#endif - if (FLP_MAX >= flp_size + j - 1){ - if (j != 1){ - memmove (&flp[i+j], &flp[i+1], sizeof (value) * (flp_size-i-1)); - } - if (j > 0) memmove (&flp[i], &buf[0], sizeof (value) * j); - flp_size += j - 1; - }else{ - if (FLP_MAX > i + j){ - if (j != 1){ - memmove (&flp[i+j], &flp[i+1], sizeof (value) * (FLP_MAX-i-j)); - } - if (j > 0) memmove (&flp[i], &buf[0], sizeof (value) * j); - }else{ - if (i != FLP_MAX){ - memmove (&flp[i], &buf[0], sizeof (value) * (FLP_MAX - i)); - } - } - flp_size = FLP_MAX - 1; - beyond = Next_small (flp[FLP_MAX - 1]); - } - } - } - return result; -} - -/* Location of the last fragment seen by the sweeping code. - This is a pointer to the first word after the fragment, which is - the header of the next block. - Note that [ff_last_fragment] doesn't point to the fragment itself, - but to the block after it. -*/ -static header_t *ff_last_fragment; - -static void ff_init_merge (void) -{ - CAML_EV_ALLOC_FLUSH(); - ff_last_fragment = NULL; - caml_fl_merge = Ff_head; -#ifdef DEBUG - ff_check (); -#endif -} - -static void ff_truncate_flp (value changed) -{ - if (changed == Ff_head){ - flp_size = 0; - beyond = Val_NULL; - }else{ - while (flp_size > 0 && - Bp_val (Next_small (flp[flp_size - 1])) >= Bp_val (changed)) - -- flp_size; - if (Bp_val (beyond) >= Bp_val (changed)) beyond = Val_NULL; - } -} - -static void ff_init (void) -{ - Next_small (Ff_head) = Val_NULL; - ff_truncate_flp (Ff_head); - caml_fl_cur_wsz = 0; -} - -static void ff_reset (void) -{ - ff_init (); -} - -/* Note: the [limit] parameter is unused because we merge blocks one by one. */ -static header_t *ff_merge_block (value bp, char *limit) -{ - value prev, cur, adj; - header_t hd = Hd_val (bp); - mlsize_t prev_wosz; - - caml_fl_cur_wsz += Whsize_hd (hd); - - /* [merge_block] is now responsible for calling the finalization function. */ - if (Tag_hd (hd) == Custom_tag){ - void (*final_fun)(value) = Custom_ops_val(bp)->finalize; - if (final_fun != NULL) final_fun(bp); - } - -#ifdef DEBUG - caml_set_fields (bp, 0, Debug_free_major); -#endif - prev = caml_fl_merge; - cur = Next_small (prev); - /* The sweep code makes sure that this is the right place to insert - this block: */ - CAMLassert (Bp_val (prev) < Bp_val (bp) || prev == Ff_head); - CAMLassert (Bp_val (cur) > Bp_val (bp) || cur == Val_NULL); - - ff_truncate_flp (prev); - - /* If [ff_last_fragment] and [bp] are adjacent, merge them. */ - if (ff_last_fragment == Hp_bp (bp)){ - mlsize_t bp_whsz = Whsize_val (bp); - if (bp_whsz <= Max_wosize){ - hd = Make_header (bp_whsz, 0, Caml_white); - bp = (value) ff_last_fragment; - Hd_val (bp) = hd; - caml_fl_cur_wsz += Whsize_wosize (0); - } - } - - /* If [bp] and [cur] are adjacent, remove [cur] from the free-list - and merge them. */ - adj = Next_in_mem (bp); - if (adj == cur){ - value next_cur = Next_small (cur); - mlsize_t cur_whsz = Whsize_val (cur); - - if (Wosize_hd (hd) + cur_whsz <= Max_wosize){ - Next_small (prev) = next_cur; - hd = Make_header (Wosize_hd (hd) + cur_whsz, 0, Caml_blue); - Hd_val (bp) = hd; - adj = Next_in_mem (bp); -#ifdef DEBUG - ff_last = Val_NULL; - Next_small (cur) = (value) Debug_free_major; - Hd_val (cur) = Debug_free_major; -#endif - cur = next_cur; - } - } - /* If [prev] and [bp] are adjacent merge them, else insert [bp] into - the free-list if it is big enough. */ - prev_wosz = Wosize_val (prev); - if (Next_in_mem (prev) == bp && prev_wosz + Whsize_hd (hd) < Max_wosize){ - Hd_val (prev) = Make_header (prev_wosz + Whsize_hd (hd), 0, Caml_blue); -#ifdef DEBUG - Hd_val (bp) = Debug_free_major; -#endif - CAMLassert (caml_fl_merge == prev); - }else if (Wosize_hd (hd) != 0){ - Hd_val (bp) = Bluehd_hd (hd); - Next_small (bp) = cur; - Next_small (prev) = bp; - caml_fl_merge = bp; - }else{ - /* This is a fragment. Leave it in white but remember it for eventual - merging with the next block. */ - ff_last_fragment = (header_t *) bp; - caml_fl_cur_wsz -= Whsize_wosize (0); - } - return Hp_val (adj); -} - -/* This is a heap extension. We have to insert it in the right place - in the free-list. - [ff_add_blocks] can only be called right after a call to - [ff_allocate] that returned Val_NULL. - Most of the heap extensions are expected to be at the end of the - free list. (This depends on the implementation of [malloc].) - - [bp] must point to a list of blocks chained by their field 0, - terminated by Val_NULL, and field 1 of the first block must point to - the last block. -*/ -static void ff_add_blocks (value bp) -{ - value cur = bp; - CAMLassert (ff_last != Val_NULL); - CAMLassert (Next_small (ff_last) == Val_NULL); - do { - caml_fl_cur_wsz += Whsize_bp (cur); - cur = Field(cur, 0); - } while (cur != Val_NULL); - - if (Bp_val (bp) > Bp_val (ff_last)){ - Next_small (ff_last) = bp; - if (ff_last == caml_fl_merge && (char *) bp < caml_gc_sweep_hp){ - caml_fl_merge = Field (bp, 1); - } - if (flp_size < FLP_MAX){ - flp [flp_size++] = ff_last; - } - }else{ - value prev; - - prev = Ff_head; - cur = Next_small (prev); - while (cur != Val_NULL && Bp_val (cur) < Bp_val (bp)){ - CAMLassert (Bp_val (prev) < Bp_val (bp) || prev == Ff_head); - /* XXX TODO: extend flp on the fly */ - prev = cur; - cur = Next_small (prev); - } - CAMLassert (Bp_val (prev) < Bp_val (bp) || prev == Ff_head); - CAMLassert (Bp_val (cur) > Bp_val (bp) || cur == Val_NULL); - Next_small (Field (bp, 1)) = cur; - Next_small (prev) = bp; - /* When inserting blocks between [caml_fl_merge] and [caml_gc_sweep_hp], - we must advance [caml_fl_merge] to the new block, so that [caml_fl_merge] - is always the last free-list block before [caml_gc_sweep_hp]. */ - if (prev == caml_fl_merge && (char *) bp < caml_gc_sweep_hp){ - caml_fl_merge = Field (bp, 1); - } - ff_truncate_flp (bp); - } -} - -static void ff_make_free_blocks - (value *p, mlsize_t size, int do_merge, int color) -{ - mlsize_t sz; - - while (size > 0){ - if (size > Whsize_wosize (Max_wosize)){ - sz = Whsize_wosize (Max_wosize); - }else{ - sz = size; - } - *(header_t *)p = Make_header (Wosize_whsize (sz), 0, color); - if (do_merge) ff_merge_block (Val_hp (p), NULL); - size -= sz; - p += sz; - } -} - -/********************* best-fit allocation policy *********************/ - -/* quick-fit + FIFO-ordered best fit (Wilson's nomenclature) - We use Standish's data structure (a tree of doubly-linked lists) - with a splay tree (Sleator & Tarjan). -*/ - -/* [BF_NUM_SMALL] must be at least 4 for this code to work - and at least 5 for good performance on typical OCaml programs. - For portability reasons, BF_NUM_SMALL cannot be more than 32. -*/ -#define BF_NUM_SMALL 16 - -/* Note that indexing into [bf_small_fl] starts at 1, so the first entry - in this array is unused. -*/ -static struct { - value free; - value *merge; -} bf_small_fl [BF_NUM_SMALL + 1]; -static int bf_small_map = 0; - -/* Small free blocks have only one pointer to the next block. - Large free blocks have 5 fields: - tree fields: - - isnode flag - - left child - - right child - list fields: - - next - - prev -*/ -typedef struct large_free_block { - int isnode; - struct large_free_block *left; - struct large_free_block *right; - struct large_free_block *prev; - struct large_free_block *next; -} large_free_block; - -Caml_inline mlsize_t bf_large_wosize (struct large_free_block *n) { - return Wosize_val((value)(n)); -} - -static struct large_free_block *bf_large_tree; -static struct large_free_block *bf_large_least; -/* [bf_large_least] is either NULL or a pointer to the smallest (leftmost) - block in the tree. In this latter case, the block must be alone in its - doubly-linked list (i.e. have [isnode] true and [prev] and [next] - both pointing back to this block) -*/ - -/* Auxiliary functions for bitmap */ - -/* Find first (i.e. least significant) bit set in a word. */ -#ifdef HAS_FFS -#include <strings.h> -#elif defined(HAS_BITSCANFORWARD) -#include <intrin.h> -Caml_inline int ffs (int x) -{ - unsigned long index; - unsigned char result; - result = _BitScanForward (&index, (unsigned long) x); - return result ? (int) index + 1 : 0; -} -#else -Caml_inline int ffs (int x) -{ - /* adapted from Hacker's Delight */ - int bnz, b0, b1, b2, b3, b4; - CAMLassert ((x & 0xFFFFFFFF) == x); - x = x & -x; - bnz = x != 0; - b4 = !!(x & 0xFFFF0000) << 4; - b3 = !!(x & 0xFF00FF00) << 3; - b2 = !!(x & 0xF0F0F0F0) << 2; - b1 = !!(x & 0xCCCCCCCC) << 1; - b0 = !!(x & 0xAAAAAAAA); - return bnz + b0 + b1 + b2 + b3 + b4; -} -#endif /* HAS_FFS or HAS_BITSCANFORWARD */ - -/* Indexing starts at 1 because that's the minimum block size. */ -Caml_inline void set_map (int index) -{ - bf_small_map |= (1 << (index - 1)); -} -Caml_inline void unset_map (int index) -{ - bf_small_map &= ~(1 << (index - 1)); -} - - -/* debug functions for checking the data structures */ - -#if defined (DEBUG) || FREELIST_DEBUG - -static mlsize_t bf_check_cur_size = 0; -static asize_t bf_check_subtree (large_free_block *p) -{ - mlsize_t wosz; - large_free_block *cur, *next; - asize_t total_size = 0; - - if (p == NULL) return 0; - - wosz = bf_large_wosize(p); - CAMLassert (p->isnode == 1); - total_size += bf_check_subtree (p->left); - CAMLassert (wosz > BF_NUM_SMALL); - CAMLassert (wosz > bf_check_cur_size); - bf_check_cur_size = wosz; - cur = p; - while (1){ - CAMLassert (bf_large_wosize (cur) == wosz); - CAMLassert (Color_val ((value) cur) == Caml_blue); - CAMLassert ((cur == p && cur->isnode == 1) || cur->isnode == 0); - total_size += Whsize_wosize (wosz); - next = cur->next; - CAMLassert (next->prev == cur); - if (next == p) break; - cur = next; - } - total_size += bf_check_subtree (p->right); - return total_size; -} - -static void bf_check (void) -{ - mlsize_t i; - asize_t total_size = 0; - int map = 0; - - /* check free lists */ - CAMLassert (BF_NUM_SMALL <= 8 * sizeof (int)); - for (i = 1; i <= BF_NUM_SMALL; i++){ - value b; - int col = 0; - int merge_found = 0; - - if (bf_small_fl[i].merge == &bf_small_fl[i].free){ - merge_found = 1; - }else{ - CAMLassert (caml_gc_phase != Phase_sweep - || caml_fl_merge == Val_NULL - || bf_small_fl[i].merge < &Next_small(caml_fl_merge)); - } - CAMLassert (*bf_small_fl[i].merge == Val_NULL - || Color_val (*bf_small_fl[i].merge) == Caml_blue); - if (bf_small_fl[i].free != Val_NULL) map |= 1 << (i-1); - for (b = bf_small_fl[i].free; b != Val_NULL; b = Next_small (b)){ - if (bf_small_fl[i].merge == &Next_small (b)) merge_found = 1; - CAMLassert (Wosize_val (b) == i); - total_size += Whsize_wosize (i); - if (Color_val (b) == Caml_blue){ - col = 1; - CAMLassert (Next_small (b) == Val_NULL - || Bp_val (Next_small (b)) > Bp_val (b)); - }else{ - CAMLassert (col == 0); - CAMLassert (Color_val (b) == Caml_white); - } - } - if (caml_gc_phase == Phase_sweep) CAMLassert (merge_found); - } - CAMLassert (map == bf_small_map); - /* check [caml_fl_merge] */ - CAMLassert (caml_gc_phase != Phase_sweep - || caml_fl_merge == Val_NULL - || Hp_val (caml_fl_merge) < (header_t *) caml_gc_sweep_hp); - /* check the tree */ - bf_check_cur_size = 0; - total_size += bf_check_subtree (bf_large_tree); - /* check the total free set size */ - CAMLassert (total_size == caml_fl_cur_wsz); - /* check the smallest-block pointer */ - if (bf_large_least != NULL){ - large_free_block *x = bf_large_tree; - while (x->left != NULL) x = x->left; - CAMLassert (x == bf_large_least); - CAMLassert (x->isnode == 1); - CAMLassert (x->prev == x); - CAMLassert (x->next == x); - } -} - -#endif /* DEBUG || FREELIST_DEBUG */ - -#if FREELIST_DEBUG -#define FREELIST_DEBUG_bf_check() bf_check () -#else -#define FREELIST_DEBUG_bf_check() -#endif - -/**************************************************************************/ -/* splay trees */ - -/* Our tree is composed of nodes. Each node is the head of a doubly-linked - circular list of blocks, all of the same size. -*/ - -/* Search for the node of the given size. Return a pointer to the pointer - to the node, or a pointer to the NULL where the node should have been - (it can be inserted here). -*/ -static large_free_block **bf_search (mlsize_t wosz) -{ - large_free_block **p = &bf_large_tree; - large_free_block *cur; - mlsize_t cursz; - - while (1){ - cur = *p; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (1)); - if (cur == NULL) break; - cursz = bf_large_wosize (cur); - if (cursz == wosz){ - break; - }else if (cursz > wosz){ - p = &(cur->left); - }else{ - CAMLassert (cursz < wosz); - p = &(cur->right); - } - } - return p; -} - -/* Search for the least node that is large enough to accommodate the given - size. Return in [next_lower] an upper bound on either the size of the - next-lower node in the tree, or BF_NUM_SMALL if there is no such node. -*/ -static large_free_block **bf_search_best (mlsize_t wosz, mlsize_t *next_lower) -{ - large_free_block **p = &bf_large_tree; - large_free_block **best = NULL; - mlsize_t lowsz = BF_NUM_SMALL; - large_free_block *cur; - mlsize_t cursz; - - while (1){ - cur = *p; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (1)); - if (cur == NULL){ - *next_lower = lowsz; - break; - } - cursz = bf_large_wosize (cur); - if (cursz == wosz){ - best = p; - *next_lower = wosz; - break; - }else if (cursz > wosz){ - best = p; - p = &(cur->left); - }else{ - CAMLassert (cursz < wosz); - lowsz = cursz; - p = &(cur->right); - } - } - return best; -} - -/* Splay the tree at the given size. If a node of this size exists, it will - become the root. If not, the last visited node will be the root. This is - either the least node larger or the greatest node smaller than the given - size. - We use simple top-down splaying as described in S&T 85. -*/ -static void bf_splay (mlsize_t wosz) -{ - large_free_block *x, *y; - mlsize_t xsz; - large_free_block *left_top = NULL; - large_free_block *right_top = NULL; - large_free_block **left_bottom = &left_top; - large_free_block **right_bottom = &right_top; - - x = bf_large_tree; - if (x == NULL) return; - while (1){ - xsz = bf_large_wosize (x); - if (xsz == wosz) break; - if (xsz > wosz){ - /* zig */ - y = x->left; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (1)); - if (y == NULL) break; - if (bf_large_wosize (y) > wosz){ - /* zig-zig: rotate right */ - x->left = y->right; - y->right = x; - x = y; - y = x->left; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (2)); - if (y == NULL) break; - } - /* link right */ - *right_bottom = x; - right_bottom = &(x->left); - x = y; - }else{ - CAMLassert (xsz < wosz); - /* zag */ - y = x->right; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (1)); - if (y == NULL) break; - if (bf_large_wosize (y) < wosz){ - /* zag-zag : rotate left */ - x->right = y->left; - y->left = x; - x = y; - y = x->right; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (2)); - if (y == NULL) break; - } - /* link left */ - *left_bottom = x; - left_bottom = &(x->right); - x = y; - } - } - /* reassemble the tree */ - *left_bottom = x->left; - *right_bottom = x->right; - x->left = left_top; - x->right = right_top; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (2)); - bf_large_tree = x; -} - -/* Splay the subtree at [p] on its leftmost (least) node. After this - operation, the root node of the subtree is the least node and it - has no left child. - The subtree must not be empty. -*/ -static void bf_splay_least (large_free_block **p) -{ - large_free_block *x, *y; - large_free_block *right_top = NULL; - large_free_block **right_bottom = &right_top; - - x = *p; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (1)); - CAMLassert (x != NULL); - while (1){ - /* We are always in the zig case. */ - y = x->left; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (1)); - if (y == NULL) break; - /* And in the zig-zig case. rotate right */ - x->left = y->right; - y->right = x; - x = y; - y = x->left; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (2)); - if (y == NULL) break; - /* link right */ - *right_bottom = x; - right_bottom = &(x->left); - x = y; - } - /* reassemble the tree */ - CAMLassert (x->left == NULL); - *right_bottom = x->right; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (1)); - x->right = right_top; - *p = x; -} - -/* Remove the node at [p], if any. */ -static void bf_remove_node (large_free_block **p) -{ - large_free_block *x; - large_free_block *l, *r; - - x = *p; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (1)); - if (x == NULL) return; - if (x == bf_large_least) bf_large_least = NULL; - l = x->left; - r = x->right; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (2)); - if (l == NULL){ - *p = r; - }else if (r == NULL){ - *p = l; - }else{ - bf_splay_least (&r); - r->left = l; - *p = r; - } -} - -/* Insert a block into the tree, either as a new node or as a block in an - existing list. - Splay if the list is already present. -*/ -static void bf_insert_block (large_free_block *n) -{ - mlsize_t sz = bf_large_wosize (n); - large_free_block **p = bf_search (sz); - large_free_block *x = *p; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (1)); - - if (bf_large_least != NULL){ - mlsize_t least_sz = bf_large_wosize (bf_large_least); - if (sz < least_sz){ - CAMLassert (x == NULL); - bf_large_least = n; - }else if (sz == least_sz){ - CAMLassert (x == bf_large_least); - bf_large_least = NULL; - } - } - - CAMLassert (Color_val ((value) n) == Caml_blue); - CAMLassert (Wosize_val ((value) n) > BF_NUM_SMALL); - if (x == NULL){ - /* add new node */ - n->isnode = 1; - n->left = n->right = NULL; - n->prev = n->next = n; - *p = n; - }else{ - /* insert at tail of doubly-linked list */ - CAMLassert (x->isnode == 1); - n->isnode = 0; -#ifdef DEBUG - n->left = n->right = (large_free_block *) Debug_free_unused; -#endif - n->prev = x->prev; - n->next = x; - x->prev->next = n; - x->prev = n; - CAML_EVENTLOG_DO(EV_ALLOC_JUMP (2)); - bf_splay (sz); - } -} - -#if defined (DEBUG) || FREELIST_DEBUG -static int bf_is_in_tree (large_free_block *b) -{ - int wosz = bf_large_wosize (b); - large_free_block **p = bf_search (wosz); - large_free_block *n = *p; - large_free_block *cur = n; - - if (n == NULL) return 0; - while (1){ - if (cur == b) return 1; - cur = cur->next; - if (cur == n) return 0; - } -} -#endif /* DEBUG || FREELIST_DEBUG */ - -/**************************************************************************/ - -/* Add back a remnant into a small free list. The block must be small - and white (or a 0-size fragment). - The block may be left out of the list depending on the sweeper's state. - The free list size is updated accordingly. - - The block will be left out of the list if the GC is in its Sweep phase - and the block is in the still-to-be-swept region because every block of - the free list encountered by the sweeper must be blue and linked in - its proper place in the increasing-addresses order of the list. This is - to ensure that coalescing is always done when two or more free blocks - are adjacent. -*/ -static void bf_insert_remnant_small (value v) -{ - mlsize_t wosz = Wosize_val (v); - - CAMLassert (Color_val (v) == Caml_white); - CAMLassert (wosz <= BF_NUM_SMALL); - if (wosz != 0 - && (caml_gc_phase != Phase_sweep - || (char *) Hp_val (v) < (char *) caml_gc_sweep_hp)){ - caml_fl_cur_wsz += Whsize_wosize (wosz); - Next_small (v) = bf_small_fl[wosz].free; - bf_small_fl[wosz].free = v; - if (bf_small_fl[wosz].merge == &bf_small_fl[wosz].free){ - bf_small_fl[wosz].merge = &Next_small (v); - } - set_map (wosz); - } -} - -/* Add back a remnant into the free set. The block must have the - appropriate color: - - White if it is a fragment or a small block (wosize <= BF_NUM_SMALL) - - Blue if it is a large block (BF_NUM_SMALL < wosize) - The block may be left out or the set, depending on its size and the - sweeper's state. - The free list size is updated accordingly. -*/ -static void bf_insert_remnant (value v) -{ - mlsize_t wosz = Wosize_val (v); - - if (wosz <= BF_NUM_SMALL){ - CAMLassert (Color_val (v) == Caml_white); - bf_insert_remnant_small (v); - }else{ - CAMLassert (Color_val (v) == Caml_blue); - bf_insert_block ((large_free_block *) v); - caml_fl_cur_wsz += Whsize_wosize (wosz); - } -} -/* Insert the block into the free set during sweep. The block must be blue. */ -static void bf_insert_sweep (value v) -{ - mlsize_t wosz = Wosize_val (v); - value next; - - CAMLassert (Color_val (v) == Caml_blue); - if (wosz <= BF_NUM_SMALL){ - while (1){ - next = *bf_small_fl[wosz].merge; - if (next == Val_NULL){ - set_map (wosz); - break; - } - if (Bp_val (next) >= Bp_val (v)) break; - bf_small_fl[wosz].merge = &Next_small (next); - } - Next_small (v) = *bf_small_fl[wosz].merge; - *bf_small_fl[wosz].merge = v; - bf_small_fl[wosz].merge = &Next_small (v); - }else{ - bf_insert_block ((large_free_block *) v); - } -} - -/* Remove a given block from the free set. */ -static void bf_remove (value v) -{ - mlsize_t wosz = Wosize_val (v); - - CAMLassert (Color_val (v) == Caml_blue); - if (wosz <= BF_NUM_SMALL){ - while (*bf_small_fl[wosz].merge != v){ - CAMLassert (Bp_val (*bf_small_fl[wosz].merge) < Bp_val (v)); - bf_small_fl[wosz].merge = &Next_small (*bf_small_fl[wosz].merge); - } - *bf_small_fl[wosz].merge = Next_small (v); - if (bf_small_fl[wosz].free == Val_NULL) unset_map (wosz); - }else{ - large_free_block *b = (large_free_block *) v; - CAMLassert (bf_is_in_tree (b)); - CAMLassert (b->prev->next == b); - CAMLassert (b->next->prev == b); - if (b->isnode){ - large_free_block **p = bf_search (bf_large_wosize (b)); - CAMLassert (*p != NULL); - if (b->next == b){ - bf_remove_node (p); - }else{ - large_free_block *n = b->next; - n->prev = b->prev; - b->prev->next = n; - *p = n; - n->isnode = 1; - n->left = b->left; - n->right = b->right; -#ifdef DEBUG - Field ((value) b, 0) = Debug_free_major; - b->left = b->right = b->next = b->prev = - (large_free_block *) Debug_free_major; -#endif - } - }else{ - b->prev->next = b->next; - b->next->prev = b->prev; - } - } -} - -/* Split the given block, return a new block of the given size. - The remnant is still at the same address, its size is changed - and its color becomes white. - The size of the free set is decremented by the whole block size - and the caller must readjust it if the remnant is reinserted or - remains in the free set. - The size of [v] must be strictly greater than [wosz]. -*/ -static header_t *bf_split_small (mlsize_t wosz, value v) -{ - intnat blocksz = Whsize_val (v); - intnat remwhsz = blocksz - Whsize_wosize (wosz); - - CAMLassert (Wosize_val (v) > wosz); - caml_fl_cur_wsz -= blocksz; - Hd_val (v) = Make_header (Wosize_whsize (remwhsz), Abstract_tag, Caml_white); - return (header_t *) &Field (v, Wosize_whsize (remwhsz)); -} - -/* Split the given block, return a new block of the given size. - The original block is at the same address but its size is changed. - Its color and tag are changed as appropriate for calling the - insert_remnant* functions. - The size of the free set is decremented by the whole block size - and the caller must readjust it if the remnant is reinserted or - remains in the free set. - The size of [v] must be strictly greater than [wosz]. -*/ -static header_t *bf_split (mlsize_t wosz, value v) -{ - header_t hd = Hd_val (v); - mlsize_t remwhsz = Whsize_hd (hd) - Whsize_wosize (wosz); - - CAMLassert (Wosize_val (v) > wosz); - CAMLassert (remwhsz > 0); - caml_fl_cur_wsz -= Whsize_hd (hd); - if (remwhsz <= Whsize_wosize (BF_NUM_SMALL)){ - /* Same as bf_split_small. */ - Hd_val (v) = Make_header (Wosize_whsize(remwhsz), Abstract_tag, Caml_white); - }else{ - Hd_val (v) = Make_header (Wosize_whsize (remwhsz), 0, Caml_blue); - } - return (header_t *) &Field (v, Wosize_whsize (remwhsz)); -} - -/* Allocate from a large block at [p]. If the node is single and the remaining - size is greater than [bound], it stays at the same place in the tree. - If [set_least] is true, [wosz] is guaranteed to be [<= BF_NUM_SMALL], so - the block has the smallest size in the tree. - In this case, the large block becomes (or remains) the single smallest - in the tree and we set the [bf_large_least] pointer. -*/ -static header_t *bf_alloc_from_large (mlsize_t wosz, large_free_block **p, - mlsize_t bound, int set_least) -{ - large_free_block *n = *p; - large_free_block *b; - header_t *result; - mlsize_t wosize_n = bf_large_wosize (n); - - CAMLassert (bf_large_wosize (n) >= wosz); - if (n->next == n){ - if (wosize_n > bound + Whsize_wosize (wosz)){ - /* TODO splay at [n]? if the remnant is larger than [wosz]? */ - if (set_least){ - CAMLassert (bound == BF_NUM_SMALL); - bf_large_least = n; - } - result = bf_split (wosz, (value) n); - caml_fl_cur_wsz += Whsize_wosize (wosize_n) - Whsize_wosize (wosz); - /* remnant stays in tree */ - return result; - }else{ - bf_remove_node (p); - if (wosize_n == wosz){ - caml_fl_cur_wsz -= Whsize_wosize (wosz); - return Hp_val ((value) n); - }else{ - result = bf_split (wosz, (value) n); - bf_insert_remnant ((value) n); - return result; - } - } - }else{ - b = n->next; - CAMLassert (bf_large_wosize (b) == bf_large_wosize (n)); - n->next = b->next; - b->next->prev = n; - if (wosize_n == wosz){ - caml_fl_cur_wsz -= Whsize_wosize (wosz); - return Hp_val ((value) b); - }else{ - result = bf_split (wosz, (value) b); - bf_insert_remnant ((value) b); - /* TODO: splay at [n] if the remnant is smaller than [wosz] */ - if (set_least){ - CAMLassert (bound == BF_NUM_SMALL); - if (bf_large_wosize (b) > BF_NUM_SMALL){ - bf_large_least = b; - } - } - return result; - } - } -} - -static header_t *bf_allocate_from_tree (mlsize_t wosz, int set_least) -{ - large_free_block **n; - mlsize_t bound; - - n = bf_search_best (wosz, &bound); - if (n == NULL) return NULL; - return bf_alloc_from_large (wosz, n, bound, set_least); -} - -static header_t *bf_allocate (mlsize_t wosz) -{ - value block; - header_t *result; - - CAMLassert (sizeof (char *) == sizeof (value)); - CAMLassert (wosz >= 1); - - if (wosz <= BF_NUM_SMALL){ - if (bf_small_fl[wosz].free != Val_NULL){ - /* fast path: allocate from the corresponding free list */ - block = bf_small_fl[wosz].free; - if (bf_small_fl[wosz].merge == &Next_small (block)){ - bf_small_fl[wosz].merge = &bf_small_fl[wosz].free; - } - bf_small_fl[wosz].free = Next_small (block); - if (bf_small_fl[wosz].free == Val_NULL) unset_map (wosz); - caml_fl_cur_wsz -= Whsize_wosize (wosz); - FREELIST_DEBUG_bf_check (); - return Hp_val (block); - }else{ - /* allocate from the next available size */ - mlsize_t s = ffs (bf_small_map & ((~0U) << wosz)); - FREELIST_DEBUG_bf_check (); - if (s != 0){ - block = bf_small_fl[s].free; - CAMLassert (block != Val_NULL); - if (bf_small_fl[s].merge == &Next_small (block)){ - bf_small_fl[s].merge = &bf_small_fl[s].free; - } - bf_small_fl[s].free = Next_small (block); - if (bf_small_fl[s].free == Val_NULL) unset_map (s); - result = bf_split_small (wosz, block); - bf_insert_remnant_small (block); - FREELIST_DEBUG_bf_check (); - return result; - } - } - /* Failed to find a suitable small block: try [bf_large_least]. */ - if (bf_large_least != NULL){ - mlsize_t least_wosz = bf_large_wosize (bf_large_least); - if (least_wosz > BF_NUM_SMALL + Whsize_wosize (wosz)){ - result = bf_split (wosz, (value) bf_large_least); - caml_fl_cur_wsz += Whsize_wosize (least_wosz) - Whsize_wosize (wosz); - /* remnant stays in tree */ - CAMLassert (Color_val ((value) bf_large_least) == Caml_blue); - return result; - } - } - - /* Allocate from the tree and update [bf_large_least]. */ - result = bf_allocate_from_tree (wosz, 1); - FREELIST_DEBUG_bf_check (); - return result; - }else{ - result = bf_allocate_from_tree (wosz, 0); - FREELIST_DEBUG_bf_check (); - return result; - } -} - -static void bf_init_merge (void) -{ - mlsize_t i; - - CAML_EV_ALLOC_FLUSH(); - - caml_fl_merge = Val_NULL; - - for (i = 1; i <= BF_NUM_SMALL; i++){ - /* At the beginning of each small free list is a segment of remnants - that were pushed back to the list after splitting. These are white - and they are not in order. We need to remove them - from the list for coalescing to work. They - will be picked up by the sweeping code and inserted in the right - place in the list. - */ - value p = bf_small_fl[i].free; - while (1){ - if (p == Val_NULL){ - unset_map (i); - break; - } - if (Color_val (p) == Caml_blue) break; - CAMLassert (Color_val (p) == Caml_white); - caml_fl_cur_wsz -= Whsize_val (p); - p = Next_small (p); - } - bf_small_fl[i].free = p; - /* Set the merge pointer to its initial value */ - bf_small_fl[i].merge = &bf_small_fl[i].free; - } -} - -static void bf_init (void) -{ - mlsize_t i; - - for (i = 1; i <= BF_NUM_SMALL; i++){ - bf_small_fl[i].free = Val_NULL; - bf_small_fl[i].merge = &bf_small_fl[i].free; - } - bf_small_map = 0; - bf_large_tree = NULL; - bf_large_least = NULL; - caml_fl_cur_wsz = 0; -} - -/* Make sure all free blocks are blue and tear down the BF data structures. */ -static void bf_reset (void) -{ - mlsize_t i; - - for (i = 1; i <= BF_NUM_SMALL; i++){ - /* At the beginning of each small free list is a segment of remnants - that were pushed back to the list after splitting. These are white - and they are not in order. We must make them blue before we can - compact or change the allocator policy. - */ - value p = bf_small_fl[i].free; - while (1){ - if (p == Val_NULL || Color_val (p) == Caml_blue) break; - CAMLassert (Color_val (p) == Caml_white); - Hd_val (p) = Bluehd_hd (Hd_val (p)); - p = Next_small (p); - } - } - /* We have no malloced data structures, so we can just call [bf_init] to - clear all our pointers. */ - bf_init (); -} - -static header_t *bf_merge_block (value bp, char *limit) -{ - value start; - value cur; - mlsize_t wosz; - - CAMLassert (Color_val (bp) == Caml_white); - /* Find the starting point of the current run of free blocks. */ - if (caml_fl_merge != Val_NULL && Next_in_mem (caml_fl_merge) == bp - && Color_val (caml_fl_merge) == Caml_blue){ - start = caml_fl_merge; - bf_remove (start); - }else{ - start = bp; - } - cur = bp; - while (1){ - /* This slightly convoluted loop is just going over the run of - white or blue blocks, doing the right thing for each color, and - stopping on a gray or black block or when limit is passed. - It is convoluted because we start knowing that the first block - is white. */ - white: - if (Tag_val (cur) == Custom_tag){ - void (*final_fun)(value) = Custom_ops_val(cur)->finalize; - if (final_fun != NULL) final_fun(cur); - } - caml_fl_cur_wsz += Whsize_val (cur); - next: - cur = Next_in_mem (cur); - if (Hp_val (cur) >= (header_t *) limit){ - CAMLassert (Hp_val (cur) == (header_t *) limit); - goto end_of_run; - } - switch (Color_val (cur)){ - case Caml_white: goto white; - case Caml_blue: bf_remove (cur); goto next; - case Caml_gray: - case Caml_black: - goto end_of_run; - } - } - end_of_run: - wosz = Wosize_whsize ((value *) cur - (value *) start); -#ifdef DEBUG - { - value *p; - for (p = (value *) start; p < (value *) Hp_val (cur); p++){ - *p = Debug_free_major; - } - } -#endif - while (wosz > Max_wosize){ - Hd_val (start) = Make_header (Max_wosize, 0, Caml_blue); - bf_insert_sweep (start); - start = Next_in_mem (start); - wosz -= Whsize_wosize (Max_wosize); - } - if (wosz > 0){ - Hd_val (start) = Make_header (wosz, 0, Caml_blue); - bf_insert_sweep (start); - }else{ - Hd_val (start) = Make_header (0, 0, Caml_white); - caml_fl_cur_wsz -= Whsize_wosize (0); - } - FREELIST_DEBUG_bf_check (); - return Hp_val (cur); -} - -static void bf_add_blocks (value bp) -{ - while (bp != Val_NULL){ - value next = Next_small (bp); - mlsize_t wosz = Wosize_val (bp); - - if (wosz > BF_NUM_SMALL){ - caml_fl_cur_wsz += Whsize_wosize (wosz); - bf_insert_block ((large_free_block *) bp); - }else{ - Hd_val (bp) = Make_header (wosz, Abstract_tag, Caml_white); - bf_insert_remnant_small (bp); - } - bp = next; - } -} - -static void bf_make_free_blocks (value *p, mlsize_t size, int do_merge, - int color) -{ - mlsize_t sz, wosz; - - while (size > 0){ - if (size > Whsize_wosize (Max_wosize)){ - sz = Whsize_wosize (Max_wosize); - }else{ - sz = size; - } - wosz = Wosize_whsize (sz); - if (do_merge){ - if (wosz <= BF_NUM_SMALL){ - color = Caml_white; - }else{ - color = Caml_blue; - } - *(header_t *)p = Make_header (wosz, 0, color); - bf_insert_remnant (Val_hp (p)); - }else{ - *(header_t *)p = Make_header (wosz, 0, color); - } - size -= sz; - p += sz; - } -} - -/*********************** policy selection *****************************/ - -enum { - policy_next_fit = 0, - policy_first_fit = 1, - policy_best_fit = 2, -}; - -uintnat caml_allocation_policy = policy_next_fit; - -/********************* exported functions *****************************/ - -/* [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, or NULL if no suitable block - is found in the free set. -*/ -header_t *(*caml_fl_p_allocate) (mlsize_t wo_sz) = &nf_allocate; - -/* Initialize the merge_block machinery (at start of sweeping). */ -void (*caml_fl_p_init_merge) (void) = &nf_init_merge; - -/* These are called internally. */ -static void (*caml_fl_p_init) (void) = &nf_init; -static void (*caml_fl_p_reset) (void) = &nf_reset; - -/* [caml_fl_merge_block] returns the head pointer of the next block after [bp], - because merging blocks may change the size of [bp]. */ -header_t *(*caml_fl_p_merge_block) (value bp, char *limit) = &nf_merge_block; - -/* [bp] must point to a list of blocks of wosize >= 1 chained by their field 0, - terminated by Val_NULL, and field 1 of the first block must point to - the last block. - The blocks must be blue. -*/ -void (*caml_fl_p_add_blocks) (value bp) = &nf_add_blocks; - -/* Cut a block of memory into pieces of size [Max_wosize], give them headers, - and optionally merge them into the free list. - arguments: - p: pointer to the first word of the block - size: size of the block (in words) - do_merge: 1 -> do merge; 0 -> do not merge - color: which color to give to the pieces; if [do_merge] is 1, this - is overridden by the merge code, but we have historically used - [Caml_white]. -*/ -void (*caml_fl_p_make_free_blocks) - (value *p, mlsize_t size, int do_merge, int color) - = &nf_make_free_blocks; -#ifdef DEBUG -void (*caml_fl_p_check) (void) = &nf_check; -#endif - -void caml_set_allocation_policy (intnat p) -{ - switch (p){ - case policy_next_fit: default: - caml_allocation_policy = policy_next_fit; - caml_fl_p_allocate = &nf_allocate; - caml_fl_p_init_merge = &nf_init_merge; - caml_fl_p_reset = &nf_reset; - caml_fl_p_init = &nf_init; - caml_fl_p_merge_block = &nf_merge_block; - caml_fl_p_add_blocks = &nf_add_blocks; - caml_fl_p_make_free_blocks = &nf_make_free_blocks; -#ifdef DEBUG - caml_fl_p_check = &nf_check; -#endif - break; - case policy_first_fit: - caml_allocation_policy = policy_first_fit; - caml_fl_p_allocate = &ff_allocate; - caml_fl_p_init_merge = &ff_init_merge; - caml_fl_p_reset = &ff_reset; - caml_fl_p_init = &ff_init; - caml_fl_p_merge_block = &ff_merge_block; - caml_fl_p_add_blocks = &ff_add_blocks; - caml_fl_p_make_free_blocks = &ff_make_free_blocks; -#ifdef DEBUG - caml_fl_p_check = &ff_check; -#endif - break; - case policy_best_fit: - caml_allocation_policy = policy_best_fit; - caml_fl_p_allocate = &bf_allocate; - caml_fl_p_init_merge = &bf_init_merge; - caml_fl_p_reset = &bf_reset; - caml_fl_p_init = &bf_init; - caml_fl_p_merge_block = &bf_merge_block; - caml_fl_p_add_blocks = &bf_add_blocks; - caml_fl_p_make_free_blocks = &bf_make_free_blocks; -#ifdef DEBUG - caml_fl_p_check = &bf_check; -#endif - break; - } -} - -/* This is called by caml_compact_heap. */ -void caml_fl_reset_and_switch_policy (intnat new_allocation_policy) -{ - /* reset the fl data structures */ - (*caml_fl_p_reset) (); - if (new_allocation_policy != -1){ - caml_set_allocation_policy (new_allocation_policy); - (*caml_fl_p_init) (); /* initialize the new allocation policy */ - } -} diff --git a/runtime/gc_ctrl.c b/runtime/gc_ctrl.c index a200b20382..c878a6477a 100644 --- a/runtime/gc_ctrl.c +++ b/runtime/gc_ctrl.c @@ -13,34 +13,35 @@ /* */ /**************************************************************************/ + #define CAML_INTERNALS #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/shared_heap.h" #include "caml/misc.h" #include "caml/mlvalues.h" -#include "caml/signals.h" -#include "caml/eventlog.h" #ifdef NATIVE_CODE #include "caml/stack.h" +#include "frame_descriptors.h" #else -#include "caml/stacks.h" +#include "caml/fiber.h" #endif -#include "caml/startup_aux.h" +#include "caml/domain.h" +#include "caml/globroots.h" +#include "caml/signals.h" +#include "caml/startup.h" +#include "caml/domain.h" +#include "caml/eventlog.h" +#include "caml/fail.h" -#ifndef NATIVE_CODE -extern uintnat caml_max_stack_size; /* defined in stacks.c */ -#endif +uintnat caml_max_stack_size; +uintnat caml_fiber_wsz; extern uintnat caml_major_heap_increment; /* percent or words; see major_gc.c */ extern uintnat caml_percent_free; /* see major_gc.c */ @@ -50,278 +51,47 @@ extern uintnat caml_custom_major_ratio; /* see custom.c */ extern uintnat caml_custom_minor_ratio; /* see custom.c */ extern uintnat caml_custom_minor_max_bsz; /* see custom.c */ -#define Next(hp) ((header_t *)(hp) + Whsize_hp (hp)) - -#ifdef DEBUG - -/* Check that [v]'s header looks good. [v] must be a block in the heap. */ -static void check_head (value v) -{ - CAMLassert (Is_block (v)); - CAMLassert (Is_in_heap (v)); - - CAMLassert (Wosize_val (v) != 0); - CAMLassert (Color_hd (Hd_val (v)) != Caml_blue); - CAMLassert (Is_in_heap (v)); - if (Tag_val (v) == Infix_tag){ - int offset = Wsize_bsize (Infix_offset_val (v)); - value trueval = Val_op (&Field (v, -offset)); - CAMLassert (Tag_val (trueval) == Closure_tag); - CAMLassert (Wosize_val (trueval) > offset); - CAMLassert (Is_in_heap (&Field (trueval, Wosize_val (trueval) - 1))); - }else{ - CAMLassert (Is_in_heap (&Field (v, Wosize_val (v) - 1))); - } - if (Tag_val (v) == Double_tag){ - CAMLassert (Wosize_val (v) == Double_wosize); - }else if (Tag_val (v) == Double_array_tag){ - CAMLassert (Wosize_val (v) % Double_wosize == 0); - } -} - -static void check_block (header_t *hp) -{ - mlsize_t i; - value v = Val_hp (hp); - value f; - - check_head (v); - switch (Tag_hp (hp)){ - case Abstract_tag: break; - case String_tag: - break; - case Double_tag: - CAMLassert (Wosize_val (v) == Double_wosize); - break; - case Double_array_tag: - CAMLassert (Wosize_val (v) % Double_wosize == 0); - break; - case Custom_tag: - CAMLassert (!Is_in_heap (Custom_ops_val (v))); - break; - - case Infix_tag: - CAMLassert (0); - break; - - default: - CAMLassert (Tag_hp (hp) < No_scan_tag); - for (i = 0; i < Wosize_hp (hp); i++){ - f = Field (v, i); - if (Is_block (f) && Is_in_heap (f)){ - check_head (f); - CAMLassert (Color_val (f) != Caml_blue); - } - } - } -} - -#endif /* DEBUG */ - -/* Check the heap structure (if compiled in debug mode) and - gather statistics; return the stats if [returnstats] is true, - otherwise return [Val_unit]. -*/ -static value heap_stats (int returnstats) -{ - CAMLparam0 (); - intnat live_words = 0, live_blocks = 0, - free_words = 0, free_blocks = 0, largest_free = 0, - fragments = 0, heap_chunks = 0; - char *chunk = caml_heap_start, *chunk_end; - header_t *cur_hp; -#ifdef DEBUG - header_t *prev_hp; -#endif - header_t cur_hd; - -#ifdef DEBUG - caml_gc_message (-1, "### OCaml runtime: heap check ###\n"); -#endif - - while (chunk != NULL){ - ++ heap_chunks; - chunk_end = chunk + Chunk_size (chunk); -#ifdef DEBUG - prev_hp = NULL; -#endif - cur_hp = (header_t *) chunk; - while (cur_hp < (header_t *) chunk_end){ - cur_hd = Hd_hp (cur_hp); - CAMLassert (Next (cur_hp) <= (header_t *) chunk_end); - switch (Color_hd (cur_hd)){ - case Caml_white: - if (Wosize_hd (cur_hd) == 0){ - ++ fragments; - CAMLassert (prev_hp == NULL - || Color_hp (prev_hp) != Caml_blue - || cur_hp == (header_t *) caml_gc_sweep_hp); - }else{ - if (caml_gc_phase == Phase_sweep - && cur_hp >= (header_t *) caml_gc_sweep_hp){ - ++ free_blocks; - free_words += Whsize_hd (cur_hd); - if (Whsize_hd (cur_hd) > largest_free){ - largest_free = Whsize_hd (cur_hd); - } - }else{ - ++ live_blocks; - live_words += Whsize_hd (cur_hd); -#ifdef DEBUG - check_block (cur_hp); -#endif - } - } - break; - case Caml_gray: case Caml_black: - CAMLassert (Wosize_hd (cur_hd) > 0); - ++ live_blocks; - live_words += Whsize_hd (cur_hd); -#ifdef DEBUG - check_block (cur_hp); -#endif - break; - case Caml_blue: - CAMLassert (Wosize_hd (cur_hd) > 0); - ++ free_blocks; - free_words += Whsize_hd (cur_hd); - if (Whsize_hd (cur_hd) > largest_free){ - largest_free = Whsize_hd (cur_hd); - } - /* not true any more with big heap chunks - CAMLassert (prev_hp == NULL - || (Color_hp (prev_hp) != Caml_blue - && Wosize_hp (prev_hp) > 0) - || cur_hp == caml_gc_sweep_hp); - CAMLassert (Next (cur_hp) == chunk_end - || (Color_hp (Next (cur_hp)) != Caml_blue - && Wosize_hp (Next (cur_hp)) > 0) - || (Whsize_hd (cur_hd) + Wosize_hp (Next (cur_hp)) - > Max_wosize) - || Next (cur_hp) == caml_gc_sweep_hp); - */ - break; - } -#ifdef DEBUG - prev_hp = cur_hp; -#endif - cur_hp = Next (cur_hp); - } - CAMLassert (cur_hp == (header_t *) chunk_end); - chunk = Chunk_next (chunk); - } - -#ifdef DEBUG - caml_final_invariant_check(); - caml_fl_check (); -#endif - - CAMLassert (heap_chunks == Caml_state->stat_heap_chunks); - CAMLassert (live_words + free_words + fragments == Caml_state->stat_heap_wsz); - - if (returnstats){ - CAMLlocal1 (res); - - /* get a copy of these before allocating anything... */ - double minwords = - Caml_state->stat_minor_words - + (double) (Caml_state->young_alloc_end - Caml_state->young_ptr); - double prowords = Caml_state->stat_promoted_words; - double majwords = - Caml_state->stat_major_words + (double) caml_allocated_words; - intnat mincoll = Caml_state->stat_minor_collections; - intnat majcoll = Caml_state->stat_major_collections; - intnat heap_words = Caml_state->stat_heap_wsz; - intnat cpct = Caml_state->stat_compactions; - intnat forcmajcoll = Caml_state->stat_forced_major_collections; - intnat top_heap_words = Caml_state->stat_top_heap_wsz; - - res = caml_alloc_tuple (17); - Store_field (res, 0, caml_copy_double (minwords)); - Store_field (res, 1, caml_copy_double (prowords)); - Store_field (res, 2, caml_copy_double (majwords)); - Store_field (res, 3, Val_long (mincoll)); - Store_field (res, 4, Val_long (majcoll)); - Store_field (res, 5, Val_long (heap_words)); - Store_field (res, 6, Val_long (heap_chunks)); - Store_field (res, 7, Val_long (live_words)); - Store_field (res, 8, Val_long (live_blocks)); - Store_field (res, 9, Val_long (free_words)); - Store_field (res, 10, Val_long (free_blocks)); - Store_field (res, 11, Val_long (largest_free)); - Store_field (res, 12, Val_long (fragments)); - Store_field (res, 13, Val_long (cpct)); - Store_field (res, 14, Val_long (top_heap_words)); - Store_field (res, 15, Val_long (caml_stack_usage())); - Store_field (res, 16, Val_long (forcmajcoll)); - CAMLreturn (res); - }else{ - CAMLreturn (Val_unit); - } -} - -#ifdef DEBUG -void caml_heap_check (void) -{ - heap_stats (0); -} -#endif - -CAMLprim value caml_gc_stat(value v) -{ - value result; - CAML_EV_BEGIN(EV_EXPLICIT_GC_STAT); - CAMLassert (v == Val_unit); - result = heap_stats (1); - CAML_EV_END(EV_EXPLICIT_GC_STAT); - return result; -} - CAMLprim value caml_gc_quick_stat(value v) { CAMLparam0 (); CAMLlocal1 (res); /* get a copy of these before allocating anything... */ - double minwords = - Caml_state->stat_minor_words - + (double) (Caml_state->young_alloc_end - Caml_state->young_ptr); - double prowords = Caml_state->stat_promoted_words; - double majwords = - Caml_state->stat_major_words + (double) caml_allocated_words; - intnat mincoll = Caml_state->stat_minor_collections; - intnat majcoll = Caml_state->stat_major_collections; - intnat heap_words = Caml_state->stat_heap_wsz; - intnat top_heap_words = Caml_state->stat_top_heap_wsz; - intnat cpct = Caml_state->stat_compactions; - intnat forcmajcoll = Caml_state->stat_forced_major_collections; - intnat heap_chunks = Caml_state->stat_heap_chunks; + intnat majcoll; + struct gc_stats s; + caml_sample_gc_stats(&s); + majcoll = Caml_state->stat_major_collections; res = caml_alloc_tuple (17); - Store_field (res, 0, caml_copy_double (minwords)); - Store_field (res, 1, caml_copy_double (prowords)); - Store_field (res, 2, caml_copy_double (majwords)); - Store_field (res, 3, Val_long (mincoll)); + Store_field (res, 0, caml_copy_double ((double)s.minor_words)); + Store_field (res, 1, caml_copy_double ((double)s.promoted_words)); + Store_field (res, 2, caml_copy_double ((double)s.major_words)); + Store_field (res, 3, Val_long (s.minor_collections)); Store_field (res, 4, Val_long (majcoll)); - Store_field (res, 5, Val_long (heap_words)); - Store_field (res, 6, Val_long (heap_chunks)); - Store_field (res, 7, Val_long (0)); - Store_field (res, 8, Val_long (0)); - Store_field (res, 9, Val_long (0)); + Store_field (res, 5, Val_long ( + s.major_heap.pool_words + s.major_heap.large_words)); + Store_field (res, 6, Val_long (0)); + Store_field (res, 7, Val_long ( + s.major_heap.pool_live_words + s.major_heap.large_words)); + Store_field (res, 8, Val_long ( + s.major_heap.pool_live_blocks + s.major_heap.large_blocks)); + Store_field (res, 9, Val_long ( + s.major_heap.pool_words - s.major_heap.pool_live_words - s.major_heap.pool_frag_words)); Store_field (res, 10, Val_long (0)); Store_field (res, 11, Val_long (0)); - Store_field (res, 12, Val_long (0)); - Store_field (res, 13, Val_long (cpct)); - Store_field (res, 14, Val_long (top_heap_words)); - Store_field (res, 15, Val_long (caml_stack_usage())); - Store_field (res, 16, Val_long (forcmajcoll)); + Store_field (res, 12, Val_long (s.major_heap.pool_frag_words)); + Store_field (res, 13, Val_long (0)); + Store_field (res, 14, Val_long ( + s.major_heap.pool_max_words + s.major_heap.large_max_words)); + Store_field (res, 15, Val_long (0)); + Store_field (res, 16, Val_long (s.forced_major_collections)); CAMLreturn (res); } double caml_gc_minor_words_unboxed() { return (Caml_state->stat_minor_words - + (double) (Caml_state->young_alloc_end - Caml_state->young_ptr)); + + ((double) (Caml_state->young_end - Caml_state->young_ptr)) / sizeof(value)); } CAMLprim value caml_gc_minor_words(value v) @@ -336,46 +106,38 @@ CAMLprim value caml_gc_counters(value v) CAMLlocal1 (res); /* get a copy of these before allocating anything... */ - double minwords = - Caml_state->stat_minor_words - + (double) (Caml_state->young_alloc_end - Caml_state->young_ptr); + double minwords = Caml_state->stat_minor_words + + ((double) Wsize_bsize (Caml_state->young_end - + Caml_state->young_ptr)) / sizeof(value); double prowords = Caml_state->stat_promoted_words; - double majwords = - Caml_state->stat_major_words + (double) caml_allocated_words; + double majwords = Caml_state->stat_major_words + (double) Caml_state->allocated_words; - res = caml_alloc_tuple (3); - Store_field (res, 0, caml_copy_double (minwords)); - Store_field (res, 1, caml_copy_double (prowords)); - Store_field (res, 2, caml_copy_double (majwords)); + res = caml_alloc_3(0, + caml_copy_double (minwords), + caml_copy_double (prowords), + caml_copy_double (majwords)); 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 (11); - Store_field (res, 0, Val_long (Caml_state->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 */ - Store_field (res, 3, Val_long (caml_verb_gc)); /* v */ - Store_field (res, 4, Val_long (caml_percent_max)); /* O */ + Store_field (res, 0, Val_long (Caml_state->minor_heap_wsz)); /* s */ + Store_field (res, 2, Val_long (caml_percent_free)); /* o */ + Store_field (res, 3, Val_long (caml_params->verb_gc)); /* v */ #ifndef NATIVE_CODE - Store_field (res, 5, Val_long (caml_max_stack_size)); /* l */ + Store_field (res, 5, Val_long (caml_max_stack_size)); /* l */ #else 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 */ - Store_field (res, 8, Val_long (caml_custom_major_ratio)); /* M */ - Store_field (res, 9, Val_long (caml_custom_minor_ratio)); /* m */ - Store_field (res, 10, Val_long (caml_custom_minor_max_bsz)); /* n */ + Store_field (res, 8, Val_long (caml_custom_major_ratio)); /* M */ + Store_field (res, 9, Val_long (caml_custom_minor_ratio)); /* m */ + Store_field (res, 10, Val_long (caml_custom_minor_max_bsz)); /* n */ + CAMLreturn (res); + CAMLreturn (res); } @@ -386,29 +148,10 @@ static uintnat norm_pfree (uintnat p) return Max (p, 1); } -static uintnat norm_pmax (uintnat p) +/*static uintnat norm_pmax (uintnat p) { return p; -} - -static intnat norm_minsize (intnat s) -{ - intnat page_wsize = Wsize_bsize(Page_size); - if (s < Minor_heap_min) s = Minor_heap_min; - if (s > Minor_heap_max) s = Minor_heap_max; - /* PR#9128 : Make sure the minor heap occupies an integral number of - pages, so that no page contains both bytecode and OCaml - values. This would confuse, e.g., caml_hash. */ - s = (s + page_wsize - 1) / page_wsize * page_wsize; - return s; -} - -static uintnat norm_window (intnat w) -{ - if (w < 1) w = 1; - if (w > Max_major_window) w = Max_major_window; - return w; -} +}*/ static uintnat norm_custom_maj (uintnat p) { @@ -422,55 +165,29 @@ static uintnat norm_custom_min (uintnat p) CAMLprim value caml_gc_set(value v) { - uintnat newpf, newpm; - asize_t newheapincr; - asize_t newminwsz; - uintnat newpolicy; + uintnat newpf; + uintnat newminwsz; uintnat new_custom_maj, new_custom_min, new_custom_sz; CAML_EV_BEGIN(EV_EXPLICIT_GC_SET); - caml_verb_gc = Long_val (Field (v, 3)); - #ifndef NATIVE_CODE - caml_change_max_stack_size (Long_val (Field (v, 5))); + caml_change_max_stack_size (Long_field (v, 5)); #endif - newpf = norm_pfree (Long_val (Field (v, 2))); + newpf = norm_pfree (Long_field (v, 2)); if (newpf != caml_percent_free){ caml_percent_free = newpf; caml_gc_message (0x20, "New space overhead: %" ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_free); } - newpm = norm_pmax (Long_val (Field (v, 4))); - if (newpm != caml_percent_max){ - caml_percent_max = newpm; - caml_gc_message (0x20, "New max overhead: %" - ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_max); - } - - newheapincr = Long_val (Field (v, 1)); - if (newheapincr != caml_major_heap_increment){ - caml_major_heap_increment = newheapincr; - if (newheapincr > 1000){ - caml_gc_message (0x20, "New heap increment size: %" - ARCH_INTNAT_PRINTF_FORMAT "uk words\n", - caml_major_heap_increment/1024); - }else{ - caml_gc_message (0x20, "New heap increment size: %" - ARCH_INTNAT_PRINTF_FORMAT "u%%\n", - caml_major_heap_increment); - } - } - - /* 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 = caml_norm_minor_heap_size (Long_field (v, 0)); + if (newminwsz != Caml_state->minor_heap_wsz){ + caml_gc_message (0x20, "New minor heap size: %" + ARCH_SIZET_PRINTF_FORMAT "uk words\n", newminwsz / 1024); + caml_set_minor_heap_size (newminwsz); } /* These fields were added in 4.08.0. */ @@ -497,106 +214,47 @@ CAMLprim value caml_gc_set(value v) caml_custom_minor_max_bsz); } } - - /* Save field 0 before [v] is invalidated. */ - newminwsz = norm_minsize (Long_val (Field (v, 0))); - - /* Switching allocation policies must trigger a compaction, so it - invalidates [v]. */ - newpolicy = Long_val (Field (v, 6)); - if (newpolicy != caml_allocation_policy){ - caml_empty_minor_heap (); - caml_finish_major_cycle (); - caml_finish_major_cycle (); - ++ Caml_state->stat_forced_major_collections; - caml_compact_heap (newpolicy); - caml_gc_message (0x20, "New allocation policy: %" - ARCH_INTNAT_PRINTF_FORMAT "u\n", newpolicy); - } - - /* Minor heap size comes last because it can raise [Out_of_memory]. */ - if (newminwsz != Caml_state->minor_heap_wsz){ - caml_gc_message (0x20, "New minor heap size: %" - ARCH_SIZET_PRINTF_FORMAT "uk words\n", newminwsz / 1024); - caml_set_minor_heap_size (Bsize_wsize (newminwsz)); - } CAML_EV_END(EV_EXPLICIT_GC_SET); - /* The compaction may have triggered some finalizers that we need to call. */ - caml_process_pending_actions(); - return Val_unit; } CAMLprim value caml_gc_minor(value v) { - value exn; - CAML_EV_BEGIN(EV_EXPLICIT_GC_MINOR); CAMLassert (v == Val_unit); - caml_request_minor_gc (); - // call the gc and call finalisers - exn = caml_process_pending_actions_exn(); + caml_minor_collection (); CAML_EV_END(EV_EXPLICIT_GC_MINOR); - caml_raise_if_exception(exn); return Val_unit; } -static void test_and_compact (void) -{ - double fp; - - fp = 100.0 * caml_fl_cur_wsz / (Caml_state->stat_heap_wsz - caml_fl_cur_wsz); - if (fp > 999999.0) fp = 999999.0; - caml_gc_message (0x200, "Estimated overhead (lower bound) = %" - ARCH_INTNAT_PRINTF_FORMAT "u%%\n", - (uintnat) fp); - if (fp >= caml_percent_max){ - caml_gc_message (0x200, "Automatic compaction triggered.\n"); - caml_compact_heap (-1); - } -} - CAMLprim value caml_gc_major(value v) { - value exn; - CAML_EV_BEGIN(EV_EXPLICIT_GC_MAJOR); CAMLassert (v == Val_unit); - caml_gc_message (0x1, "Major GC cycle requested\n"); - caml_empty_minor_heap (); - caml_finish_major_cycle (); - test_and_compact (); - // call finalisers - exn = caml_process_pending_actions_exn(); + caml_gc_log ("Major GC cycle requested"); + caml_empty_minor_heaps_once(); + caml_finish_major_cycle(); + caml_final_do_calls (); CAML_EV_END(EV_EXPLICIT_GC_MAJOR); - caml_raise_if_exception(exn); return Val_unit; } CAMLprim value caml_gc_full_major(value v) { - value exn; - + int i; CAML_EV_BEGIN(EV_EXPLICIT_GC_FULL_MAJOR); CAMLassert (v == Val_unit); - caml_gc_message (0x1, "Full major GC cycle requested\n"); - caml_empty_minor_heap (); - caml_finish_major_cycle (); - // call finalisers - exn = caml_process_pending_actions_exn(); - if (Is_exception_result(exn)) goto cleanup; - caml_empty_minor_heap (); - caml_finish_major_cycle (); + caml_gc_log ("Full Major GC requested"); + /* In general, it can require up to 3 GC cycles for a + currently-unreachable object to be collected. */ + for (i = 0; i < 3; i++) { + caml_empty_minor_heaps_once(); + caml_finish_major_cycle(); + caml_final_do_calls (); + } ++ Caml_state->stat_forced_major_collections; - test_and_compact (); - // call finalisers - exn = caml_process_pending_actions_exn(); - -cleanup: CAML_EV_END(EV_EXPLICIT_GC_FULL_MAJOR); - caml_raise_if_exception(exn); - return Val_unit; } @@ -604,92 +262,65 @@ CAMLprim value caml_gc_major_slice (value v) { CAML_EV_BEGIN(EV_EXPLICIT_GC_MAJOR_SLICE); CAMLassert (Is_long (v)); - caml_major_collection_slice (Long_val (v)); + caml_major_collection_slice(Long_val(v)); CAML_EV_END(EV_EXPLICIT_GC_MAJOR_SLICE); return Val_long (0); } CAMLprim value caml_gc_compaction(value v) { - value exn; - CAML_EV_BEGIN(EV_EXPLICIT_GC_COMPACT); CAMLassert (v == Val_unit); - caml_gc_message (0x10, "Heap compaction requested\n"); - caml_empty_minor_heap (); - caml_finish_major_cycle (); - // call finalisers - exn = caml_process_pending_actions_exn(); - if (Is_exception_result(exn)) goto cleanup; - caml_empty_minor_heap (); - caml_finish_major_cycle (); + caml_gc_major(v); ++ Caml_state->stat_forced_major_collections; - caml_compact_heap (-1); - // call finalisers - exn = caml_process_pending_actions_exn(); - - cleanup: CAML_EV_END(EV_EXPLICIT_GC_COMPACT); - caml_raise_if_exception(exn); return Val_unit; } -CAMLprim value caml_get_minor_free (value v) -{ - return Val_int (Caml_state->young_ptr - Caml_state->young_alloc_start); -} -CAMLprim value caml_get_major_bucket (value v) +CAMLprim value caml_gc_stat(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); - } + value result; + CAML_EV_BEGIN(EV_EXPLICIT_GC_STAT); + caml_gc_full_major(Val_unit); + result = caml_gc_quick_stat(Val_unit); + CAML_EV_END(EV_EXPLICIT_GC_STAT); + return result; } -CAMLprim value caml_get_major_credit (value v) +CAMLprim value caml_get_minor_free (value v) { - CAMLassert (v == Val_unit); - return Val_long ((long) (caml_major_work_credit * 1e6)); + return Val_int (Caml_state->young_ptr - Caml_state->young_start); } -/* [minor_size] and [major_size] are numbers of words - [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 window, - uintnat custom_maj, uintnat custom_min, - uintnat custom_bsz) +void caml_init_gc () { - uintnat major_bsize; - if (major_size < Heap_chunk_min) major_size = Heap_chunk_min; - major_bsize = Bsize_wsize(major_size); - major_bsize = ((major_bsize + Page_size - 1) >> Page_log) << Page_log; + caml_max_stack_size = caml_params->init_max_stack_wsz; + caml_fiber_wsz = caml_params->init_fiber_wsz; + caml_percent_free = norm_pfree (caml_params->init_percent_free); + caml_gc_log ("Initial stack limit: %luk bytes", + caml_max_stack_size / 1024 * sizeof (value)); - if (caml_page_table_initialize(Bsize_wsize(minor_size) + major_bsize)){ - caml_fatal_error ("cannot initialize page table"); - } - caml_set_minor_heap_size (Bsize_wsize (norm_minsize (minor_size))); + caml_custom_major_ratio = + norm_custom_maj (caml_params->init_custom_major_ratio); + caml_custom_minor_ratio = + norm_custom_min (caml_params->init_custom_minor_ratio); + caml_custom_minor_max_bsz = caml_params->init_custom_minor_max_bsz; + + caml_gc_phase = Phase_sweep_and_mark_main; + #ifdef NATIVE_CODE + caml_init_frame_descriptors(); + #endif + caml_init_domains(caml_params->init_minor_heap_wsz); +/* caml_major_heap_increment = major_incr; caml_percent_free = norm_pfree (percent_fr); caml_percent_max = norm_pmax (percent_m); - caml_init_major_heap (major_bsize); - caml_major_window = norm_window (window); - caml_custom_major_ratio = norm_custom_maj (custom_maj); - caml_custom_minor_ratio = norm_custom_min (custom_min); - caml_custom_minor_max_bsz = custom_bsz; - caml_gc_message (0x20, "Initial minor heap size: %" - ARCH_SIZET_PRINTF_FORMAT "uk words\n", - Caml_state->minor_heap_wsz / 1024); - caml_gc_message (0x20, "Initial major heap size: %" - ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n", - major_bsize / 1024); + caml_init_major_heap (major_heap_size); + caml_gc_message (0x20, "Initial minor heap size: %luk bytes\n", + Caml_state->minor_heap_size / 1024); + caml_gc_message (0x20, "Initial major heap size: %luk bytes\n", + major_heap_size / 1024); caml_gc_message (0x20, "Initial space overhead: %" ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_percent_free); caml_gc_message (0x20, "Initial max overhead: %" @@ -703,13 +334,11 @@ void caml_init_gc (uintnat minor_size, uintnat major_size, ARCH_INTNAT_PRINTF_FORMAT "u%%\n", caml_major_heap_increment); } - caml_gc_message (0x20, "Initial allocation policy: %" - ARCH_INTNAT_PRINTF_FORMAT "u\n", caml_allocation_policy); - caml_gc_message (0x20, "Initial smoothing window: %d\n", - caml_major_window); + caml_gc_message (0x20, "Initial allocation policy: %d\n", + caml_allocation_policy); +*/ } - /* FIXME After the startup_aux.c unification, move these functions there. */ CAMLprim value caml_runtime_variant (value unit) @@ -732,31 +361,8 @@ CAMLprim value caml_runtime_parameters (value unit) #define F_S ARCH_SIZET_PRINTF_FORMAT CAMLassert (unit == Val_unit); - return caml_alloc_sprintf - ("a=%d,b=%d,H=%"F_Z"u,i=%"F_Z"u,l=%"F_Z"u,o=%"F_Z"u,O=%"F_Z"u,p=%d," - "s=%"F_S"u,t=%"F_Z"u,v=%"F_Z"u,w=%d,W=%"F_Z"u", - /* a */ (int) caml_allocation_policy, - /* b */ (int) Caml_state->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 */ (uintnat) 0, -#else - /* l */ caml_max_stack_size, -#endif - /* o */ caml_percent_free, - /* O */ caml_percent_max, - /* p */ caml_parser_trace, - /* R */ /* missing */ - /* s */ Caml_state->minor_heap_wsz, - /* t */ caml_trace_level, - /* v */ caml_verb_gc, - /* w */ caml_major_window, - /* W */ caml_runtime_warnings - ); -#undef F_Z -#undef F_S + /* TODO KC */ + return caml_alloc_sprintf ("caml_runtime_parameters not implemented: %d", 0); } /* Control runtime warnings */ diff --git a/runtime/gen_primitives.sh b/runtime/gen_primitives.sh index 8816ccb417..4ed7c9c86e 100755 --- a/runtime/gen_primitives.sh +++ b/runtime/gen_primitives.sh @@ -23,9 +23,9 @@ export LC_ALL=C ( for prim in \ alloc array compare extern floats gc_ctrl hash intern interp ints io \ - lexing md5 meta memprof obj parsing signals str sys callback weak \ - finalise stacks dynlink backtrace_byt backtrace spacetime_byt afl \ - bigarray eventlog + lexing md5 meta obj parsing signals str sys callback weak finalise \ + domain platform eventlog fiber memory startup_aux \ + dynlink backtrace_byt backtrace spacetime_byt afl bigarray do sed -n -e 's/^CAMLprim value \([a-z0-9_][a-z0-9_]*\).*/\1/p' "$prim.c" done diff --git a/runtime/gen_sizeclasses.ml b/runtime/gen_sizeclasses.ml new file mode 100644 index 0000000000..2cffb252ef --- /dev/null +++ b/runtime/gen_sizeclasses.ml @@ -0,0 +1,58 @@ +let overhead block slot obj = 1. -. float_of_int((block / slot) * obj) /. float_of_int block + +let max_overhead = 0.10 + +let rec blocksizes block slot = function + | 0 -> [] + | obj -> + if overhead block slot obj > max_overhead + then + if overhead block obj obj < max_overhead then + obj :: blocksizes block obj (obj - 1) + else + failwith (Format.sprintf "%d-word objects cannot fit in %d-word arena below %.1f%% overhead" + obj block (100. *. max_overhead)) + else blocksizes block slot (obj - 1) + +let rec findi_acc i p = function + | [] -> raise Not_found + | x :: xs -> if p x then i else findi_acc (i + 1) p xs +let findi = findi_acc 0 + +let arena = 4096 +let header_size = 4 +let max_slot = 128 +let avail_arena = arena - header_size +let sizes = List.rev (blocksizes avail_arena max_int max_slot) + +let rec size_slots n = + if n > max_slot then [] else findi (fun x -> n <= x) sizes :: size_slots (n + 1) + +let rec wastage = + sizes |> List.map (fun s -> avail_arena mod s) + +open Format + +let rec print_overheads n = function + | [] -> () + | s :: ss when n > s -> print_overheads n ss + | (s :: _) as ss -> + printf "%3d/%-3d: %.1f%%\n" n s (100. *. overhead avail_arena s n); + print_overheads (n+1) ss + +(* let () = print_overheads 1 sizes *) + +let rec print_list ppf = function + | [] -> () + | [x] -> fprintf ppf "%d" x + | x :: xs -> fprintf ppf "%d,@ %a" x print_list xs + +let _ = + printf "#define POOL_WSIZE %d\n" arena; + printf "#define POOL_HEADER_WSIZE %d\n" header_size; + printf "#define SIZECLASS_MAX %d\n" max_slot; + printf "#define NUM_SIZECLASSES %d\n" (List.length sizes); + printf "static const unsigned int wsize_sizeclass[NUM_SIZECLASSES] = @[<2>{ %a };@]\n" print_list sizes; + printf "static const unsigned char wastage_sizeclass[NUM_SIZECLASSES] = @[<2>{ %a };@]\n" print_list wastage; + printf "static const unsigned char sizeclass_wsize[SIZECLASS_MAX + 1] = @[<2>{ %a };@]\n" print_list (255 :: size_slots 1); + diff --git a/runtime/globroots.c b/runtime/globroots.c index 3025d09559..70141e6e68 100644 --- a/runtime/globroots.c +++ b/runtime/globroots.c @@ -21,6 +21,60 @@ #include "caml/roots.h" #include "caml/globroots.h" #include "caml/skiplist.h" +#include "caml/stack.h" + +static caml_plat_mutex roots_mutex = CAML_PLAT_MUTEX_INITIALIZER; + +/* legacy multicore API that we need to fix */ +CAMLexport caml_root caml_create_root(value init) +{ + CAMLparam1(init); + + value* v = (value*)caml_stat_alloc(sizeof(value)); + + *v = init; + + caml_register_global_root(v); + + CAMLreturnT(caml_root, (caml_root)v); +} + +CAMLexport caml_root caml_create_root_noexc(value init) +{ + CAMLparam1(init); + + value* v = (value*)caml_stat_alloc_noexc(sizeof(value)); + + if( v == NULL ) { + CAMLdrop; + return NULL; + } + + *v = init; + + caml_register_global_root(v); + + CAMLreturnT(caml_root, (caml_root)v); +} + +CAMLexport void caml_delete_root(caml_root root) +{ + value* v = (value*)root; + Assert(root); + /* the root will be removed from roots_all and freed at the next GC */ + caml_remove_global_root(v); + caml_stat_free(v); +} + +CAMLexport value caml_read_root(caml_root root) +{ + return *((value*)root); +} + +CAMLexport void caml_modify_root(caml_root root, value newv) +{ + *((value*)root) = newv; +} /* The three global root lists. Each is represented by a skip list with the key being the address @@ -40,30 +94,35 @@ struct skiplist caml_global_roots_old = SKIPLIST_STATIC_INITIALIZER; in [caml_global_roots_old] or in [caml_global_roots_young]; - Otherwise (the root contains a pointer outside of the heap or an integer), then neither [caml_global_roots_young] nor [caml_global_roots_old] contain - it. -*/ + it. */ /* Insertion and deletion */ Caml_inline void caml_insert_global_root(struct skiplist * list, value * r) { + caml_plat_lock(&roots_mutex); caml_skiplist_insert(list, (uintnat) r, 0); + caml_plat_unlock(&roots_mutex); } Caml_inline void caml_delete_global_root(struct skiplist * list, value * r) { + caml_plat_lock(&roots_mutex); caml_skiplist_remove(list, (uintnat) r); + caml_plat_unlock(&roots_mutex); } /* Iterate a GC scanning action over a global root list */ static void caml_iterate_global_roots(scanning_action f, - struct skiplist * rootlist) + struct skiplist * rootlist, void* fdata) { + caml_plat_lock(&roots_mutex); FOREACH_SKIPLIST_ELEMENT(e, rootlist, { value * r = (value *) (e->key); - f(*r, r); + f(fdata, *r, r); }) + caml_plat_unlock(&roots_mutex); } /* Register a global C root of the mutable kind */ @@ -91,9 +150,6 @@ static enum gc_root_class classify_gc_root(value v) { if(!Is_block(v)) return UNTRACKED; if(Is_young(v)) return YOUNG; -#ifndef NO_NAKED_POINTERS - if(!Is_in_heap(v)) return UNTRACKED; -#endif return OLD; } @@ -162,26 +218,92 @@ CAMLexport void caml_modify_generational_global_root(value *r, value newval) *r = newval; } -/* Scan all global roots */ +#ifdef NATIVE_CODE + +/* Linked-list of natdynlink'd globals */ + +typedef struct link { + void *data; + struct link *next; +} link; + +static link *cons(void *data, link *tl) { + link *lnk = caml_stat_alloc(sizeof(link)); + lnk->data = data; + lnk->next = tl; + return lnk; +} + +#define iter_list(list,lnk) \ + for (lnk = list; lnk != NULL; lnk = lnk->next) + + +/* protected by roots_mutex */ +static link * caml_dyn_globals = NULL; + +void caml_register_dyn_global(void *v) { + caml_plat_lock(&roots_mutex); + caml_dyn_globals = cons((void*) v,caml_dyn_globals); + caml_plat_unlock(&roots_mutex); +} -void caml_scan_global_roots(scanning_action f) +static void scan_native_globals(scanning_action f, void* fdata) { - caml_iterate_global_roots(f, &caml_global_roots); - caml_iterate_global_roots(f, &caml_global_roots_young); - caml_iterate_global_roots(f, &caml_global_roots_old); + int i, j; + static link* dyn_globals; + value* glob; + link* lnk; + + caml_plat_lock(&roots_mutex); + dyn_globals = caml_dyn_globals; + caml_plat_unlock(&roots_mutex); + + /* The global roots */ + for (i = 0; i <= caml_globals_inited && caml_globals[i] != 0; i++) { + for(glob = caml_globals[i]; *glob != 0; glob++) { + for (j = 0; j < Wosize_val(*glob); j++){ + f(fdata, Op_val(*glob)[j], &Op_val(*glob)[j]); + } + } + } + + /* Dynamic (natdynlink) global roots */ + iter_list(dyn_globals, lnk) { + for(glob = (value *) lnk->data; *glob != 0; glob++) { + for (j = 0; j < Wosize_val(*glob); j++){ + f(fdata, Op_val(*glob)[j], &Op_val(*glob)[j]); + } + } + } +} + +#endif + +/* Scan all global roots */ +void caml_scan_global_roots(scanning_action f, void* fdata) { + caml_iterate_global_roots(f, &caml_global_roots, fdata); + caml_iterate_global_roots(f, &caml_global_roots_young, fdata); + caml_iterate_global_roots(f, &caml_global_roots_old, fdata); + + #ifdef NATIVE_CODE + scan_native_globals(f, fdata); + #endif } /* Scan global roots for a minor collection */ -void caml_scan_global_young_roots(scanning_action f) +void caml_scan_global_young_roots(scanning_action f, void* fdata) { - - caml_iterate_global_roots(f, &caml_global_roots); - caml_iterate_global_roots(f, &caml_global_roots_young); + caml_iterate_global_roots(f, &caml_global_roots, fdata); + caml_iterate_global_roots(f, &caml_global_roots_young, fdata); /* Move young roots to old roots */ + + caml_plat_lock(&roots_mutex); FOREACH_SKIPLIST_ELEMENT(e, &caml_global_roots_young, { value * r = (value *) (e->key); - caml_insert_global_root(&caml_global_roots_old, r); + caml_skiplist_insert(&caml_global_roots_old, (uintnat) r, 0); }); + caml_plat_unlock(&roots_mutex); + caml_skiplist_empty(&caml_global_roots_young); } diff --git a/runtime/hash.c b/runtime/hash.c index f33634c227..dd901b6327 100644 --- a/runtime/hash.c +++ b/runtime/hash.c @@ -204,14 +204,7 @@ CAMLprim value caml_hash(value count, value limit, value seed, value obj) if (Is_long(v)) { h = caml_hash_mix_intnat(h, v); num--; - } - else if (!Is_in_value_area(v)) { - /* v is a pointer outside the heap, probably a code pointer. - Shall we count it? Let's say yes by compatibility with old code. */ - h = caml_hash_mix_intnat(h, v); - num--; - } - else { + } else { switch (Tag_val(v)) { case String_tag: h = caml_hash_mix_string(h, v); @@ -237,12 +230,26 @@ CAMLprim value caml_hash(value count, value limit, value seed, value obj) h = caml_hash_mix_uint32(h, Infix_offset_val(v)); v = v - Infix_offset_val(v); goto again; + case Closure_tag: + /* !! something complicated */ + #if 0 + /* v is a pointer outside the heap, probably a code pointer. + Shall we count it? Let's say yes by compatibility with old code. */ + h = caml_hash_mix_intnat(h, v); + num--; + #endif + h = 42; + break; + case Cont_tag: + /* All continuations hash to the same value, since we have no idea how to distinguish them. */ + h = 42; + break; case Forward_tag: /* PR#6361: we can have a loop here, so limit the number of Forward_tag links being followed */ for (i = MAX_FORWARD_DEREFERENCE; i > 0; i--) { v = Forward_val(v); - if (Is_long(v) || !Is_in_value_area(v) || Tag_val(v) != Forward_tag) + if (Is_long(v) || Tag_val(v) != Forward_tag) goto again; } /* Give up on this object and move to the next */ @@ -260,35 +267,13 @@ CAMLprim value caml_hash(value count, value limit, value seed, value obj) num--; } break; -#ifdef NO_NAKED_POINTERS - case Closure_tag: { - mlsize_t startenv; - len = Wosize_val(v); - startenv = Start_env_closinfo(Closinfo_val(v)); - CAMLassert (startenv <= len); - /* Mix in the tag and size, but do not count this towards [num] */ - h = caml_hash_mix_uint32(h, Whitehd_hd(Hd_val(v))); - /* Mix the code pointers, closure info fields, and infix headers */ - for (i = 0; i < startenv; i++) { - h = caml_hash_mix_intnat(h, Field(v, i)); - num--; - } - /* Copy environment fields into queue, - not exceeding the total size [sz] */ - for (/*nothing*/; i < len; i++) { - if (wr >= sz) break; - queue[wr++] = Field(v, i); - } - break; - } -#endif default: /* Mix in the tag and size, but do not count this towards [num] */ h = caml_hash_mix_uint32(h, Whitehd_hd(Hd_val(v))); /* Copy fields into queue, not exceeding the total size [sz] */ for (i = 0, len = Wosize_val(v); i < len; i++) { if (wr >= sz) break; - queue[wr++] = Field(v, i); + caml_read_field(v, i, &queue[wr++]); } break; } diff --git a/runtime/instrtrace.c b/runtime/instrtrace.c index 2760475ed5..cce6c93b71 100644 --- a/runtime/instrtrace.c +++ b/runtime/instrtrace.c @@ -23,27 +23,32 @@ #include <string.h> #include <ctype.h> +#include "caml/fiber.h" +#include "caml/domain.h" #include "caml/instrtrace.h" #include "caml/instruct.h" #include "caml/misc.h" #include "caml/mlvalues.h" #include "caml/opnames.h" #include "caml/prims.h" -#include "caml/stacks.h" -#include "caml/startup_aux.h" +#include "caml/startup.h" extern code_t caml_start_code; -intnat caml_icount = 0; +__thread intnat caml_icount = 0; void caml_stop_here () {} -void caml_disasm_instr(pc) - code_t pc; +char * caml_instr_string (code_t pc); + +void caml_disasm_instr(code_t pc) { + char buf[256]; + char opbuf[128]; int instr = *pc; - printf("%6ld %s", (long) (pc - caml_start_code), - instr < 0 || instr > STOP ? "???" : names_of_instructions[instr]); + snprintf(opbuf, sizeof(opbuf), "%6ld %s", (long) (pc - caml_start_code), + (instr < 0 || instr >= FIRST_UNIMPLEMENTED_OP) ? + "???" : names_of_instructions[instr]); pc++; switch(instr) { /* Instructions with one integer operand */ @@ -53,130 +58,42 @@ void caml_disasm_instr(pc) case GRAB: case PUSHGETGLOBAL: case GETGLOBAL: case SETGLOBAL: case PUSHATOM: case ATOM: case MAKEBLOCK1: case MAKEBLOCK2: case MAKEBLOCK3: case MAKEFLOATBLOCK: - case GETFIELD: case SETFIELD: case GETFLOATFIELD: case SETFLOATFIELD: + case GETFIELD: case GETMUTABLEFIELD: case SETFIELD: + case GETFLOATFIELD: case SETFLOATFIELD: case BRANCH: case BRANCHIF: case BRANCHIFNOT: case PUSHTRAP: case CONSTINT: case PUSHCONSTINT: case OFFSETINT: case OFFSETREF: case OFFSETCLOSURE: case PUSHOFFSETCLOSURE: - printf(" %d\n", pc[0]); break; + case RESUMETERM: case REPERFORMTERM: + snprintf(buf, sizeof(buf), "%s %d\n", opbuf, pc[0]); break; /* Instructions with two operands */ case APPTERM: case CLOSURE: case CLOSUREREC: case PUSHGETGLOBALFIELD: case GETGLOBALFIELD: case MAKEBLOCK: case BEQ: case BNEQ: case BLTINT: case BLEINT: case BGTINT: case BGEINT: case BULTINT: case BUGEINT: - printf(" %d, %d\n", pc[0], pc[1]); break; + snprintf(buf, sizeof(buf), "%s %d, %d\n", opbuf, pc[0], pc[1]); break; /* Instructions with a C primitive as operand */ case C_CALLN: - printf(" %d,", pc[0]); pc++; + snprintf(buf, sizeof(buf), "%s %d,", opbuf, pc[0]); pc++; /* fallthrough */ case C_CALL1: case C_CALL2: case C_CALL3: case C_CALL4: case C_CALL5: if (pc[0] < 0 || pc[0] >= caml_prim_name_table.size) - printf(" unknown primitive %d\n", pc[0]); + snprintf(buf, sizeof(buf), "%s unknown primitive %d\n", opbuf, pc[0]); else - printf(" %s\n", (char *) caml_prim_name_table.contents[pc[0]]); - break; - default: - printf("\n"); - } - fflush (stdout); -} - -char * caml_instr_string (code_t pc) -{ - static char buf[256]; - char nambuf[128]; - int instr = *pc; - char *nam; - - nam = (instr < 0 || instr > STOP) - ? (snprintf (nambuf, sizeof(nambuf), "???%d", instr), nambuf) - : names_of_instructions[instr]; - pc++; - switch (instr) { - /* Instructions with one integer operand */ - case PUSHACC: - case ACC: - case POP: - case ASSIGN: - case PUSHENVACC: - case ENVACC: - case PUSH_RETADDR: - case APPLY: - case APPTERM1: - case APPTERM2: - case APPTERM3: - case RETURN: - case GRAB: - case PUSHGETGLOBAL: - case GETGLOBAL: - case SETGLOBAL: - case PUSHATOM: - case ATOM: - case MAKEBLOCK1: - case MAKEBLOCK2: - case MAKEBLOCK3: - case MAKEFLOATBLOCK: - case GETFIELD: - case SETFIELD: - case GETFLOATFIELD: - case SETFLOATFIELD: - case BRANCH: - case BRANCHIF: - case BRANCHIFNOT: - case PUSHTRAP: - case CONSTINT: - case PUSHCONSTINT: - case OFFSETINT: - case OFFSETREF: - case OFFSETCLOSURE: - case PUSHOFFSETCLOSURE: - snprintf(buf, sizeof(buf), "%s %d", nam, pc[0]); - break; - /* Instructions with two operands */ - case APPTERM: - case CLOSURE: - case CLOSUREREC: - case PUSHGETGLOBALFIELD: - case GETGLOBALFIELD: - case MAKEBLOCK: - case BEQ: - case BNEQ: - case BLTINT: - case BLEINT: - case BGTINT: - case BGEINT: - case BULTINT: - case BUGEINT: - snprintf(buf, sizeof(buf), "%s %d, %d", nam, pc[0], pc[1]); + snprintf(buf, sizeof(buf), "%s %s\n", opbuf, (char *) caml_prim_name_table.contents[pc[0]]); break; case SWITCH: - snprintf(buf, sizeof(buf), "SWITCH sz%#lx=%ld::ntag%lu nint%lu", - (long) pc[0], (long) pc[0], (unsigned long) pc[0] >> 16, - (unsigned long) pc[0] & 0xffff); - break; - /* Instructions with a C primitive as operand */ - case C_CALLN: - snprintf(buf, sizeof(buf), "%s %d,", nam, pc[0]); - pc++; - /* fallthrough */ - case C_CALL1: - case C_CALL2: - case C_CALL3: - case C_CALL4: - case C_CALL5: - if (pc[0] < 0 || pc[0] >= caml_prim_name_table.size) - snprintf(buf, sizeof(buf), "%s unknown primitive %d", nam, pc[0]); - else - snprintf(buf, sizeof(buf), "%s %s", - nam, (char *) caml_prim_name_table.contents[pc[0]]); + snprintf(buf, sizeof(buf), "%s ntag=%lu nint=%lu\n", + opbuf, + (unsigned long) pc[0] >> 16, + (unsigned long) pc[0] & 0xffff); break; default: - snprintf(buf, sizeof(buf), "%s", nam); - break; - }; - return buf; + snprintf(buf, sizeof(buf), "%s\n", opbuf); + } + printf("[%02d] %s", Caml_state->id, buf); + fflush (stdout); } - void caml_trace_value_file (value v, code_t prog, asize_t proglen, FILE * f) { @@ -187,13 +104,13 @@ caml_trace_value_file (value v, code_t prog, asize_t proglen, FILE * f) if (prog && v % sizeof (int) == 0 && (code_t) v >= prog && (code_t) v < (code_t) ((char *) prog + proglen)) - fprintf (f, "=code@%ld", (long) ((code_t) v - prog)); + fprintf (f, "=code@%ld", Pc_val(v) - prog); else if (Is_long (v)) fprintf (f, "=long%" ARCH_INTNAT_PRINTF_FORMAT "d", Long_val (v)); - else if ((void*)v >= (void*)Caml_state->stack_low - && (void*)v < (void*)Caml_state->stack_high) + else if (Stack_base(Caml_state->current_stack) <= (value*)v && + (value*)v < Stack_high(Caml_state->current_stack)) fprintf (f, "=stack_%ld", - (long) ((intnat*)Caml_state->stack_high - (intnat*)v)); + (long)((intnat*)Stack_high(Caml_state->current_stack)-(intnat*)v)); else if (Is_block (v)) { int s = Wosize_val (v); int tg = Tag_val (v); @@ -240,7 +157,7 @@ caml_trace_value_file (value v, code_t prog, asize_t proglen, FILE * f) }; if (i > 0) putc (' ', f); - fprintf (f, "%#" ARCH_INTNAT_PRINTF_FORMAT "x", Field (v, i)); + fprintf (f, "%#" ARCH_INTNAT_PRINTF_FORMAT "x", Op_val (v)[i]); }; if (s > 0) putc (')', f); @@ -257,11 +174,12 @@ caml_trace_accu_sp_file (value accu, value * sp, code_t prog, asize_t proglen, fprintf (f, "accu="); caml_trace_value_file (accu, prog, proglen, f); fprintf (f, "\n sp=%#" ARCH_INTNAT_PRINTF_FORMAT "x @%ld:", - (intnat) sp, (long) (Caml_state->stack_high - sp)); + (intnat) sp, (long) (Stack_high(Caml_state->current_stack) - sp)); for (p = sp, i = 0; - i < 12 + (1 << caml_trace_level) && p < Caml_state->stack_high; + i < 12 + (1 << caml_params->trace_level) && + p < Stack_high(Caml_state->current_stack); p++, i++) { - fprintf (f, "\n[%ld] ", (long) (Caml_state->stack_high - p)); + fprintf (f, "\n[%ld] ", (long) (Stack_high(Caml_state->current_stack) - p)); caml_trace_value_file (*p, prog, proglen, f); }; putc ('\n', f); diff --git a/runtime/intern.c b/runtime/intern.c index 651c5ab570..07ee156563 100644 --- a/runtime/intern.c +++ b/runtime/intern.c @@ -31,43 +31,17 @@ #include "caml/intext.h" #include "caml/io.h" #include "caml/memory.h" -#include "caml/memprof.h" #include "caml/mlvalues.h" #include "caml/misc.h" #include "caml/reverse.h" -#include "caml/signals.h" - -static unsigned char * intern_src; +static __thread unsigned char * intern_src; /* Reading pointer in block holding input data. */ -static unsigned char * intern_input = NULL; +static __thread unsigned char * intern_input = NULL; /* Pointer to beginning of block holding input data, if non-NULL this pointer will be freed by the cleanup function. */ -static header_t * intern_dest; -/* Writing pointer in destination block */ - -static char * intern_extra_block = NULL; -/* If non-NULL, point to new heap chunk allocated with caml_alloc_for_heap. */ - -static asize_t obj_counter; -/* Count how many objects seen so far */ - -static value * intern_obj_table = NULL; -/* The pointers to objects already seen */ - -static color_t intern_color; -/* Color to assign to newly created headers */ - -static header_t intern_header; -/* Original header of the destination block. - Meaningful only if intern_extra_block is NULL. */ - -static value intern_block = 0; -/* Point to the heap block allocated as destination block. - Meaningful only if intern_extra_block is NULL. */ - static char * intern_resolve_code_pointer(unsigned char digest[16], asize_t offset); @@ -75,8 +49,6 @@ CAMLnoreturn_start static void intern_bad_code_pointer(unsigned char digest[16]) CAMLnoreturn_end; -static void intern_free_stack(void); - Caml_inline unsigned char read8u(void) { return *intern_src++; } @@ -143,39 +115,18 @@ static void intern_init(void * src, void * input) /* This is asserted at the beginning of demarshaling primitives. If it fails, it probably means that an exception was raised without calling intern_cleanup() during the previous demarshaling. */ - CAMLassert (intern_input == NULL && intern_obj_table == NULL \ - && intern_extra_block == NULL && intern_block == 0); + CAMLassert (intern_input == NULL); intern_src = src; intern_input = input; } -static void intern_cleanup(void) -{ - if (intern_input != NULL) { - caml_stat_free(intern_input); - intern_input = NULL; - } - if (intern_obj_table != NULL) { - caml_stat_free(intern_obj_table); - intern_obj_table = NULL; - } - if (intern_extra_block != NULL) { - /* free newly allocated heap chunk */ - caml_free_for_heap(intern_extra_block); - intern_extra_block = NULL; - } else if (intern_block != 0) { - /* restore original header for heap block, otherwise GC is confused */ - Hd_val(intern_block) = intern_header; - intern_block = 0; - } - /* free the recursion stack */ - intern_free_stack(); -} +struct intern_stack; +static void intern_cleanup(struct intern_stack*); static void readfloat(double * dest, unsigned int code) { if (sizeof(double) != 8) { - intern_cleanup(); + intern_cleanup(0); // Leak!! caml_invalid_argument("input_value: non-standard floats"); } readblock((char *) dest, 8); @@ -200,7 +151,7 @@ static void readfloats(double * dest, mlsize_t len, unsigned int code) { mlsize_t i; if (sizeof(double) != 8) { - intern_cleanup(); + intern_cleanup(0); // Leak!! caml_invalid_argument("input_value: non-standard floats"); } readblock((char *) dest, len * 8); @@ -230,486 +181,427 @@ static void readfloats(double * dest, mlsize_t len, unsigned int code) #endif } -/* Item on the stack with defined operation */ -struct intern_item { - value * dest; - intnat arg; - enum { - OReadItems, /* read arg items and store them in dest[0], dest[1], ... */ - OFreshOID, /* generate a fresh OID and store it in *dest */ - OShift /* offset *dest by arg */ - } op; +enum { + OReadItems, /* read arg items and store them in dest[0], dest[1], ... */ + OFreshOID, /* generate a fresh OID and store it in *dest */ + OShift /* offset *dest by arg */ }; -/* FIXME: This is duplicated in two other places, with the only difference of - the type of elements stored in the stack. Possible solution in C would - be to instantiate stack these function via. C preprocessor macro. - */ +#define STACK_NFIELDS 4 +#define STACK_VAL(s, i) (s)[i][0] /* the value being read */ +#define STACK_FIELD(s, i) (s)[i][1] /* the next field to be read */ +#define STACK_OP(s, i) (s)[i][2] /* the operation */ +#define STACK_ARG(s, i) (s)[i][3] /* if op == OReadItems, the length */ + -#define INTERN_STACK_INIT_SIZE 256 +#define INTERN_STACK_INIT_SIZE 64 #define INTERN_STACK_MAX_SIZE (1024*1024*100) +typedef value intern_stack_item[STACK_NFIELDS]; +struct intern_stack { + struct caml__roots_block caml__roots_stack; -static struct intern_item intern_stack_init[INTERN_STACK_INIT_SIZE]; + intern_stack_item first_vals[INTERN_STACK_INIT_SIZE]; -static struct intern_item * intern_stack = intern_stack_init; -static struct intern_item * intern_stack_limit = intern_stack_init - + INTERN_STACK_INIT_SIZE; + intern_stack_item* curr_vals; + int len; + int sp; +}; -/* Free the recursion stack if needed */ -static void intern_free_stack(void) -{ - if (intern_stack != intern_stack_init) { - caml_stat_free(intern_stack); - /* Reinitialize the globals for next time around */ - intern_stack = intern_stack_init; - intern_stack_limit = intern_stack + INTERN_STACK_INIT_SIZE; +static void stack_init(struct intern_stack* s) { + int i, j; + for (i = 0; i < INTERN_STACK_INIT_SIZE; i++) { + for (j = 0; j < STACK_NFIELDS; j++) { + s->first_vals[i][j] = Val_unit; + } } + s->curr_vals = s->first_vals; + s->len = INTERN_STACK_INIT_SIZE; + s->sp = 0; + + /* Set up GC roots */ + s->caml__roots_stack.next = CAML_LOCAL_ROOTS; + CAML_LOCAL_ROOTS = &s->caml__roots_stack; + s->caml__roots_stack.mutexes = 0; + s->caml__roots_stack.ntables = 1; + s->caml__roots_stack.nitems = INTERN_STACK_INIT_SIZE * STACK_NFIELDS; + s->caml__roots_stack.tables[0] = (value*)s->curr_vals; +} + +static int stack_is_empty(struct intern_stack* s) { + return s->sp == 0; +} + +static void stack_free(struct intern_stack* s) { + /* free any memory allocated */ + if (s->curr_vals != s->first_vals) caml_stat_free(s->curr_vals); +} + +static void stack_realloc(struct intern_stack* s, value save) { + CAMLparam1(save); + int i; + intern_stack_item* new_vals; + int new_len = s->len * 2; + /* reallocate stack */ + caml_gc_log("Reallocating intern stack to size %d", new_len); + if (new_len >= INTERN_STACK_MAX_SIZE) { + caml_gc_log ("Stack overflow in un-marshaling value"); + stack_free(s); + caml_raise_out_of_memory(); + } + + new_vals = caml_stat_alloc(new_len * STACK_NFIELDS * sizeof(value)); + + for (i = 0; i < s->sp; i++) { + STACK_VAL(new_vals, i) = STACK_VAL(s->curr_vals, i); + STACK_FIELD(new_vals, i) = STACK_FIELD(s->curr_vals, i); + STACK_OP(new_vals, i) = STACK_OP(s->curr_vals, i); + STACK_ARG(new_vals, i) = STACK_ARG(s->curr_vals, i); + } + + for (; i < new_len; i++) { + STACK_VAL(new_vals, i) = Val_unit; + STACK_FIELD(new_vals, i) = Val_unit; + STACK_OP(new_vals, i) = Val_unit; + STACK_ARG(new_vals, i) = Val_unit; + } + + if (s->curr_vals != s->first_vals) caml_stat_free(s->curr_vals); + + /* register GC root */ + s->curr_vals = new_vals; + s->len = new_len; + s->caml__roots_stack.nitems = new_len * STACK_NFIELDS; + s->caml__roots_stack.tables[0] = (value*)new_vals; + CAMLreturn0; } -/* Same, then raise Out_of_memory */ -CAMLnoreturn_start -static void intern_stack_overflow(void) -CAMLnoreturn_end; +static void stack_push(struct intern_stack* s, value v, int field, int op, intnat arg) { + if (Is_block(v)) { + Assert(field < Wosize_hd(Hd_val(v))); + } + if (s->sp == s->len - 1) { + stack_realloc(s, v); + } + STACK_VAL(s->curr_vals, s->sp) = v; + STACK_FIELD(s->curr_vals, s->sp) = Val_int(field); + STACK_OP(s->curr_vals, s->sp) = Val_int(op); + STACK_ARG(s->curr_vals, s->sp) = Val_long(arg); + s->sp++; +} -static void intern_stack_overflow(void) -{ - caml_gc_message (0x04, "Stack overflow in un-marshaling value\n"); - intern_free_stack(); - caml_raise_out_of_memory(); +static void stack_pop(struct intern_stack* s) { + Assert(!stack_is_empty(s)); + s->sp--; +} + +static value stack_curr_val(struct intern_stack* s) { + Assert(!stack_is_empty(s)); + return STACK_VAL(s->curr_vals, s->sp - 1); +} + +static int stack_curr_op(struct intern_stack* s) { + Assert(!stack_is_empty(s)); + return Int_val(STACK_OP(s->curr_vals, s->sp - 1)); +} + +static int stack_curr_field(struct intern_stack* s) { + Assert(!stack_is_empty(s)); + return Int_val(STACK_FIELD(s->curr_vals, s->sp - 1)); } -static struct intern_item * intern_resize_stack(struct intern_item * sp) +static void stack_advance_field(struct intern_stack* s) { + int field; + Assert(!stack_is_empty(s)); + field = Int_val(STACK_FIELD(s->curr_vals, s->sp - 1)); + field++; + STACK_FIELD(s->curr_vals, s->sp - 1) = Val_int(field); + if (field == Int_val(STACK_ARG(s->curr_vals, s->sp - 1))) { + stack_pop(s); + } +} + +static void stack_push_items(struct intern_stack* s, value dest, int n) { + if (n > 0) { + stack_push(s, dest, 0, OReadItems, n); + } +} + +static void intern_cleanup(struct intern_stack* s) { - asize_t newsize = 2 * (intern_stack_limit - intern_stack); - asize_t sp_offset = sp - intern_stack; - struct intern_item * newstack; - - if (newsize >= INTERN_STACK_MAX_SIZE) intern_stack_overflow(); - if (intern_stack == intern_stack_init) { - newstack = caml_stat_alloc_noexc(sizeof(struct intern_item) * newsize); - if (newstack == NULL) intern_stack_overflow(); - memcpy(newstack, intern_stack_init, - sizeof(struct intern_item) * INTERN_STACK_INIT_SIZE); - } else { - newstack = caml_stat_resize_noexc(intern_stack, - sizeof(struct intern_item) * newsize); - if (newstack == NULL) intern_stack_overflow(); + if (intern_input != NULL) { + caml_stat_free (intern_input); + intern_input = NULL; } - intern_stack = newstack; - intern_stack_limit = newstack + newsize; - return newstack + sp_offset; + if (s) stack_free(s); } -/* Convenience macros for requesting operation on the stack */ -#define PushItem() \ - do { \ - sp++; \ - if (sp >= intern_stack_limit) sp = intern_resize_stack(sp); \ - } while(0) - -#define ReadItems(_dest,_n) \ - do { \ - if (_n > 0) { \ - PushItem(); \ - sp->op = OReadItems; \ - sp->dest = _dest; \ - sp->arg = _n; \ - } \ - } while(0) - -static void intern_rec(value *dest) +static value intern_rec(mlsize_t whsize, mlsize_t num_objects) { + int first = 1; + int curr_field; unsigned int code; tag_t tag; - mlsize_t size, len, ofs_ind; - value v; + mlsize_t size, len, i; asize_t ofs; header_t header; unsigned char digest[16]; struct custom_operations * ops; char * codeptr; - struct intern_item * sp; - - sp = intern_stack; + struct intern_stack S; + asize_t obj_counter = 0; /* Count how many objects seen so far */ + int use_intern_table; + + CAMLparam0(); + CAMLlocal4(v, /* the current object being read */ + dest, /* the object into which v will be inserted */ + result, /* the eventual result */ + intern_obj_table); /* object table for storing shared objects */ + stack_init(&S); + + use_intern_table = whsize > 0 && num_objects > 0; + if (use_intern_table) { + intern_obj_table = caml_alloc(num_objects, 0); + } /* Initially let's try to read the first object from the stream */ - ReadItems(dest, 1); + stack_push(&S, Val_unit, 0, OReadItems, 1); /* The un-marshaler loop, the recursion is unrolled */ - while(sp != intern_stack) { - - /* Interpret next item on the stack */ - dest = sp->dest; - switch (sp->op) { - case OFreshOID: - /* Refresh the object ID */ - /* but do not do it for predefined exception slots */ - if (Long_val(Field((value)dest, 1)) >= 0) - caml_set_oo_id((value)dest); - /* Pop item and iterate */ - sp--; - break; - case OShift: - /* Shift value by an offset */ - *dest += sp->arg; - /* Pop item and iterate */ - sp--; - break; - case OReadItems: - /* Pop item */ - sp->dest++; - if (--(sp->arg) == 0) sp--; - /* Read a value and set v to this value */ - code = read8u(); - if (code >= PREFIX_SMALL_INT) { - if (code >= PREFIX_SMALL_BLOCK) { - /* Small block */ - tag = code & 0xF; - size = (code >> 4) & 0x7; - read_block: - if (size == 0) { - v = Atom(tag); - } else { - v = Val_hp(intern_dest); - if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; - *intern_dest = Make_header_allocated_here(size, tag, intern_color); - intern_dest += 1 + size; - /* For objects, we need to freshen the oid */ - if (tag == Object_tag) { - CAMLassert(size >= 2); - /* Request to read rest of the elements of the block */ - ReadItems(&Field(v, 2), size - 2); - /* Request freshing OID */ - PushItem(); - sp->op = OFreshOID; - sp->dest = (value*) v; - sp->arg = 1; - /* Finally read first two block elements: method table and old OID */ - ReadItems(&Field(v, 0), 2); - } else - /* If it's not an object then read the contents of the block */ - ReadItems(&Field(v, 0), size); - } - } else { - /* Small integer */ - v = Val_int(code & 0x3F); + while (!stack_is_empty(&S)) { + + /* Interpret next item on the stack */ + dest = stack_curr_val(&S); + curr_field = stack_curr_field(&S); + if (!first) { + Assert (0 <= curr_field && curr_field < Wosize_hd(Hd_val(dest))); } - } else { - if (code >= PREFIX_SMALL_STRING) { - /* Small string */ - len = (code & 0x1F); - read_string: - size = (len + sizeof(value)) / sizeof(value); - v = Val_hp(intern_dest); - if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; - *intern_dest = Make_header_allocated_here(size, String_tag, intern_color); - intern_dest += 1 + size; - Field(v, size - 1) = 0; - ofs_ind = Bsize_wsize(size) - 1; - Byte(v, ofs_ind) = ofs_ind - len; - readblock((char *)String_val(v), len); - } else { - switch(code) { - case CODE_INT8: - v = Val_long(read8s()); - break; - case CODE_INT16: - v = Val_long(read16s()); - break; - case CODE_INT32: - v = Val_long(read32s()); - break; - case CODE_INT64: + + switch (stack_curr_op(&S)) { + case OFreshOID: + /* Refresh the object ID */ + /* but do not do it for predefined exception slots */ + if (Int_field(dest, 1) >= 0) + caml_set_oo_id(dest); + /* Pop item and iterate */ + stack_pop(&S); + break; + case OShift: + caml_failwith("shift op"); + /* Shift value by an offset */ + /* !! */ + /* *dest += sp->arg; */ + /* Pop item and iterate */ + /* sp--; */ + break; + case OReadItems: + /* Pop item */ + stack_advance_field(&S); + /* Read a value and set v to this value */ + code = read8u(); + if (code >= PREFIX_SMALL_INT) { + if (code >= PREFIX_SMALL_BLOCK) { + /* Small block */ + tag = code & 0xF; + size = (code >> 4) & 0x7; + read_block: + if (size == 0) { + v = Atom(tag); + } else { + Assert(tag != Closure_tag); + Assert(tag != Infix_tag); + v = caml_alloc(size, tag); + for (i = 0; i < size; i++) Op_val(v)[i] = Val_unit; + if (use_intern_table) Store_field(intern_obj_table, obj_counter++, v); + /* For objects, we need to freshen the oid */ + if (tag == Object_tag) { + Assert(size >= 2); + /* Request to read rest of the elements of the block */ + if (size > 2) stack_push(&S, v, 2, OReadItems, size - 2); + /* Request freshing OID */ + stack_push(&S, v, 1, OFreshOID, 1); + /* Finally read first two block elements: method table and old OID */ + stack_push(&S, v, 0, OReadItems, 2); + } else { + /* If it's not an object then read the contents of the block */ + stack_push_items(&S, v, size); + } + } + } else { + /* Small integer */ + v = Val_int(code & 0x3F); + } + } else { + if (code >= PREFIX_SMALL_STRING) { + /* Small string */ + len = (code & 0x1F); + read_string: + v = caml_alloc_string(len); + if (use_intern_table) Store_field(intern_obj_table, obj_counter++, v); + readblock((char *)String_val(v), len); + } else { + switch(code) { + case CODE_INT8: + v = Val_long(read8s()); + break; + case CODE_INT16: + v = Val_long(read16s()); + break; + case CODE_INT32: + v = Val_long(read32s()); + break; + case CODE_INT64: #ifdef ARCH_SIXTYFOUR - v = Val_long((intnat) (read64u())); - break; + v = Val_long((intnat) (read64u())); + break; #else - intern_cleanup(); - caml_failwith("input_value: integer too large"); - break; -#endif - case CODE_SHARED8: - ofs = read8u(); - read_shared: - CAMLassert (ofs > 0); - CAMLassert (ofs <= obj_counter); - CAMLassert (intern_obj_table != NULL); - v = intern_obj_table[obj_counter - ofs]; - break; - case CODE_SHARED16: - ofs = read16u(); - goto read_shared; - case CODE_SHARED32: - ofs = read32u(); - goto read_shared; -#ifdef ARCH_SIXTYFOUR - case CODE_SHARED64: - ofs = read64u(); - goto read_shared; -#endif - case CODE_BLOCK32: - header = (header_t) read32u(); - tag = Tag_hd(header); - size = Wosize_hd(header); - goto read_block; -#ifdef ARCH_SIXTYFOUR - case CODE_BLOCK64: - header = (header_t) read64u(); - tag = Tag_hd(header); - size = Wosize_hd(header); - goto read_block; + intern_cleanup(&S); + caml_failwith("input_value: integer too large"); + break; #endif - case CODE_STRING8: - len = read8u(); - goto read_string; - case CODE_STRING32: - len = read32u(); - goto read_string; + case CODE_SHARED8: + ofs = read8u(); + read_shared: + Assert (ofs > 0); + Assert (ofs <= obj_counter); + Assert (use_intern_table); + v = Field(intern_obj_table, obj_counter - ofs); + break; + case CODE_SHARED16: + ofs = read16u(); + goto read_shared; + case CODE_SHARED32: + ofs = read32u(); + goto read_shared; + case CODE_BLOCK32: + header = (header_t) read32u(); + tag = Tag_hd(header); + size = Wosize_hd(header); + goto read_block; + case CODE_BLOCK64: #ifdef ARCH_SIXTYFOUR - case CODE_STRING64: - len = read64u(); - goto read_string; + header = (header_t) read64u(); + tag = Tag_hd(header); + size = Wosize_hd(header); + goto read_block; +#else + intern_cleanup(&S); + caml_failwith("input_value: data block too large"); + break; #endif - case CODE_DOUBLE_LITTLE: - case CODE_DOUBLE_BIG: - v = Val_hp(intern_dest); - if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; - *intern_dest = Make_header_allocated_here(Double_wosize, Double_tag, - intern_color); - intern_dest += 1 + Double_wosize; - readfloat((double *) v, code); - break; - case CODE_DOUBLE_ARRAY8_LITTLE: - case CODE_DOUBLE_ARRAY8_BIG: - len = read8u(); - read_double_array: - size = len * Double_wosize; - v = Val_hp(intern_dest); - if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; - *intern_dest = Make_header_allocated_here(size, Double_array_tag, - intern_color); - intern_dest += 1 + size; - readfloats((double *) v, len, code); - break; - case CODE_DOUBLE_ARRAY32_LITTLE: - case CODE_DOUBLE_ARRAY32_BIG: - len = read32u(); - goto read_double_array; -#ifdef ARCH_SIXTYFOUR - case CODE_DOUBLE_ARRAY64_LITTLE: - case CODE_DOUBLE_ARRAY64_BIG: - len = read64u(); - goto read_double_array; + case CODE_STRING8: + len = read8u(); + goto read_string; + case CODE_STRING32: + len = read32u(); + goto read_string; + case CODE_DOUBLE_LITTLE: + case CODE_DOUBLE_BIG: + v = caml_alloc(Double_wosize, Double_tag); + if (use_intern_table) Store_field(intern_obj_table, obj_counter++, v); + readfloat((double *) v, code); + break; + case CODE_DOUBLE_ARRAY8_LITTLE: + case CODE_DOUBLE_ARRAY8_BIG: + len = read8u(); + read_double_array: + v = caml_alloc(len * Double_wosize, Double_array_tag); + if (use_intern_table) Store_field(intern_obj_table, obj_counter++, v); + readfloats((double *) v, len, code); + break; + case CODE_DOUBLE_ARRAY32_LITTLE: + case CODE_DOUBLE_ARRAY32_BIG: + len = read32u(); + goto read_double_array; + case CODE_CODEPOINTER: + caml_failwith("wtfff"); + ofs = read32u(); + readblock(digest, 16); + codeptr = intern_resolve_code_pointer(digest, ofs); /* !! */ + if (codeptr != NULL) { + v = (value) codeptr; + } else { + const value* function_placeholder = + caml_named_value ("Debugger.function_placeholder"); + if (function_placeholder) { + v = *function_placeholder; + } else { + intern_cleanup(&S); + intern_bad_code_pointer(digest); + } + } + break; + case CODE_INFIXPOINTER: + caml_failwith("wtf"); +#if 0 + ofs = read32u(); + /* Read a value to *dest, then offset *dest by ofs */ + PushItem(); + sp->dest = dest; + sp->op = OShift; + sp->arg = ofs; + ReadItems(dest, 1); + continue; /* with next iteration of main loop, skipping *dest = v */ #endif - case CODE_CODEPOINTER: - ofs = read32u(); - readblock(digest, 16); - codeptr = intern_resolve_code_pointer(digest, ofs); - if (codeptr != NULL) { - v = (value) codeptr; - } else { - const value * function_placeholder = - caml_named_value ("Debugger.function_placeholder"); - if (function_placeholder != NULL) { - v = *function_placeholder; - } else { - intern_cleanup(); - intern_bad_code_pointer(digest); - } - } - break; - case CODE_INFIXPOINTER: - ofs = read32u(); - /* Read a value to *dest, then offset *dest by ofs */ - PushItem(); - sp->dest = dest; - sp->op = OShift; - sp->arg = ofs; - ReadItems(dest, 1); - continue; /* with next iteration of main loop, skipping *dest = v */ - case CODE_CUSTOM: - case CODE_CUSTOM_LEN: - case CODE_CUSTOM_FIXED: { - ops = caml_find_custom_operations((char *) intern_src); - if (ops == NULL) { - intern_cleanup(); - caml_failwith("input_value: unknown custom block identifier"); - } - if (code == CODE_CUSTOM_FIXED && ops->fixed_length == NULL) { - intern_cleanup(); - caml_failwith("input_value: expected a fixed-size custom block"); - } - while (*intern_src++ != 0) /*nothing*/; /*skip identifier*/ - if (code == CODE_CUSTOM) { - /* deprecated */ - size = ops->deserialize((void *) (intern_dest + 2)); - } else { - uintnat expected_size; + + case CODE_CUSTOM: + case CODE_CUSTOM_LEN: + case CODE_CUSTOM_FIXED: { + uintnat expected_size, size; + ops = caml_find_custom_operations((char *) intern_src); + if (ops == NULL) { + intern_cleanup(&S); + caml_failwith("input_value: unknown custom block identifier"); + } + if (code != CODE_CUSTOM_LEN && ops->fixed_length == NULL) { + intern_cleanup(&S); + caml_failwith("input_value: expected a fixed-size custom block"); + } + while (*intern_src++ != 0) /*nothing*/; /*skip identifier*/ #ifdef ARCH_SIXTYFOUR - if (code == CODE_CUSTOM_FIXED) { - expected_size = ops->fixed_length->bsize_64; - } else { - intern_src += 4; - expected_size = read64u(); - } + if (code != CODE_CUSTOM_LEN) { + expected_size = ops->fixed_length->bsize_64; + } else { + intern_src += 4; + expected_size = read64u(); + } #else - if (code == CODE_CUSTOM_FIXED) { - expected_size = ops->fixed_length->bsize_32; - } else { - expected_size = read32u(); - intern_src += 8; - } + if (code != CODE_CUSTOM_LEN) { + expected_size = ops->fixed_length->bsize_32; + } else { + expected_size = read32u(); + intern_src += 8; + } #endif - size = ops->deserialize((void *) (intern_dest + 2)); - if (size != expected_size) { - intern_cleanup(); - caml_failwith( - "input_value: incorrect length of serialized custom block"); + v = caml_alloc_custom(ops, expected_size, 0, 0); + size = ops->deserialize(Data_custom_val(v)); + if (size != expected_size) { + intern_cleanup(&S); + caml_failwith( + "input_value: incorrect length of serialized custom block"); + } + if (use_intern_table) Store_field (intern_obj_table, obj_counter++, v); + break; + } + default: + intern_cleanup(&S); + caml_failwith("input_value: ill-formed message"); } } - size = 1 + (size + sizeof(value) - 1) / sizeof(value); - v = Val_hp(intern_dest); - if (intern_obj_table != NULL) intern_obj_table[obj_counter++] = v; - *intern_dest = Make_header_allocated_here(size, Custom_tag, - intern_color); - Custom_ops_val(v) = ops; - - if (ops->finalize != NULL && Is_young(v)) { - /* Remember that the block has a finalizer. */ - add_to_custom_table (Caml_state->custom_table, v, 0, 1); - } - - intern_dest += 1 + size; - break; - } - default: - intern_cleanup(); - caml_failwith("input_value: ill-formed message"); } - } - } - /* end of case OReadItems */ - *dest = v; - break; - default: - CAMLassert(0); - } - } - /* We are done. Cleanup the stack and leave the function */ - intern_free_stack(); -} - -static void intern_alloc(mlsize_t whsize, mlsize_t num_objects, - int outside_heap) -{ - mlsize_t wosize; - - if (whsize == 0) { - CAMLassert (intern_extra_block == NULL && intern_block == 0 - && intern_obj_table == NULL); - return; - } - wosize = Wosize_whsize(whsize); - if (outside_heap || wosize > Max_wosize) { - /* Round desired size up to next page */ - asize_t request = - ((Bsize_wsize(whsize) + Page_size - 1) >> Page_log) << Page_log; - intern_extra_block = caml_alloc_for_heap(request); - if (intern_extra_block == NULL) { - intern_cleanup(); - caml_raise_out_of_memory(); - } - intern_color = - outside_heap ? Caml_black : caml_allocation_color(intern_extra_block); - intern_dest = (header_t *) intern_extra_block; - CAMLassert (intern_block == 0); - } else { - /* this is a specialised version of caml_alloc from alloc.c */ - if (wosize <= Max_young_wosize){ - if (wosize == 0){ - intern_block = Atom (String_tag); - }else{ -#define Setup_for_gc -#define Restore_after_gc - Alloc_small_no_track(intern_block, wosize, String_tag); -#undef Setup_for_gc -#undef Restore_after_gc - } - }else{ - intern_block = caml_alloc_shr_no_track_noexc (wosize, String_tag); - /* do not do the urgent_gc check here because it might darken - intern_block into gray and break the intern_color assertion below */ - if (intern_block == 0) { - intern_cleanup(); - caml_raise_out_of_memory(); + /* end of case OReadItems */ + if (first) { + result = v; + first = 0; + } else { + Store_field(dest, curr_field, v); } + break; + default: + Assert(0); } - intern_header = Hd_val(intern_block); - intern_color = Color_hd(intern_header); - CAMLassert (intern_color == Caml_white || intern_color == Caml_black); - intern_dest = (header_t *) Hp_val(intern_block); - CAMLassert (intern_extra_block == NULL); } - obj_counter = 0; - if (num_objects > 0) { - intern_obj_table = - (value *) caml_stat_alloc_noexc(num_objects * sizeof(value)); - if (intern_obj_table == NULL) { - intern_cleanup(); - caml_raise_out_of_memory(); - } - } else - CAMLassert(intern_obj_table == NULL); -} - -static header_t* intern_add_to_heap(mlsize_t whsize) -{ - header_t* res = NULL; - /* 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 = Chunk_size (intern_extra_block); - header_t * end_extra_block = - (header_t *) intern_extra_block + Wsize_bsize(request); - CAMLassert(intern_block == 0); - CAMLassert(intern_dest <= end_extra_block); - if (intern_dest < end_extra_block){ - caml_make_free_blocks ((value *) intern_dest, - end_extra_block - intern_dest, 0, Caml_white); - } - caml_allocated_words += - Wsize_bsize ((char *) intern_dest - intern_extra_block); - if(caml_add_to_heap(intern_extra_block) != 0) { - intern_cleanup(); - caml_raise_out_of_memory(); - } - res = (header_t*)intern_extra_block; - intern_extra_block = NULL; // To prevent intern_cleanup freeing it - } else if(intern_block != 0) { /* [intern_block = 0] when [whsize = 0] */ - res = Hp_val(intern_block); - intern_block = 0; // To prevent intern_cleanup rewriting its header - } - return res; -} - -static value intern_end(value res, mlsize_t whsize) -{ - CAMLparam1(res); - header_t *block = intern_add_to_heap(whsize); - header_t *blockend = intern_dest; - - /* Free everything */ - intern_cleanup(); - - /* Memprof tracking has to be done here, because unmarshalling can - still fail until now. */ - if(block != NULL) - caml_memprof_track_interned(block, blockend); - - // Give gc a chance to run, and run memprof callbacks - caml_process_pending_actions(); - - CAMLreturn(res); + stack_free(&S); + CAMLreturn(result); } /* Parsing the header */ @@ -767,7 +659,7 @@ static void caml_parse_header(char * fun_name, /* Reading from a channel */ -static value caml_input_val_core(struct channel *chan, int outside_heap) +static value caml_input_val_core(struct channel *chan) { intnat r; char header[32]; @@ -803,24 +695,16 @@ static value caml_input_val_core(struct channel *chan, int outside_heap) } /* Initialize global state */ intern_init(block, block); - intern_alloc(h.whsize, h.num_objects, outside_heap); /* Fill it in */ - intern_rec(&res); - if (!outside_heap) - return intern_end(res, h.whsize); - else { - caml_disown_for_heap(intern_extra_block); - intern_extra_block = NULL; - intern_block = 0; - /* Free everything */ - intern_cleanup(); - return caml_check_urgent_gc(res); - } + res = intern_rec(h.whsize, h.num_objects); + /* Free everything */ + intern_cleanup(0); // Leak!! + return caml_check_urgent_gc(res); } value caml_input_val(struct channel* chan) { - return caml_input_val_core(chan, 0); + return caml_input_val_core(chan); } CAMLprim value caml_input_value(value vchan) @@ -829,9 +713,9 @@ CAMLprim value caml_input_value(value vchan) struct channel * chan = Channel(vchan); CAMLlocal1 (res); - Lock(chan); - res = caml_input_val(chan); - Unlock(chan); + With_mutex(&chan->mutex, { + res = caml_input_val(chan); + } ); CAMLreturn (res); } @@ -839,48 +723,18 @@ CAMLprim value caml_input_value(value vchan) CAMLprim value caml_input_value_to_outside_heap(value vchan) { - CAMLparam1 (vchan); - struct channel * chan = Channel(vchan); - CAMLlocal1 (res); - - Lock(chan); - res = caml_input_val_core(chan, 1); - Unlock(chan); - CAMLreturn (res); -} - -CAMLexport value caml_input_val_from_bytes(value str, intnat ofs) -{ - CAMLparam1 (str); - CAMLlocal1 (obj); - struct marshal_header h; - - /* Initialize global state */ - intern_init(&Byte_u(str, ofs), NULL); - caml_parse_header("input_val_from_string", &h); - if (ofs + h.header_len + h.data_len > caml_string_length(str)) - caml_failwith("input_val_from_string: bad length"); - /* Allocate result */ - intern_alloc(h.whsize, h.num_objects, 0); - intern_src = &Byte_u(str, ofs + h.header_len); /* If a GC occurred */ - /* Fill it in */ - intern_rec(&obj); - CAMLreturn (intern_end(obj, h.whsize)); -} - -CAMLprim value caml_input_value_from_bytes(value str, value ofs) -{ - return caml_input_val_from_bytes(str, Long_val(ofs)); + /* XXX KC: outside_heap is ignored */ + return caml_input_value(vchan); } static value input_val_from_block(struct marshal_header * h) { value obj; - /* Allocate result */ - intern_alloc(h->whsize, h->num_objects, 0); /* Fill it in */ - intern_rec(&obj); - return (intern_end(obj, h->whsize)); + obj = intern_rec(h->whsize, h->num_objects); + /* Free internal data structures */ + intern_cleanup(0); //Leak!! + return caml_check_urgent_gc(obj); } CAMLexport value caml_input_value_from_malloc(char * data, intnat ofs) @@ -895,18 +749,42 @@ CAMLexport value caml_input_value_from_malloc(char * data, intnat ofs) } /* [len] is a number of bytes */ -CAMLexport value caml_input_value_from_block(char * data, intnat len) +CAMLexport value caml_input_value_from_block(const char * data, intnat len) { struct marshal_header h; /* Initialize global state */ - intern_init(data, NULL); + intern_init((void*)data, NULL); caml_parse_header("input_value_from_block", &h); if (h.header_len + h.data_len > len) caml_failwith("input_val_from_block: bad length"); return input_val_from_block(&h); } +CAMLexport value caml_input_val_from_bytes(value str, intnat ofs) +{ + CAMLparam1 (str); + CAMLlocal1 (obj); + struct marshal_header h; + + /* Initialize global state */ + intern_init(&Byte_u(str, ofs), NULL); + caml_parse_header("input_val_from_string", &h); + if (ofs + h.header_len + h.data_len > caml_string_length(str)) + caml_failwith("input_val_from_string: bad length"); + intern_src = &Byte_u(str, ofs + h.header_len); /* If a GC occurred */ + /* Fill it in */ + obj = intern_rec(h.whsize, h.num_objects); + /* Free everything */ + intern_cleanup(0); // Leak!! + CAMLreturn (caml_check_urgent_gc(obj)); +} + +CAMLprim value caml_input_value_from_bytes(value str, value ofs) +{ + return caml_input_val_from_bytes(str, Long_val(ofs)); +} + /* [ofs] is a [value] that represents a number of bytes result is a [value] that represents a number of bytes To handle both the small and the big format, @@ -1094,6 +972,6 @@ CAMLexport void caml_deserialize_block_float_8(void * data, intnat len) CAMLexport void caml_deserialize_error(char * msg) { - intern_cleanup(); + intern_cleanup(0); // Leak!! caml_failwith(msg); } diff --git a/runtime/interp.c b/runtime/interp.c index 3411eb65de..c7e25213ca 100644 --- a/runtime/interp.c +++ b/runtime/interp.c @@ -32,7 +32,10 @@ #include "caml/mlvalues.h" #include "caml/prims.h" #include "caml/signals.h" -#include "caml/stacks.h" +#include "caml/fiber.h" +#include "caml/domain.h" +#include "caml/globroots.h" +#include "caml/startup.h" #include "caml/startup_aux.h" /* Registers for the abstract machine: @@ -40,7 +43,7 @@ sp the stack pointer (grows downward) accu the accumulator env heap-allocated environment - Caml_state->trapsp pointer to the current trap frame + Caml_state->trap_sp_off offset to the current trap frame extra_args number of extra arguments provided by the caller sp is a local copy of the global variable Caml_state->extern_sp. */ @@ -71,18 +74,20 @@ sp is a local copy of the global variable Caml_state->extern_sp. */ // Do call asynchronous callbacks from allocation functions #define Alloc_small_origin CAML_FROM_CAML #define Setup_for_gc \ - { sp -= 3; sp[0] = accu; sp[1] = env; sp[2] = (value)pc; \ - Caml_state->extern_sp = sp; } + { sp -= 3; sp[0] = accu; sp[1] = env; sp[2] = Val_pc(pc); \ + domain_state->current_stack->sp = sp; } #define Restore_after_gc \ - { sp = Caml_state->extern_sp; accu = sp[0]; env = sp[1]; sp += 3; } + { sp = domain_state->current_stack->sp; accu = sp[0]; env = sp[1]; sp += 3; } +#define Enter_gc \ + { Setup_for_gc; caml_handle_gc_interrupt(); Restore_after_gc; } /* We store [pc+1] in the stack so that, in case of an exception, the first backtrace slot points to the event following the C call instruction. */ #define Setup_for_c_call \ - { sp -= 2; sp[0] = env; sp[1] = (value)(pc + 1); Caml_state->extern_sp = sp; } + { sp -= 2; sp[0] = env; sp[1] = Val_pc(pc + 1); domain_state->current_stack->sp = sp; } #define Restore_after_c_call \ - { sp = Caml_state->extern_sp; env = *sp; sp += 2; } + { sp = domain_state->current_stack->sp; env = *sp; sp += 2; } /* For VM threads purposes, an event frame must look like accu + a C_CALL frame + a RETURN 1 frame. @@ -93,13 +98,13 @@ sp is a local copy of the global variable Caml_state->extern_sp. */ sp[0] = accu; /* accu */ \ sp[1] = Val_unit; /* C_CALL frame: dummy environment */ \ sp[2] = Val_unit; /* RETURN frame: dummy local 0 */ \ - sp[3] = (value) pc; /* RETURN frame: saved return address */ \ + sp[3] = Val_pc(pc); /* RETURN frame: saved return address */ \ sp[4] = env; /* RETURN frame: saved environment */ \ sp[5] = Val_long(extra_args); /* RETURN frame: saved extra args */ \ - Caml_state->extern_sp = sp; } + domain_state->current_stack->sp = sp; } #define Restore_after_event \ - { sp = Caml_state->extern_sp; accu = sp[0]; \ - pc = (code_t) sp[3]; env = sp[4]; extra_args = Long_val(sp[5]); \ + { sp = domain_state->current_stack->sp; accu = sp[0]; \ + pc = Pc_val(sp[3]); env = sp[4]; extra_args = Long_val(sp[5]); \ sp += 6; } /* Debugger interface */ @@ -108,9 +113,9 @@ sp is a local copy of the global variable Caml_state->extern_sp. */ { sp -= 4; \ sp[0] = accu; sp[1] = (value)(pc - 1); \ sp[2] = env; sp[3] = Val_long(extra_args); \ - Caml_state->extern_sp = sp; } + domain_state->current_stack->sp = sp; } #define Restore_after_debugger \ - { CAMLassert(sp == Caml_state->extern_sp); \ + { CAMLassert(sp == domain_state->current_stack->sp); \ CAMLassert(sp[0] == accu); \ CAMLassert(sp[2] == env); \ sp += 4; } @@ -124,9 +129,21 @@ sp is a local copy of the global variable Caml_state->extern_sp. */ goto dispatch_instr #endif + +/* Initialising fields of objects just allocated with Alloc_small */ +#define Init_field(o, i, x) Op_val(o)[i] = (x) + +/* Inlined read barrier for interpreter loop. + Does 'accu = accu[i]' */ +#define Accu_field(i) do { \ + int idx = (i); \ + value field_contents = Op_val(accu)[idx]; \ + accu = field_contents; \ + } while (0) + #define Check_trap_barrier \ - if (Caml_state->trapsp >= Caml_state->trap_barrier) \ - caml_debugger(TRAP_BARRIER, Val_unit) + if (domain_state->trap_sp_off >= domain_state->trap_barrier_off) \ + caml_debugger(TRAP_BARRIER, Val_unit) /* Register optimization. Some compilers underestimate the use of the local variables representing @@ -206,11 +223,12 @@ sp is a local copy of the global variable Caml_state->extern_sp. */ #endif #ifdef DEBUG -static intnat caml_bcodcount; +static __thread intnat caml_bcodcount; #endif -/* The interpreter itself */ +static caml_root raise_unhandled; +/* The interpreter itself */ value caml_interprete(code_t prog, asize_t prog_size) { #ifdef PC_REG @@ -231,12 +249,15 @@ value caml_interprete(code_t prog, asize_t prog_size) #endif value env; intnat extra_args; - struct longjmp_buffer * initial_external_raise; - intnat initial_sp_offset; - /* volatile ensures that initial_local_roots - will keep correct value across longjmp */ - struct caml__roots_block * volatile initial_local_roots; + struct caml_exception_context * initial_external_raise; + int initial_stack_words; + intnat initial_trap_sp_off; + volatile value raise_exn_bucket = Val_unit; struct longjmp_buffer raise_buf; + value resume_fn, resume_arg; + caml_domain_state* domain_state = Caml_state; + struct caml_exception_context exception_ctx = + { &raise_buf, domain_state->local_roots, &raise_exn_bucket}; #ifndef THREADED_CODE opcode_t curr_instr; #endif @@ -248,69 +269,82 @@ value caml_interprete(code_t prog, asize_t prog_size) #endif if (prog == NULL) { /* Interpreter is initializing */ + static opcode_t raise_unhandled_code[] = { ACC, 0, RAISE }; + value raise_unhandled_closure; #ifdef THREADED_CODE caml_instr_table = (char **) jumptable; caml_instr_base = Jumptbl_base; + caml_thread_code(raise_unhandled_code, + sizeof(raise_unhandled_code)); #endif + raise_unhandled_closure = caml_alloc_small (2, Closure_tag); + Field(raise_unhandled_closure, 0) = Val_bytecode(raise_unhandled_code); + Closinfo_val(raise_unhandled_closure) = Make_closinfo(0, 2); + raise_unhandled = caml_create_root(raise_unhandled_closure); + caml_global_data = caml_create_root(Val_unit); + caml_init_callbacks(); return Val_unit; } #if defined(THREADED_CODE) && defined(ARCH_SIXTYFOUR) && !defined(ARCH_CODE32) jumptbl_base = Jumptbl_base; #endif - initial_local_roots = Caml_state->local_roots; - initial_sp_offset = - (char *) Caml_state->stack_high - (char *) Caml_state->extern_sp; - initial_external_raise = Caml_state->external_raise; - caml_callback_depth++; + initial_trap_sp_off = domain_state->trap_sp_off; + initial_stack_words = Stack_high(domain_state->current_stack) - domain_state->current_stack->sp; + initial_external_raise = domain_state->external_raise; + caml_incr_callback_depth (); if (sigsetjmp(raise_buf.buf, 0)) { - Caml_state->local_roots = initial_local_roots; - sp = Caml_state->extern_sp; - accu = Caml_state->exn_bucket; + /* no non-volatile local variables read here */ + sp = domain_state->current_stack->sp; + accu = raise_exn_bucket; Check_trap_barrier; - if (Caml_state->backtrace_active) { - /* pc has already been pushed on the stack when calling the C + if (domain_state->backtrace_active) { + /* pc has already been pushed on the stack when calling the C function that raised the exception. No need to push it again here. */ caml_stash_backtrace(accu, sp, 0); } goto raise_notrace; } - Caml_state->external_raise = &raise_buf; + domain_state->external_raise = &exception_ctx; - sp = Caml_state->extern_sp; + domain_state->trap_sp_off = 1; + + sp = domain_state->current_stack->sp; pc = prog; extra_args = 0; env = Atom(0); accu = Val_int(0); + #ifdef THREADED_CODE #ifdef DEBUG next_instr: if (caml_icount-- == 0) caml_stop_here (); - CAMLassert(sp >= Caml_state->stack_low); - CAMLassert(sp <= Caml_state->stack_high); + Assert(Stack_base(domain_state->current_stack) <= sp && + sp <= Stack_high(domain_state->current_stack)); #endif goto *(void *)(jumptbl_base + *pc++); /* Jump to the first instruction */ #else while(1) { #ifdef DEBUG + caml_bcodcount++; if (caml_icount-- == 0) caml_stop_here (); - if (caml_trace_level>1) printf("\n##%" ARCH_INTNAT_PRINTF_FORMAT "d\n", - caml_bcodcount); - if (caml_trace_level>0) caml_disasm_instr(pc); - if (caml_trace_level>1) { + if (caml_params->trace_level>1) printf("\n##%ld\n", caml_bcodcount); + if (caml_params->trace_level) caml_disasm_instr(pc); + if (caml_params->trace_level>1) { printf("env="); caml_trace_value_file(env,prog,prog_size,stdout); putchar('\n'); caml_trace_accu_sp_file(accu,sp,prog,prog_size,stdout); fflush(stdout); }; - CAMLassert(sp >= Caml_state->stack_low); - CAMLassert(sp <= Caml_state->stack_high); + Assert(Stack_base(domain_state->current_stack) <= sp && + sp <= Stack_high(domain_state->current_stack)); + #endif curr_instr = *pc++; @@ -400,7 +434,7 @@ value caml_interprete(code_t prog, asize_t prog_size) Instruct(PUSH_RETADDR): { sp -= 3; - sp[0] = (value) (pc + *pc); + sp[0] = Val_pc(pc + *pc); sp[1] = env; sp[2] = Val_long(extra_args); pc++; @@ -416,7 +450,7 @@ value caml_interprete(code_t prog, asize_t prog_size) value arg1 = sp[0]; sp -= 3; sp[0] = arg1; - sp[1] = (value)pc; + sp[1] = Val_pc(pc); sp[2] = env; sp[3] = Val_long(extra_args); pc = Code_val(accu); @@ -430,7 +464,7 @@ value caml_interprete(code_t prog, asize_t prog_size) sp -= 3; sp[0] = arg1; sp[1] = arg2; - sp[2] = (value)pc; + sp[2] = Val_pc(pc); sp[3] = env; sp[4] = Val_long(extra_args); pc = Code_val(accu); @@ -446,7 +480,7 @@ value caml_interprete(code_t prog, asize_t prog_size) sp[0] = arg1; sp[1] = arg2; sp[2] = arg3; - sp[3] = (value)pc; + sp[3] = Val_pc(pc); sp[4] = env; sp[5] = Val_long(extra_args); pc = Code_val(accu); @@ -509,14 +543,42 @@ value caml_interprete(code_t prog, asize_t prog_size) extra_args--; pc = Code_val(accu); env = accu; + Next; } else { - pc = (code_t)(sp[0]); + goto do_return; + } + } + + do_return: + if (sp == Stack_high(domain_state->current_stack)) { + /* return to parent stack */ + struct stack_info* old_stack = domain_state->current_stack; + struct stack_info* parent_stack = Stack_parent(old_stack); + value hval = Stack_handle_value(old_stack); + Assert(parent_stack != NULL); + + old_stack->sp = sp; + domain_state->current_stack = parent_stack; + sp = domain_state->current_stack->sp; + caml_free_stack(old_stack); + + domain_state->trap_sp_off = Long_val(sp[0]); + extra_args = Long_val(sp[1]); + sp++; + sp[0] = accu; + + accu = hval; + pc = Code_val(accu); + env = accu; + goto check_stacks; + } else { + /* return to callee, no stack switching */ + pc = Pc_val(sp[0]); env = sp[1]; extra_args = Long_val(sp[2]); sp += 3; } Next; - } Instruct(RESTART): { int num_args = Wosize_val(env) - 3; @@ -532,21 +594,18 @@ value caml_interprete(code_t prog, asize_t prog_size) int required = *pc++; if (extra_args >= required) { extra_args -= required; + Next; } else { mlsize_t num_args, i; num_args = 1 + extra_args; /* arg1 + extra args */ - Alloc_small(accu, num_args + 3, Closure_tag); + Alloc_small(accu, num_args + 3, Closure_tag, Enter_gc); Field(accu, 2) = env; for (i = 0; i < num_args; i++) Field(accu, i + 3) = sp[i]; - Code_val(accu) = pc - 3; /* Point to the preceding RESTART instr. */ + Field(accu, 0) = Val_bytecode(pc-3); /* Point to the preceding RESTART instr. */ Closinfo_val(accu) = Make_closinfo(0, 2); sp += num_args; - pc = (code_t)(sp[0]); - env = sp[1]; - extra_args = Long_val(sp[2]); - sp += 3; + goto do_return; } - Next; } Instruct(CLOSURE): { @@ -555,18 +614,18 @@ value caml_interprete(code_t prog, asize_t prog_size) if (nvars > 0) *--sp = accu; if (nvars <= Max_young_wosize - 2) { /* nvars + 2 <= Max_young_wosize, can allocate in minor heap */ - Alloc_small(accu, 2 + nvars, Closure_tag); + Alloc_small(accu, 2 + nvars, Closure_tag, Enter_gc); for (i = 0; i < nvars; i++) Field(accu, i + 2) = sp[i]; } else { - /* PR#6385: must allocate in major heap */ /* caml_alloc_shr and caml_initialize never trigger a GC, so no need to Setup_for_gc */ + /* PR#6385: must allocate in major heap */ accu = caml_alloc_shr(2 + nvars, Closure_tag); for (i = 0; i < nvars; i++) caml_initialize(&Field(accu, i + 2), sp[i]); } /* The code pointer is not in the heap, so no need to go through caml_initialize. */ - Code_val(accu) = pc + *pc; + Field(accu, 0) = Val_bytecode(pc + *pc); Closinfo_val(accu) = Make_closinfo(0, 2); pc++; sp += nvars; @@ -579,10 +638,10 @@ value caml_interprete(code_t prog, asize_t prog_size) mlsize_t envofs = nfuncs * 3 - 1; mlsize_t blksize = envofs + nvars; int i; - value * p; + value *p; if (nvars > 0) *--sp = accu; if (blksize <= Max_young_wosize) { - Alloc_small(accu, blksize, Closure_tag); + Alloc_small(accu, blksize, Closure_tag, Enter_gc); p = &Field(accu, envofs); for (i = 0; i < nvars; i++, p++) *p = sp[i]; } else { @@ -598,12 +657,12 @@ value caml_interprete(code_t prog, asize_t prog_size) so no need to go through caml_initialize. */ *--sp = accu; p = &Field(accu, 0); - *p++ = (value) (pc + pc[0]); + *p++ = Val_bytecode (pc + pc[0]); *p++ = Make_closinfo(0, envofs); for (i = 1; i < nfuncs; i++) { - *p++ = Make_header(i * 3, Infix_tag, Caml_white); /* color irrelevant */ + *p++ = Make_header(i * 3, Infix_tag, 0); /* color irrelevant */ *--sp = (value) p; - *p++ = (value) (pc + pc[i]); + *p++ = Val_bytecode (pc + pc[i]); envofs -= 3; *p++ = Make_closinfo(0, envofs); } @@ -636,7 +695,7 @@ value caml_interprete(code_t prog, asize_t prog_size) *--sp = accu; /* Fallthrough */ Instruct(GETGLOBAL): - accu = Field(caml_global_data, *pc); + accu = Field(caml_read_root(caml_global_data), *pc); pc++; Next; @@ -644,15 +703,15 @@ value caml_interprete(code_t prog, asize_t prog_size) *--sp = accu; /* Fallthrough */ Instruct(GETGLOBALFIELD): { - accu = Field(caml_global_data, *pc); + accu = Field(caml_read_root(caml_global_data), *pc); pc++; - accu = Field(accu, *pc); + Accu_field(*pc); pc++; Next; } Instruct(SETGLOBAL): - caml_modify(&Field(caml_global_data, *pc), accu); + caml_modify_field(caml_read_root(caml_global_data), *pc, accu); accu = Val_unit; pc++; Next; @@ -677,13 +736,20 @@ value caml_interprete(code_t prog, asize_t prog_size) mlsize_t i; value block; if (wosize <= Max_young_wosize) { - Alloc_small(block, wosize, tag); - Field(block, 0) = accu; - for (i = 1; i < wosize; i++) Field(block, i) = *sp++; + Alloc_small(block, wosize, tag, Enter_gc); + Init_field(block, 0, accu); + for (i = 1; i < wosize; i++) Init_field(block, i, *sp++); } else { block = caml_alloc_shr(wosize, tag); - caml_initialize(&Field(block, 0), accu); - for (i = 1; i < wosize; i++) caml_initialize(&Field(block, i), *sp++); + Setup_for_c_call; + caml_initialize_field(block, 0, accu); + Restore_after_c_call; + for (i = 1; i < wosize; i++) { + value v = *sp++; + Setup_for_c_call; + caml_initialize_field(block, i, v); + Restore_after_c_call; + } } accu = block; Next; @@ -691,17 +757,17 @@ value caml_interprete(code_t prog, asize_t prog_size) Instruct(MAKEBLOCK1): { tag_t tag = *pc++; value block; - Alloc_small(block, 1, tag); - Field(block, 0) = accu; + Alloc_small(block, 1, tag, Enter_gc); + Init_field(block, 0, accu); accu = block; Next; } Instruct(MAKEBLOCK2): { tag_t tag = *pc++; value block; - Alloc_small(block, 2, tag); - Field(block, 0) = accu; - Field(block, 1) = sp[0]; + Alloc_small(block, 2, tag, Enter_gc); + Init_field(block, 0, accu); + Init_field(block, 1, sp[0]); sp += 1; accu = block; Next; @@ -709,10 +775,10 @@ value caml_interprete(code_t prog, asize_t prog_size) Instruct(MAKEBLOCK3): { tag_t tag = *pc++; value block; - Alloc_small(block, 3, tag); - Field(block, 0) = accu; - Field(block, 1) = sp[0]; - Field(block, 2) = sp[1]; + Alloc_small(block, 3, tag, Enter_gc); + Init_field(block, 0, accu); + Init_field(block, 1, sp[0]); + Init_field(block, 2, sp[1]); sp += 2; accu = block; Next; @@ -722,9 +788,11 @@ value caml_interprete(code_t prog, asize_t prog_size) mlsize_t i; value block; if (size <= Max_young_wosize / Double_wosize) { - Alloc_small(block, size * Double_wosize, Double_array_tag); + Alloc_small(block, size * Double_wosize, Double_array_tag, Enter_gc); } else { + Setup_for_gc; block = caml_alloc_shr(size * Double_wosize, Double_array_tag); + Restore_after_gc; } Store_double_flat_field(block, 0, Double_val(accu)); for (i = 1; i < size; i++){ @@ -747,31 +815,41 @@ value caml_interprete(code_t prog, asize_t prog_size) accu = Field(accu, 3); Next; Instruct(GETFIELD): accu = Field(accu, *pc); pc++; Next; + Instruct(GETMUTABLEFIELD0): + Accu_field(0); Next; + Instruct(GETMUTABLEFIELD1): + Accu_field(1); Next; + Instruct(GETMUTABLEFIELD2): + Accu_field(2); Next; + Instruct(GETMUTABLEFIELD3): + Accu_field(3); Next; + Instruct(GETMUTABLEFIELD): + Accu_field(*pc); pc++; Next; Instruct(GETFLOATFIELD): { double d = Double_flat_field(accu, *pc++); - Alloc_small(accu, Double_wosize, Double_tag); + Alloc_small(accu, Double_wosize, Double_tag, Enter_gc); Store_double_val(accu, d); Next; } Instruct(SETFIELD0): - caml_modify(&Field(accu, 0), *sp++); + caml_modify_field(accu, 0, *sp++); accu = Val_unit; Next; Instruct(SETFIELD1): - caml_modify(&Field(accu, 1), *sp++); + caml_modify_field(accu, 1, *sp++); accu = Val_unit; Next; Instruct(SETFIELD2): - caml_modify(&Field(accu, 2), *sp++); + caml_modify_field(accu, 2, *sp++); accu = Val_unit; Next; Instruct(SETFIELD3): - caml_modify(&Field(accu, 3), *sp++); + caml_modify_field(accu, 3, *sp++); accu = Val_unit; Next; Instruct(SETFIELD): - caml_modify(&Field(accu, *pc), *sp++); + caml_modify_field(accu, *pc, *sp++); accu = Val_unit; pc++; Next; @@ -794,11 +872,11 @@ value caml_interprete(code_t prog, asize_t prog_size) Next; } Instruct(GETVECTITEM): - accu = Field(accu, Long_val(sp[0])); + Accu_field(Long_val(sp[0])); sp += 1; Next; Instruct(SETVECTITEM): - caml_modify(&Field(accu, Long_val(sp[0])), sp[1]); + caml_modify_field(accu, Long_val(sp[0]), sp[1]); accu = Val_unit; sp += 2; Next; @@ -847,23 +925,23 @@ value caml_interprete(code_t prog, asize_t prog_size) Instruct(PUSHTRAP): sp -= 4; - Trap_pc(sp) = pc + *pc; - Trap_link_offset(sp) = Val_long(Caml_state->trapsp - sp); + Trap_pc(sp) = Val_pc(pc + *pc); + Trap_link(sp) = Val_long(domain_state->trap_sp_off); sp[2] = env; sp[3] = Val_long(extra_args); - Caml_state->trapsp = sp; + domain_state->trap_sp_off = sp - Stack_high(domain_state->current_stack); pc++; Next; Instruct(POPTRAP): - if (caml_something_to_do) { + if (Caml_check_gc_interrupt(domain_state)) { /* We must check here so that if a signal is pending and its handler triggers an exception, the exception is trapped by the current try...with, not the enclosing one. */ pc--; /* restart the POPTRAP after processing the signal */ - goto process_actions; + goto process_signal; } - Caml_state->trapsp = sp + Long_val(Trap_link_offset(sp)); + domain_state->trap_sp_off = Long_val(Trap_link(sp)); sp += 4; Next; @@ -873,54 +951,80 @@ value caml_interprete(code_t prog, asize_t prog_size) Instruct(RERAISE): Check_trap_barrier; - if (Caml_state->backtrace_active) { - *--sp = (value)(pc - 1); + if (domain_state->backtrace_active) { + *--sp = Val_pc(pc - 1); caml_stash_backtrace(accu, sp, 1); } goto raise_notrace; Instruct(RAISE): + raise_exception: Check_trap_barrier; - if (Caml_state->backtrace_active) { - *--sp = (value)(pc - 1); + if (domain_state->backtrace_active) { + *--sp = Val_pc(pc - 1); caml_stash_backtrace(accu, sp, 0); } raise_notrace: - if ((char *) Caml_state->trapsp - >= (char *) Caml_state->stack_high - initial_sp_offset) { - Caml_state->external_raise = initial_external_raise; - Caml_state->extern_sp = (value *) ((char *) Caml_state->stack_high - - initial_sp_offset); - caml_callback_depth--; - return Make_exception_result(accu); + if (domain_state->trap_sp_off > 0) { + if (Stack_parent(domain_state->current_stack) == NULL) { + domain_state->external_raise = initial_external_raise; + domain_state->trap_sp_off = initial_trap_sp_off; + domain_state->current_stack->sp = + Stack_high(domain_state->current_stack) - initial_stack_words ; + caml_decr_callback_depth (); + return Make_exception_result(accu); + } else { + struct stack_info* old_stack = domain_state->current_stack; + struct stack_info* parent_stack = Stack_parent(old_stack); + value hexn = Stack_handle_exception(old_stack); + old_stack->sp = sp; + domain_state->current_stack = parent_stack; + sp = domain_state->current_stack->sp; + caml_free_stack(old_stack); + + domain_state->trap_sp_off = Long_val(sp[0]); + extra_args = Long_val(sp[1]); + sp++; + sp[0] = accu; + + accu = hexn; + pc = Code_val(accu); + env = accu; + goto check_stacks; + } + } else { + sp = Stack_high(domain_state->current_stack) + domain_state->trap_sp_off; + pc = Pc_val(Trap_pc(sp)); + domain_state->trap_sp_off = Long_val(Trap_link(sp)); + env = sp[2]; + extra_args = Long_val(sp[3]); + sp += 4; } - sp = Caml_state->trapsp; - pc = Trap_pc(sp); - Caml_state->trapsp = sp + Long_val(Trap_link_offset(sp)); - env = sp[2]; - extra_args = Long_val(sp[3]); - sp += 4; Next; + + /* Stack checks */ check_stacks: - if (sp < Caml_state->stack_threshold) { - Caml_state->extern_sp = sp; - caml_realloc_stack(Stack_threshold / sizeof(value)); - sp = Caml_state->extern_sp; + if (sp < Stack_threshold_ptr(domain_state->current_stack)) { + domain_state->current_stack->sp = sp; + if (!caml_try_realloc_stack(Stack_threshold / sizeof(value))) { + Setup_for_c_call; caml_raise_stack_overflow(); + } + sp = domain_state->current_stack->sp; } /* Fall through CHECK_SIGNALS */ /* Signal handling */ Instruct(CHECK_SIGNALS): /* accu not preserved */ - if (caml_something_to_do) goto process_actions; + if (Caml_check_gc_interrupt(domain_state)) goto process_signal; Next; - process_actions: + process_signal: Setup_for_event; - caml_process_pending_actions(); + caml_handle_gc_interrupt(); Restore_after_event; Next; @@ -1069,8 +1173,11 @@ value caml_interprete(code_t prog, asize_t prog_size) accu += *pc << 1; pc++; Next; - Instruct(OFFSETREF): - Field(accu, 0) += *pc << 1; + Instruct(OFFSETREF): { + long n = Long_field(accu, 0); + n += *pc; + caml_modify_field(accu, 0, Val_long(n)); + } accu = Val_unit; pc++; Next; @@ -1080,10 +1187,8 @@ value caml_interprete(code_t prog, asize_t prog_size) /* Object-oriented operations */ -#define Lookup(obj, lab) Field (Field (obj, 0), Int_val(lab)) - Instruct(GETMETHOD): - accu = Lookup(sp[0], accu); + accu = Field (Field(sp[0], 0), Int_val(accu)); Next; #define CAML_METHOD_CACHE @@ -1103,11 +1208,11 @@ value caml_interprete(code_t prog, asize_t prog_size) *--sp = accu; accu = Val_int(*pc++); ofs = *pc & Field(meths,1); - if (*(value*)(((char*)&Field(meths,3)) + ofs) == accu) { + if (*(value*)(((char*)(Op_val(meths)+3)) + ofs) == accu) { #ifdef CAML_TEST_CACHE hits++; #endif - accu = *(value*)(((char*)&Field(meths,2)) + ofs); + accu = *(value*)(((char*)(Op_val(meths)+2)) + ofs); } else { @@ -1133,10 +1238,10 @@ value caml_interprete(code_t prog, asize_t prog_size) Instruct(GETDYNMET): { /* accu == tag, sp[0] == object, *pc == cache */ value meths = Field (sp[0], 0); - int li = 3, hi = Field(meths,0), mi; + int li = 3, hi = Field (meths,0), mi; while (li < hi) { mi = ((li+hi) >> 1) | 1; - if (accu < Field(meths,mi)) hi = mi-2; + if (accu < Field (meths,mi)) hi = mi-2; else li = mi; } accu = Field (meths, li-1); @@ -1146,9 +1251,10 @@ value caml_interprete(code_t prog, asize_t prog_size) /* Debugging and machine control */ Instruct(STOP): - Caml_state->external_raise = initial_external_raise; - Caml_state->extern_sp = sp; - caml_callback_depth--; + domain_state->external_raise = initial_external_raise; + domain_state->trap_sp_off = initial_trap_sp_off; + domain_state->current_stack->sp = sp; + caml_decr_callback_depth (); return accu; Instruct(EVENT): @@ -1165,6 +1271,126 @@ value caml_interprete(code_t prog, asize_t prog_size) Restore_after_debugger; Restart_curr_instr; +/* Context switching */ + + Instruct(RESUME): + resume_fn = sp[0]; + resume_arg = sp[1]; + sp -= 3; + sp[0] = Val_long(domain_state->trap_sp_off); + sp[1] = Val_long(0); + sp[2] = Val_pc(pc); + sp[3] = env; + sp[4] = Val_long(extra_args); + goto do_resume; + +do_resume: { + struct stack_info* stk = Ptr_val(accu); + if (stk == NULL) { + accu = Field(caml_read_root(caml_global_data), CONTINUATION_ALREADY_TAKEN_EXN); + goto raise_exception; + } + while (Stack_parent(stk) != NULL) stk = Stack_parent(stk); + Stack_parent(stk) = Caml_state->current_stack; + + domain_state->current_stack->sp = sp; + domain_state->current_stack = Ptr_val(accu); + sp = domain_state->current_stack->sp; + + domain_state->trap_sp_off = Long_val(sp[0]); + sp[0] = resume_arg; + accu = resume_fn; + pc = Code_val(accu); + env = accu; + extra_args = 0; + goto check_stacks; + } + + Instruct(RESUMETERM): + resume_fn = sp[0]; + resume_arg = sp[1]; + sp = sp + *pc - 2; + sp[0] = Val_long(domain_state->trap_sp_off); + sp[1] = Val_long(extra_args); + goto do_resume; + + + Instruct(PERFORM): { + value cont; + struct stack_info* old_stack = domain_state->current_stack; + struct stack_info* parent_stack = Stack_parent(old_stack); + + if (parent_stack == NULL) { + accu = Field(caml_read_root(caml_global_data), UNHANDLED_EXN); + goto raise_exception; + } + + Alloc_small(cont, 1, Cont_tag, Enter_gc); + + sp -= 4; + sp[0] = Val_long(domain_state->trap_sp_off); + sp[1] = Val_pc(pc); + sp[2] = env; + sp[3] = Val_long(extra_args); + + old_stack->sp = sp; + domain_state->current_stack = parent_stack; + sp = parent_stack->sp; + Stack_parent(old_stack) = NULL; + Init_field(cont, 0, Val_ptr(old_stack)); + + domain_state->trap_sp_off = Long_val(sp[0]); + extra_args = Long_val(sp[1]); + sp--; + sp[0] = accu; + sp[1] = cont; + sp[2] = Val_ptr(old_stack); + accu = Stack_handle_effect(old_stack); + pc = Code_val(accu); + env = accu; + extra_args += 2; + goto check_stacks; + } + + Instruct(REPERFORMTERM): { + value eff = accu; + value cont = sp[0]; + struct stack_info* cont_tail = Ptr_val(sp[1]); + struct stack_info* self = domain_state->current_stack; + struct stack_info* parent = Stack_parent(domain_state->current_stack); + + sp = sp + *pc - 2; + sp[0] = Val_long(domain_state->trap_sp_off); + sp[1] = Val_long(extra_args); + + if (parent == NULL) { + accu = caml_continuation_use(cont); + resume_fn = caml_read_root(raise_unhandled); + resume_arg = Field(caml_read_root(caml_global_data), UNHANDLED_EXN); + goto do_resume; + } + + self->sp = sp; + domain_state->current_stack = parent; + sp = parent->sp; + + CAMLassert(Stack_parent(cont_tail) == NULL); + Stack_parent(self) = NULL; + Stack_parent(cont_tail) = self; + + domain_state->trap_sp_off = Long_val(sp[0]); + extra_args = Long_val(sp[1]); + sp--; + sp[0] = eff; + sp[1] = cont; + sp[2] = Val_ptr(self); + accu = Stack_handle_effect(self); + pc = Code_val(accu); + env = accu; + extra_args += 2; + goto check_stacks; + } + #ifndef THREADED_CODE default: #if _MSC_VER >= 1200 diff --git a/runtime/ints.c b/runtime/ints.c index c9584e4aba..eb539b94f4 100644 --- a/runtime/ints.c +++ b/runtime/ints.c @@ -214,7 +214,7 @@ static uintnat int32_deserialize(void * dst) static const struct custom_fixed_length int32_length = { 4, 4 }; -CAMLexport struct custom_operations caml_int32_ops = { +CAMLexport const struct custom_operations caml_int32_ops = { "_i", custom_finalize_default, int32_cmp, @@ -413,7 +413,7 @@ static uintnat int64_deserialize(void * dst) static const struct custom_fixed_length int64_length = { 8, 8 }; -CAMLexport struct custom_operations caml_int64_ops = { +CAMLexport const struct custom_operations caml_int64_ops = { "_j", custom_finalize_default, int64_cmp, @@ -710,7 +710,7 @@ static uintnat nativeint_deserialize(void * dst) } static const struct custom_fixed_length nativeint_length = { 4, 8 }; -CAMLexport struct custom_operations caml_nativeint_ops = { +CAMLexport const struct custom_operations caml_nativeint_ops = { "_n", custom_finalize_default, nativeint_cmp, diff --git a/runtime/io.c b/runtime/io.c index 1db7ef0f7e..0bea59abfe 100644 --- a/runtime/io.c +++ b/runtime/io.c @@ -52,14 +52,6 @@ #define lseek _lseeki64 #endif - -/* Hooks for locking channels */ - -CAMLexport void (*caml_channel_mutex_free) (struct channel *) = NULL; -CAMLexport void (*caml_channel_mutex_lock) (struct channel *) = NULL; -CAMLexport void (*caml_channel_mutex_unlock) (struct channel *) = NULL; -CAMLexport void (*caml_channel_mutex_unlock_exn) (void) = NULL; - /* List of opened channels */ CAMLexport struct channel * caml_all_opened_channels = NULL; @@ -80,7 +72,7 @@ CAMLexport struct channel * caml_open_descriptor_in(int fd) caml_leave_blocking_section(); channel->curr = channel->max = channel->buff; channel->end = channel->buff + IO_BUFFER_SIZE; - channel->mutex = NULL; + caml_plat_mutex_init(&channel->mutex); channel->revealed = 0; channel->old_revealed = 0; channel->refcount = 0; @@ -120,7 +112,7 @@ CAMLexport void caml_close_channel(struct channel *channel) { close(channel->fd); if (channel->refcount > 0) return; - if (caml_channel_mutex_free != NULL) (*caml_channel_mutex_free)(channel); + caml_plat_mutex_free(&channel->mutex); unlink_channel(channel); caml_stat_free(channel->name); caml_stat_free(channel); @@ -402,6 +394,9 @@ CAMLexport void caml_finalize_channel(value vchan) struct channel * chan = Channel(vchan); if ((chan->flags & CHANNEL_FLAG_MANAGED_BY_GC) == 0) return; if (--chan->refcount > 0) return; + caml_plat_mutex_free(&chan->mutex); + /* TODO KC: See commented out section */ +#if 0 if (caml_channel_mutex_free != NULL) (*caml_channel_mutex_free)(chan); if (chan->fd != -1 && chan->name && caml_runtime_warnings_active()) @@ -428,10 +423,10 @@ CAMLexport void caml_finalize_channel(value vchan) "[ocaml] (moreover, it has unflushed data)\n" ); } else { - unlink_channel(chan); - caml_stat_free(chan->name); - caml_stat_free(chan); - } +#endif + unlink_channel(chan); + caml_stat_free(chan->name); + caml_stat_free(chan); } static int compare_channel(value vchan1, value vchan2) @@ -446,7 +441,7 @@ static intnat hash_channel(value vchan) return (intnat) (Channel(vchan)); } -static struct custom_operations channel_operations = { +static const struct custom_operations channel_operations = { "_chan", caml_finalize_channel, compare_channel, @@ -607,9 +602,9 @@ CAMLprim value caml_ml_flush(value vchannel) struct channel * channel = Channel(vchannel); if (channel->fd == -1) CAMLreturn(Val_unit); - Lock(channel); - caml_flush(channel); - Unlock(channel); + With_mutex(&channel->mutex, { + caml_flush(channel); + } ); CAMLreturn (Val_unit); } @@ -618,9 +613,9 @@ CAMLprim value caml_ml_output_char(value vchannel, value ch) CAMLparam2 (vchannel, ch); struct channel * channel = Channel(vchannel); - Lock(channel); - caml_putch(channel, Long_val(ch)); - Unlock(channel); + With_mutex(&channel->mutex, { + caml_putch(channel, Long_val(ch)); + } ); CAMLreturn (Val_unit); } @@ -629,9 +624,9 @@ CAMLprim value caml_ml_output_int(value vchannel, value w) CAMLparam2 (vchannel, w); struct channel * channel = Channel(vchannel); - Lock(channel); - caml_putword(channel, (uint32_t) Long_val(w)); - Unlock(channel); + With_mutex(&channel->mutex, { + caml_putword(channel, Long_val(w)); + } ); CAMLreturn (Val_unit); } @@ -643,15 +638,13 @@ CAMLprim value caml_ml_output_bytes(value vchannel, value buff, value start, intnat pos = Long_val(start); intnat len = Long_val(length); - Lock(channel); - /* We cannot call caml_really_putblock here because buff may move - during caml_write_fd */ + With_mutex(&channel->mutex, { while (len > 0) { int written = caml_putblock(channel, &Byte(buff, pos), len); pos += written; len -= written; } - Unlock(channel); + } ); CAMLreturn (Val_unit); } @@ -666,9 +659,9 @@ CAMLprim value caml_ml_seek_out(value vchannel, value pos) CAMLparam2 (vchannel, pos); struct channel * channel = Channel(vchannel); - Lock(channel); - caml_seek_out(channel, Long_val(pos)); - Unlock(channel); + With_mutex(&channel->mutex, { + caml_seek_out(channel, Long_val(pos)); + } ); CAMLreturn (Val_unit); } @@ -677,9 +670,9 @@ CAMLprim value caml_ml_seek_out_64(value vchannel, value pos) CAMLparam2 (vchannel, pos); struct channel * channel = Channel(vchannel); - Lock(channel); - caml_seek_out(channel, File_offset_val(pos)); - Unlock(channel); + With_mutex(&channel->mutex, { + caml_seek_out(channel, File_offset_val(pos)); + } ); CAMLreturn (Val_unit); } @@ -701,9 +694,9 @@ CAMLprim value caml_ml_input_char(value vchannel) struct channel * channel = Channel(vchannel); unsigned char c; - Lock(channel); - c = caml_getch(channel); - Unlock(channel); + With_mutex(&channel->mutex, { + c = caml_getch(channel); + } ); CAMLreturn (Val_long(c)); } @@ -713,9 +706,9 @@ CAMLprim value caml_ml_input_int(value vchannel) struct channel * channel = Channel(vchannel); intnat i; - Lock(channel); - i = caml_getword(channel); - Unlock(channel); + With_mutex(&channel->mutex, { + i = caml_getword(channel); + } ); #ifdef ARCH_SIXTYFOUR i = (i << 32) >> 32; /* Force sign extension */ #endif @@ -730,30 +723,30 @@ CAMLprim value caml_ml_input(value vchannel, value buff, value vstart, intnat start, len; int n, avail, nread; - Lock(channel); - /* We cannot call caml_getblock here because buff may move during + With_mutex(&channel->mutex, { + /* We cannot call caml_getblock here because buff may move during caml_read_fd */ - start = Long_val(vstart); - len = Long_val(vlength); - n = len >= INT_MAX ? INT_MAX : (int) len; - avail = channel->max - channel->curr; - if (n <= avail) { - memmove(&Byte(buff, start), channel->curr, n); - channel->curr += n; - } else if (avail > 0) { - memmove(&Byte(buff, start), channel->curr, avail); - channel->curr += avail; - n = avail; - } else { + start = Long_val(vstart); + len = Long_val(vlength); + n = len >= INT_MAX ? INT_MAX : (int) len; + avail = channel->max - channel->curr; + if (n <= avail) { + memmove(&Byte(buff, start), channel->curr, n); + channel->curr += n; + } else if (avail > 0) { + memmove(&Byte(buff, start), channel->curr, avail); + channel->curr += avail; + n = avail; + } else { nread = caml_read_fd(channel->fd, channel->flags, channel->buff, - channel->end - channel->buff); - channel->offset += nread; - channel->max = channel->buff + nread; - if (n > nread) n = nread; - memmove(&Byte(buff, start), channel->buff, n); - channel->curr = channel->buff + n; - } - Unlock(channel); + channel->end - channel->buff); + channel->offset += nread; + channel->max = channel->buff + nread; + if (n > nread) n = nread; + memmove(&Byte(buff, start), channel->buff, n); + channel->curr = channel->buff + n; + } + } ); CAMLreturn (Val_long(n)); } @@ -762,9 +755,9 @@ CAMLprim value caml_ml_seek_in(value vchannel, value pos) CAMLparam2 (vchannel, pos); struct channel * channel = Channel(vchannel); - Lock(channel); - caml_seek_in(channel, Long_val(pos)); - Unlock(channel); + With_mutex(&channel->mutex, { + caml_seek_in(channel, Long_val(pos)); + } ); CAMLreturn (Val_unit); } @@ -773,9 +766,9 @@ CAMLprim value caml_ml_seek_in_64(value vchannel, value pos) CAMLparam2 (vchannel, pos); struct channel * channel = Channel(vchannel); - Lock(channel); - caml_seek_in(channel, File_offset_val(pos)); - Unlock(channel); + With_mutex(&channel->mutex, { + caml_seek_in(channel, File_offset_val(pos)); + } ); CAMLreturn (Val_unit); } @@ -797,9 +790,9 @@ CAMLprim value caml_ml_input_scan_line(value vchannel) struct channel * channel = Channel(vchannel); intnat res; - Lock(channel); - res = caml_input_scan_line(channel); - Unlock(channel); + With_mutex(&channel->mutex, { + res = caml_input_scan_line(channel); + } ); CAMLreturn (Val_long(res)); } diff --git a/runtime/lexing.c b/runtime/lexing.c index b104990425..e2733614d8 100644 --- a/runtime/lexing.c +++ b/runtime/lexing.c @@ -19,7 +19,7 @@ #include "caml/fail.h" #include "caml/mlvalues.h" -#include "caml/stacks.h" +#include "caml/fiber.h" struct lexer_buffer { value refill_buff; @@ -130,10 +130,10 @@ static void run_mem(char *pc, value mem, value curr_pos) { src = *pc++ ; if (src == 0xff) { /* fprintf(stderr,"[%hhu] <- %d\n",dst,Int_val(curr_pos)) ;*/ - Field(mem,dst) = curr_pos ; + Store_field(mem,dst,curr_pos); } else { /* fprintf(stderr,"[%hhu] <- [%hhu]\n",dst,src) ; */ - Field(mem,dst) = Field(mem,src) ; + Store_field(mem,dst,Val_long(Long_field(mem, src))); } } } @@ -148,10 +148,10 @@ static void run_tag(char *pc, value mem) { src = *pc++ ; if (src == 0xff) { /* fprintf(stderr,"[%hhu] <- -1\n",dst) ; */ - Field(mem,dst) = Val_int(-1) ; + Store_field(mem,dst,Val_int(-1)); } else { /* fprintf(stderr,"[%hhu] <- [%hhu]\n",dst,src) ; */ - Field(mem,dst) = Field(mem,src) ; + Store_field(mem,dst, Val_long(Long_field(mem, src))); } } } diff --git a/runtime/major_gc.c b/runtime/major_gc.c index d08d8f9362..3abdf23739 100644 --- a/runtime/major_gc.c +++ b/runtime/major_gc.c @@ -15,938 +15,1502 @@ #define CAML_INTERNALS -#include <limits.h> +#include <stdlib.h> +#include <string.h> #include <math.h> -#include "caml/compact.h" -#include "caml/custom.h" +#include "caml/addrmap.h" #include "caml/config.h" +#include "caml/domain.h" +#include "caml/eventlog.h" #include "caml/fail.h" +#include "caml/fiber.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/misc.h" +#include "caml/globroots.h" +#include "caml/memory.h" #include "caml/mlvalues.h" +#include "caml/platform.h" #include "caml/roots.h" -#include "caml/signals.h" +#include "caml/shared_heap.h" +#include "caml/startup_aux.h" #include "caml/weak.h" -#include "caml/memprof.h" -#include "caml/eventlog.h" +#include "caml/skiplist.h" + +/* NB the MARK_STACK_INIT_SIZE must be larger than the number of objects + that can be in a pool, see POOL_WSIZE */ +#define MARK_STACK_INIT_SIZE (1 << 12) +#define INITIAL_POOLS_TO_RESCAN_LEN 4 + +typedef struct { + value block; + uintnat offset; +} mark_entry; + +struct mark_stack { + mark_entry* stack; + uintnat count; + uintnat size; +}; + +uintnat caml_percent_free = Percent_free_def; -#ifdef _MSC_VER -Caml_inline double fmin(double a, double b) { - return (a < b) ? a : b; +/* This variable is only written with the world stopped, + so it need not be atomic */ +uintnat caml_major_cycles_completed = 0; + +static atomic_uintnat num_domains_to_sweep; +static atomic_uintnat num_domains_to_mark; +static atomic_uintnat num_domains_to_ephe_sweep; +static atomic_uintnat num_domains_to_final_update_first; +static atomic_uintnat num_domains_to_final_update_last; + +static atomic_uintnat terminated_domains_allocated_words; + +enum global_roots_status{ + WORK_UNSTARTED, + WORK_STARTED +}; +static atomic_uintnat domain_global_roots_started; + +gc_phase_t caml_gc_phase; + +uintnat caml_get_num_domains_to_mark () { + return atomic_load_acq(&num_domains_to_mark); } -#endif -uintnat caml_percent_free; -uintnat caml_major_heap_increment; -CAMLexport char *caml_heap_start; -char *caml_gc_sweep_hp; -int caml_gc_phase; /* always Phase_mark, Pase_clean, - Phase_sweep, or Phase_idle */ -static value *gray_vals; -static value *gray_vals_cur, *gray_vals_end; -static asize_t gray_vals_size; -static int heap_is_pure; /* The heap is pure if the only gray objects - below [markhp] are also in [gray_vals]. */ -uintnat caml_allocated_words; -uintnat caml_dependent_size, caml_dependent_allocated; -double caml_extra_heap_resources; -uintnat caml_fl_wsz_at_phase_change = 0; - -extern char *caml_fl_merge; /* Defined in freelist.c. */ - -static char *markhp, *chunk, *limit; -static double p_backlog = 0.0; /* backlog for the gc speedup parameter */ - -int caml_gc_subphase; /* Subphase_{mark_roots,mark_main,mark_final} */ - -/** - Ephemerons: - During mark phase the list caml_ephe_list_head of ephemerons - is iterated by different pointers that follow the invariants: - caml_ephe_list_head ->* ephes_checked_if_pure ->* ephes_to_check ->* null - | | | - (1) (2) (3) - - At the start of mark phase, (1) and (2) are empty. - - In mark phase: - - the ephemerons in (1) have a data alive or none - (nb: new ephemerons are added in this part by weak.c) - - the ephemerons in (2) have at least a white key or are white - if ephe_list_pure is true, otherwise they are in an unknown state and - must be checked again. - - the ephemerons in (3) are in an unknown state and must be checked - - At the end of mark phase, (3) is empty and ephe_list_pure is true. - The ephemeron in (1) and (2) will be cleaned (white keys and data - replaced by none or the ephemeron is removed from the list if it is white) - in clean phase. - - In clean phase: - caml_ephe_list_head ->* ephes_to_check ->* null - | | - (1) (3) - - In clean phase, (2) is not used, ephes_to_check is initialized at - caml_ephe_list_head: - - the ephemerons in (1) are clean. - - the ephemerons in (3) should be cleaned or removed if white. - - */ -static int ephe_list_pure; -/** The ephemerons is pure if since the start of its iteration - no value have been darken. */ -static value *ephes_checked_if_pure; -static value *ephes_to_check; - -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; +extern value caml_ephe_none; /* See weak.c */ + +struct ephe_cycle_info_t { + atomic_uintnat num_domains_todo; + /* Number of domains that need to scan their ephemerons in the current major + * GC cycle. This field is decremented when ephe_info->todo list at a domain + * becomes empty. */ + atomic_uintnat ephe_cycle; + /* Ephemeron cycle count */ + atomic_uintnat num_domains_done; + /* Number of domains that have marked their ephemerons in the current + * ephemeron cycle. */ +} ephe_cycle_info; + /* In the first major cycle, there is no ephemeron marking to be done. */ + +/* ephe_cycle_info is always updated with the critical section protected by + * ephe_lock or in the global barrier. However, the fields may be read without + * the lock. */ +static caml_plat_mutex ephe_lock = CAML_PLAT_MUTEX_INITIALIZER; + +static void update_ephe_info_for_marking_done () +{ + caml_plat_lock(&ephe_lock); + atomic_fetch_add(&ephe_cycle_info.ephe_cycle, +1); + atomic_store(&ephe_cycle_info.num_domains_done, 0); + caml_plat_unlock(&ephe_lock); +} -#ifdef DEBUG -static unsigned long major_gc_counter = 0; -#endif +void caml_ephe_todo_list_emptied () +{ + caml_plat_lock(&ephe_lock); + atomic_fetch_add(&ephe_cycle_info.num_domains_todo, -1); + caml_plat_unlock(&ephe_lock); + atomic_fetch_add_verify_ge0(&num_domains_to_ephe_sweep, -1); +} + +void caml_ephe_todo_list_stolen () +{ + caml_plat_lock(&ephe_lock); + atomic_fetch_add(&ephe_cycle_info.num_domains_todo, +1); + caml_plat_unlock(&ephe_lock); + atomic_fetch_add(&num_domains_to_ephe_sweep, 1); +} + +/* Record that ephemeron marking was done for the given ephemeron cycle. */ +static void record_ephe_marking_done (uintnat ephe_cycle) +{ + CAMLassert (ephe_cycle <= atomic_load_acq(&ephe_cycle_info.ephe_cycle)); + CAMLassert (Caml_state->marking_done); + + if (ephe_cycle < atomic_load_acq(&ephe_cycle_info.ephe_cycle)) + return; + + caml_plat_lock(&ephe_lock); + if (ephe_cycle == atomic_load(&ephe_cycle_info.ephe_cycle)) { + Caml_state->ephe_info->cycle = ephe_cycle; + atomic_fetch_add(&ephe_cycle_info.num_domains_done, +1); + } + caml_plat_unlock(&ephe_lock); +} + +/* These are biased data structures left over from terminating domains. */ +static struct { + value ephe_list_todo; + value ephe_list_live; + struct caml_final_info *final_info; +} orph_structs = {0, 0, 0}; + +static caml_plat_mutex orphaned_lock = CAML_PLAT_MUTEX_INITIALIZER; + +void caml_add_orphaned_finalisers (struct caml_final_info* f) +{ + CAMLassert (caml_gc_phase == Phase_sweep_and_mark_main); + CAMLassert (!f->updated_first); + CAMLassert (!f->updated_last); + + caml_plat_lock(&orphaned_lock); + f->next = orph_structs.final_info; + orph_structs.final_info = f; + caml_plat_unlock(&orphaned_lock); + +} + +/* Called by terminating domain from handover_finalisers */ +void caml_final_domain_terminate (caml_domain_state *domain_state) +{ + struct caml_final_info *f = domain_state->final_info; + if(!f->updated_first) { + atomic_fetch_add_verify_ge0(&num_domains_to_final_update_first, -1); + f->updated_first = 1; + } + if(!f->updated_last) { + atomic_fetch_add_verify_ge0(&num_domains_to_final_update_last, -1); + f->updated_last = 1; + } +} + +static int no_orphaned_work () +{ + return + orph_structs.ephe_list_todo == 0 && + orph_structs.ephe_list_live == 0 && + orph_structs.final_info == NULL; +} + +void caml_orphan_allocated_words() { + atomic_fetch_add(&terminated_domains_allocated_words, Caml_state->allocated_words); +} + +static inline value ephe_list_tail(value e) +{ + value last = 0; + while (e != 0) { + CAMLassert (Tag_val(e) == Abstract_tag); + last = e; + e = Ephe_link(e); + } + return last; +} -void (*caml_major_gc_hook)(void) = NULL; - -static void realloc_gray_vals (void) -{ - value *new; - - CAMLassert (gray_vals_cur == gray_vals_end); - if (gray_vals_size < Caml_state->stat_heap_wsz / 32){ - caml_gc_message (0x08, "Growing gray_vals to %" - ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n", - (intnat) gray_vals_size * sizeof (value) / 512); - new = (value *) caml_stat_resize_noexc ((char *) gray_vals, - 2 * gray_vals_size * - sizeof (value)); - if (new == NULL){ - caml_gc_message (0x08, "No room for growing gray_vals\n"); - gray_vals_cur = gray_vals; - heap_is_pure = 0; - }else{ - gray_vals = new; - gray_vals_cur = gray_vals + gray_vals_size; - gray_vals_size *= 2; - gray_vals_end = gray_vals + gray_vals_size; +void caml_add_to_orphaned_ephe_list(struct caml_ephe_info* ephe_info) +{ + value todo_head = ephe_info->todo; + value live_head = ephe_info->live; + + caml_plat_lock(&orphaned_lock); + if (todo_head) { + value todo_tail = ephe_list_tail(todo_head); + CAMLassert(Ephe_link(todo_tail) == 0); + Ephe_link(todo_tail) = orph_structs.ephe_list_todo; + orph_structs.ephe_list_todo = todo_head; + } + if (live_head) { + value live_tail = ephe_list_tail(live_head); + CAMLassert(Ephe_link(live_tail) == 0); + Ephe_link(live_tail) = orph_structs.ephe_list_live; + orph_structs.ephe_list_live = live_head; + } + caml_plat_unlock(&orphaned_lock); +} + +void caml_adopt_orphaned_work () +{ + caml_domain_state* domain_state = Caml_state; + value last; + struct caml_final_info *f, *myf, *temp; + + if (no_orphaned_work() || caml_domain_is_terminating()) + return; + + caml_plat_lock(&orphaned_lock); + + if (orph_structs.ephe_list_live) { + last = ephe_list_tail(orph_structs.ephe_list_live); + Ephe_link(last) = domain_state->ephe_info->live; + domain_state->ephe_info->live = orph_structs.ephe_list_live; + orph_structs.ephe_list_live = 0; + } + + if (orph_structs.ephe_list_todo) { + if (domain_state->ephe_info->todo == 0) { + caml_ephe_todo_list_stolen(); } - }else{ - gray_vals_cur = gray_vals + gray_vals_size / 2; - heap_is_pure = 0; + last = ephe_list_tail(orph_structs.ephe_list_todo); + Ephe_link(last) = domain_state->ephe_info->todo; + domain_state->ephe_info->todo = orph_structs.ephe_list_todo; + orph_structs.ephe_list_todo = 0; } + + f = orph_structs.final_info; + myf = domain_state->final_info; + while (f != NULL) { + CAMLassert (!f->updated_first); + CAMLassert (!f->updated_last); + CAMLassert (!myf->updated_first); + CAMLassert (!myf->updated_last); + CAMLassert (caml_gc_phase == Phase_sweep_and_mark_main); + if (f->todo_head) { + myf->todo_tail->next = f->todo_head; + myf->todo_tail = f->todo_tail; + } + if (f->first.young > 0) { + caml_final_merge_finalisable (&f->first, &myf->first); + } + if (f->last.young > 0) { + caml_final_merge_finalisable (&f->last, &myf->last); + } + temp = f; + f = f->next; + caml_stat_free (temp); + } + orph_structs.final_info = NULL; + caml_plat_unlock(&orphaned_lock); } -void caml_darken (value v, value *p /* not used */) +#define BUFFER_SIZE 64 + +struct buf_list_t { + double buffer[BUFFER_SIZE]; + struct buf_list_t *next; +}; + +static struct { + intnat heap_words_last_cycle; + intnat not_garbage_words_last_cycle; + int index; + struct buf_list_t *l; + } caml_stat_space_overhead = {0, 0, 0, NULL}; + +double caml_mean_space_overhead () { -#ifdef NO_NAKED_POINTERS - if (Is_block (v) && !Is_young (v)) { -#else - if (Is_block (v) && Is_in_heap (v)) { -#endif - header_t h = Hd_val (v); - tag_t t = Tag_hd (h); - if (t == Infix_tag){ - v -= Infix_offset_val(v); - h = Hd_val (v); - t = Tag_hd (h); - } -#ifdef NO_NAKED_POINTERS - /* We insist that naked pointers to outside the heap point to things that - look like values with headers coloured black. This is always - strictly necessary because the compactor relies on it. */ - CAMLassert (Is_in_heap (v) || Is_black_hd (h)); -#endif - CAMLassert (!Is_blue_hd (h)); - if (Is_white_hd (h)){ - ephe_list_pure = 0; - if (t < No_scan_tag){ - Hd_val (v) = Grayhd_hd (h); - *gray_vals_cur++ = v; - if (gray_vals_cur >= gray_vals_end) realloc_gray_vals (); - }else{ - Hd_val (v) = Blackhd_hd (h); + int index = caml_stat_space_overhead.index; + struct buf_list_t *t, *l = caml_stat_space_overhead.l; + /* Use Welford's online algorithm for calculating running variance to remove + * outliers from mean calculation. */ + double mean = 0.0, m2 = 0.0, stddev = 0.0, v; + double delta, delta2; + intnat count = 0; + + while (l) { + while (index > 0) { + v = l->buffer[--index]; + if (count > 5 && (v < mean - 3 * stddev || v > mean + 3 * stddev)) { + continue; } + count++; + delta = v - mean; + mean = mean + delta / count; + delta2 = v - mean; + m2 = m2 + delta * delta2; + stddev = sqrt (m2 / count); } + t = l; + l = l->next; + caml_stat_free(t); + index = BUFFER_SIZE; } + return mean; } -static void start_cycle (void) -{ - CAMLassert (caml_gc_phase == Phase_idle); - CAMLassert (gray_vals_cur == gray_vals); - caml_gc_message (0x01, "Starting new major GC cycle\n"); - caml_darken_all_roots_start (); - caml_gc_phase = Phase_mark; - caml_gc_subphase = Subphase_mark_roots; - markhp = NULL; - ephe_list_pure = 1; - ephes_checked_if_pure = &caml_ephe_list_head; - ephes_to_check = &caml_ephe_list_head; +static void update_major_slice_work() { + double p, heap_words; + intnat computed_work, limit; + caml_domain_state *dom_st = Caml_state; + uintnat heap_size, heap_sweep_words, saved_terminated_words; + /* + Free memory at the start of the GC cycle (garbage + free list) (assumed): + FM = heap_words * caml_percent_free + / (100 + caml_percent_free) + + Assuming steady state and enforcing a constant allocation rate, then + FM is divided in 2/3 for garbage and 1/3 for free list. + G = 2 * FM / 3 + G is also the amount of memory that will be used during this cycle + (still assuming steady state). + + Proportion of G consumed since the previous slice: + PH = dom_st->allocated_words / G + = dom_st->allocated_words * 3 * (100 + caml_percent_free) + / (2 * heap_words * caml_percent_free) + Proportion of extra-heap resources consumed since the previous slice: + PE = caml_extra_heap_resources + Proportion of total work to do in this slice: + P = max (PH, PE) + Amount of marking work for the GC cycle: + MW = heap_words * 100 / (100 + caml_percent_free) + Amount of sweeping work for the GC cycle: + SW = heap_sweep_words + Amount of total work for the GC cycle: + TW = MW + SW = heap_words * 100 / (100 + caml_percent_free) + heap_sweep_words + + Amount of time to spend on this slice: + T = P * TT + + Since we must do TW amount of work in TT time, the amount of work done + for this slice is: + S = P * TW + */ + heap_size = caml_heap_size(dom_st->shared_heap); + heap_words = (double)Wsize_bsize(heap_size); + heap_sweep_words = heap_words; + + saved_terminated_words = terminated_domains_allocated_words; + if( saved_terminated_words > 0 ) { + while(!atomic_compare_exchange_strong(&terminated_domains_allocated_words, &saved_terminated_words, 0)); + } + + p = (double) (saved_terminated_words + dom_st->allocated_words) * 3.0 * (100 + caml_percent_free) / heap_words / caml_percent_free / 2.0; + + if (p > 0.3) p = 0.3; + + computed_work = (intnat) (p * (heap_sweep_words + (heap_words * 100 / (100 + caml_percent_free)))); + + /* accumulate work */ + dom_st->major_work_computed += computed_work; + dom_st->major_work_todo += computed_work; + + /* cap accumulated work todo to p = 0.3 */ + limit = (intnat)(0.3 * (heap_sweep_words + (heap_words * 100 / (100 + caml_percent_free)))); + if (dom_st->major_work_todo > limit) + { + dom_st->major_work_todo = limit; + } + + caml_gc_message (0x40, "heap_words = %" + ARCH_INTNAT_PRINTF_FORMAT "u\n", + (uintnat)heap_words); + caml_gc_message (0x40, "allocated_words = %" + ARCH_INTNAT_PRINTF_FORMAT "u\n", + dom_st->allocated_words); + caml_gc_message (0x40, "raw work-to-do = %" + ARCH_INTNAT_PRINTF_FORMAT "uu\n", + (uintnat) (p * 1000000)); + caml_gc_message (0x40, "computed work = %" + ARCH_INTNAT_PRINTF_FORMAT "d words\n", + computed_work); + + caml_gc_log("Updated major work: [%c] " + " %"ARCH_INTNAT_PRINTF_FORMAT "u heap_words, " + " %"ARCH_INTNAT_PRINTF_FORMAT "u allocated, " + " %"ARCH_INTNAT_PRINTF_FORMAT "d computed_work, " + " %"ARCH_INTNAT_PRINTF_FORMAT "d work_computed, " + " %"ARCH_INTNAT_PRINTF_FORMAT "d work_todo, " + " %"ARCH_INTNAT_PRINTF_FORMAT "u gc_clock", + caml_gc_phase_char(caml_gc_phase), + (uintnat)heap_words, dom_st->allocated_words, + computed_work, + dom_st->major_work_computed, + dom_st->major_work_todo, + (intnat)(dom_st->major_gc_clock*1000000)); + + dom_st->stat_major_words += dom_st->allocated_words; + dom_st->allocated_words = 0; +} + +static intnat get_major_slice_work(intnat howmuch) { + caml_domain_state *dom_st = Caml_state; + intnat computed_work; + + /* calculate how much work to do now */ + if (howmuch == AUTO_TRIGGERED_MAJOR_SLICE || + howmuch == GC_CALCULATE_MAJOR_SLICE) { + computed_work = (dom_st->major_work_todo > 0) + ? dom_st->major_work_todo + : 0; + } else { + /* forced or opportunistic GC slice with explicit quantity */ + computed_work = howmuch; + } + + /* TODO: do we want to do anything more complex or simplify the above? */ + + return computed_work; +} + +static void commit_major_slice_work(intnat words_done) { + caml_domain_state *dom_st = Caml_state; + intnat limit; + + dom_st->major_work_todo -= words_done; + + /* cap how far work todo can be in credit */ + limit = -2*Wsize_bsize(caml_heap_size(dom_st->shared_heap)); + if (dom_st->major_work_todo < limit) + { + dom_st->major_work_todo = limit; + } + + /* check clock to close a cycle if need be */ + if (dom_st->major_work_todo <= 0 + && dom_st->major_gc_clock >= 1.0) + { + caml_gc_log("Major GC slice complete: " + " %"ARCH_INTNAT_PRINTF_FORMAT "d words_done, " + " %"ARCH_INTNAT_PRINTF_FORMAT "d todo, " + " %"ARCH_INTNAT_PRINTF_FORMAT "d computed, " + " %"ARCH_INTNAT_PRINTF_FORMAT "u clock", + words_done, + dom_st->major_work_todo, + dom_st->major_work_computed, + (uintnat)(dom_st->major_gc_clock * 1000000) + ); + + /* we have caught up */ + while( dom_st->major_gc_clock >= 1.0 ) { + dom_st->major_gc_clock -= 1.; + } + + /* limit amount of work credit that can go into next cycle */ + limit = -2*dom_st->major_work_computed; + dom_st->major_work_todo = dom_st->major_work_todo < limit + ? limit + : dom_st->major_work_todo; + dom_st->major_work_computed = 0; + } +} + +static void mark_stack_prune(struct mark_stack* stk); +static struct pool* find_pool_to_rescan(); + + #ifdef DEBUG - ++ major_gc_counter; - caml_heap_check (); +#define Is_markable(v) (Is_block(v) && !Is_young(v) && v != Debug_free_major) +#else +#define Is_markable(v) (Is_block(v) && !Is_young(v)) #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; +static void realloc_mark_stack (struct mark_stack* stk) +{ + mark_entry* new; + uintnat mark_stack_bsize = stk->size * sizeof(mark_entry); + + caml_gc_log ("Growing mark stack to %"ARCH_INTNAT_PRINTF_FORMAT"uk bytes\n", + (intnat) mark_stack_bsize * 2 / 1024); + + new = (mark_entry*) caml_stat_resize_noexc ((char*) stk->stack, + 2 * mark_stack_bsize); + if (new != NULL) { + stk->stack = new; + stk->size *= 2; + return; + } + + caml_fatal_error("No room for growing mark stack.\n"); + /* TODO: re-enable mark stack prune when safe to remark a pool + from a foreign domain which is also allocating from that pool + */ + if (0) { + caml_gc_log ("Mark stack size is %"ARCH_INTNAT_PRINTF_FORMAT"u" + "bytes (> 32 * major heap size of this domain %" + ARCH_INTNAT_PRINTF_FORMAT"u bytes. Pruning..\n", + mark_stack_bsize, + caml_heap_size(Caml_state->shared_heap)); + mark_stack_prune(stk); + } +} -static void init_sweep_phase(void) +static void mark_stack_push(struct mark_stack* stk, value block, + uintnat offset, intnat* work) { - /* Phase_clean is done. */ - /* Initialise the sweep phase. */ - caml_gc_sweep_hp = caml_heap_start; - caml_fl_init_merge (); - caml_gc_phase = Phase_sweep; - chunk = caml_heap_start; - caml_gc_sweep_hp = chunk; - limit = chunk + Chunk_size (chunk); - caml_fl_wsz_at_phase_change = caml_fl_cur_wsz; - if (caml_major_gc_hook) (*caml_major_gc_hook)(); + value v; + int i, block_wsz = Wosize_val(block), end; + mark_entry* me; + + if (offset == 0 && Tag_val(block) == Closure_tag) { + /* Skip the code pointers and integers at beginning of closure; + start scanning at the first word of the environment part. */ + offset = Start_env_closinfo(Closinfo_val(block)); + } + + CAMLassert(Is_block(block) && !Is_young(block)); + CAMLassert(Tag_val(block) != Infix_tag); + CAMLassert(Tag_val(block) < No_scan_tag); + CAMLassert(Tag_val(block) != Cont_tag); + CAMLassert(offset <= block_wsz); + + /* Optimisation to avoid pushing small, unmarkable objects such as [Some 42] + * into the mark stack. */ + end = (block_wsz < 8 ? block_wsz : 8); + + for (i = offset; i < end; i++) { + v = Field(block, i); + + if (Is_markable(v)) + break; + } + + if (i == block_wsz){ + /* nothing left to mark and credit header */ + if(work != NULL){ + /* we should take credit for it though */ + *work -= Whsize_wosize(block_wsz - offset); + } + return; + } + + if( work != NULL ) { + /* take credit for the work we skipped due to the optimisation. + we will take credit for the header later as part of marking. */ + *work -= (i - offset); + } + + offset = i; + + if (stk->count == stk->size) + realloc_mark_stack(stk); + + me = &stk->stack[stk->count++]; + me->block = block; + me->offset = offset; +} + +/* to fit scanning_action */ +static void mark_stack_push_act(void* state, value v, value* ignored) { + if (Tag_val(v) < No_scan_tag && Tag_val(v) != Cont_tag) + mark_stack_push(Caml_state->mark_stack, v, 0, NULL); +} + +/* This function shrinks the mark stack back to the MARK_STACK_INIT_SIZE size + and is called at the end of a GC compaction to avoid a mark stack greater + than 1/32th of the heap. */ +void caml_shrink_mark_stack () { + struct mark_stack* stk = Caml_state->mark_stack; + intnat init_stack_bsize = MARK_STACK_INIT_SIZE * sizeof(mark_entry); + mark_entry* shrunk_stack; + + caml_gc_log ("Shrinking mark stack to %" + ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n", + init_stack_bsize); + + shrunk_stack = (mark_entry*) caml_stat_resize_noexc ((char*) stk->stack, + init_stack_bsize); + if (shrunk_stack != NULL) { + stk->stack = shrunk_stack; + stk->size = MARK_STACK_INIT_SIZE; + }else{ + caml_gc_log ("Mark stack shrinking failed"); + } } -/* auxiliary function of mark_slice */ -Caml_inline value* mark_slice_darken(value *gray_vals_ptr, - value v, mlsize_t i, - int in_ephemeron, int *slice_pointers) +void caml_darken_cont(value cont); + +static void mark_slice_darken(struct mark_stack* stk, value v, mlsize_t i, + intnat* work) { value child; header_t chd; - child = Field (v, i); + child = Field(v, i); -#ifdef NO_NAKED_POINTERS - if (Is_block (child) && ! Is_young (child)) { -#else - if (Is_block (child) && Is_in_heap (child)) { -#endif - CAML_EVENTLOG_DO (++ *slice_pointers); - chd = Hd_val (child); - if (Tag_hd (chd) == Forward_tag){ - value f = Forward_val (child); - if ((in_ephemeron && Is_long(f)) || - (Is_block (f) - && (!Is_in_value_area(f) || Tag_val (f) == Forward_tag - || Tag_val (f) == Lazy_tag -#ifdef FLAT_FLOAT_ARRAY - || Tag_val (f) == Double_tag -#endif - ))){ - /* Do not short-circuit the pointer. */ - }else{ - /* The variable child is not changed because it must be mark alive */ - Field (v, i) = f; - if (Is_block (f) && Is_young (f) && !Is_young (child)){ - if(in_ephemeron) { - add_to_ephe_ref_table (Caml_state->ephe_ref_table, v, i); - } else { - add_to_ref_table (Caml_state->ref_table, &Field (v, i)); - } - } - } - } - else if (Tag_hd(chd) == Infix_tag) { - child -= Infix_offset_val(child); + if (Is_markable(child)){ + chd = Hd_val(child); + if (Tag_hd(chd) == Infix_tag) { + child -= Infix_offset_hd(chd); chd = Hd_val(child); } -#ifdef NO_NAKED_POINTERS - /* See [caml_darken] for a description of this assertion. */ - CAMLassert (Is_in_heap (child) || Is_black_hd (chd)); -#endif - if (Is_white_hd (chd)){ - ephe_list_pure = 0; - Hd_val (child) = Grayhd_hd (chd); - *gray_vals_ptr++ = child; - if (gray_vals_ptr >= gray_vals_end) { - gray_vals_cur = gray_vals_ptr; - realloc_gray_vals (); - gray_vals_ptr = gray_vals_cur; + CAMLassert(!Has_status_hd(chd, global.GARBAGE)); + if (Has_status_hd(chd, global.UNMARKED)){ + Caml_state->stat_blocks_marked++; + if (Tag_hd(chd) == Cont_tag){ + caml_darken_cont(child); + *work -= Wosize_hd(chd); + } else{ + again: + if (Tag_hd(chd) == Lazy_tag || Tag_hd(chd) == Forcing_tag){ + if(!atomic_compare_exchange_strong(Hp_atomic_val(child), &chd, + With_status_hd(chd, global.MARKED))){ + chd = Hd_val(child); + goto again; + } + } else { + atomic_store_explicit( + Hp_atomic_val(child), + With_status_hd(chd, global.MARKED), + memory_order_relaxed); + } + if(Tag_hd(chd) < No_scan_tag){ + mark_stack_push(stk, child, 0, work); } + else{ + *work -= Wosize_hd(chd); /* account for header */ + } + } + } + } +} + +static intnat do_some_marking(intnat budget) { + struct mark_stack* stk = Caml_state->mark_stack; + while (stk->count > 0) { + mark_entry me = stk->stack[--stk->count]; + intnat me_end = Wosize_val(me.block); + while (me.offset != me_end) { + if (budget <= 0) { + mark_stack_push(stk, me.block, me.offset, NULL); + return budget; + } + budget--; + CAMLassert(Is_markable(me.block) && + Has_status_hd(Hd_val(me.block), global.MARKED) && + Tag_val(me.block) < No_scan_tag && + Tag_val(me.block) != Cont_tag); + mark_slice_darken(stk, me.block, me.offset++, &budget); } + budget--; /* credit for header */ } + return budget; +} - return gray_vals_ptr; +/* mark until the budget runs out or marking is done */ +static intnat mark(intnat budget) { + while (budget > 0 && !Caml_state->marking_done) { + budget = do_some_marking(budget); + if (budget > 0) { + struct pool* p = find_pool_to_rescan(); + if (p) { + caml_redarken_pool(p, &mark_stack_push_act, 0); + } else { + update_ephe_info_for_marking_done(); + Caml_state->marking_done = 1; + atomic_fetch_add_verify_ge0(&num_domains_to_mark, -1); + } + } + } + return budget; } -static value* mark_ephe_aux (value *gray_vals_ptr, intnat *work, - int *slice_pointers) +void caml_darken_cont(value cont) { - value v, data, key; + CAMLassert(Is_block(cont) && !Is_young(cont) && Tag_val(cont) == Cont_tag); + { + SPIN_WAIT { + header_t hd = atomic_load_explicit(Hp_atomic_val(cont), memory_order_relaxed); + CAMLassert(!Has_status_hd(hd, global.GARBAGE)); + if (Has_status_hd(hd, global.MARKED)) + break; + if (Has_status_hd(hd, global.UNMARKED) && + atomic_compare_exchange_strong( + Hp_atomic_val(cont), &hd, + With_status_hd(hd, NOT_MARKABLE))) { + value stk = Op_val(cont)[0]; + if (Ptr_val(stk) != NULL) + caml_scan_stack(&caml_darken, 0, Ptr_val(stk), 0); + atomic_store_explicit( + Hp_atomic_val(cont), + With_status_hd(hd, global.MARKED), + memory_order_release); + } + } + } +} + +void caml_darken(void* state, value v, value* ignored) { header_t hd; - mlsize_t size, i; + if (!Is_markable (v)) return; /* foreign stack, at least */ - v = *ephes_to_check; hd = Hd_val(v); - CAMLassert(Tag_val (v) == Abstract_tag); - data = Field(v,CAML_EPHE_DATA_OFFSET); - if ( data != caml_ephe_none && - Is_block (data) && -#ifdef NO_NAKED_POINTERS - !Is_young(data) && -#else - Is_in_heap (data) && -#endif - Is_white_val (data)){ - - int alive_data = 1; + if (Tag_hd(hd) == Infix_tag) { + v -= Infix_offset_hd(hd); + hd = Hd_val(v); + } + if (Has_status_hd(hd, global.UNMARKED)) { + if (Caml_state->marking_done) { + atomic_fetch_add(&num_domains_to_mark, 1); + Caml_state->marking_done = 0; + } + if (Tag_hd(hd) == Cont_tag) { + caml_darken_cont(v); + } else { + atomic_store_explicit( + Hp_atomic_val(v), + With_status_hd(hd, global.MARKED), + memory_order_relaxed); + if (Tag_hd(hd) < No_scan_tag) { + mark_stack_push(Caml_state->mark_stack, v, 0, NULL); + } + } + } +} - /* The liveness of the ephemeron is one of the condition */ - if (Is_white_hd (hd)) alive_data = 0; +intnat ephe_mark (intnat budget, uintnat for_cycle) +{ + value v, data, key, f, todo; + value* prev_linkp; + header_t hd; + mlsize_t size, i; + caml_domain_state* domain_state = Caml_state; + int alive_data; + intnat marked = 0, made_live = 0; - /* The liveness of the keys not caml_ephe_none is the other condition */ - size = Wosize_hd (hd); - for (i = CAML_EPHE_FIRST_KEY; alive_data && i < size; i++){ - key = Field (v, i); + if (domain_state->ephe_info->cursor.cycle == for_cycle) { + prev_linkp = domain_state->ephe_info->cursor.todop; + todo = *prev_linkp; + } else { + todo = domain_state->ephe_info->todo; + prev_linkp = &domain_state->ephe_info->todo; + } + while (todo != 0 && budget > 0) { + v = todo; + todo = Ephe_link(v); + CAMLassert (Tag_val(v) == Abstract_tag); + hd = Hd_val(v); + data = Ephe_data(v); + alive_data = 1; + + /* If ephemeron is unmarked, data is dead */ + if (is_unmarked(v)) alive_data = 0; + + size = Wosize_hd(hd); + for (i = CAML_EPHE_FIRST_KEY; alive_data && i < size; i++) { + key = Op_val(v)[i]; ephemeron_again: - if (key != caml_ephe_none && - Is_block (key) && -#ifdef NO_NAKED_POINTERS - !Is_young(key) -#else - Is_in_heap(key) -#endif - ){ - if (Tag_val (key) == Forward_tag){ - value f = Forward_val (key); - if (Is_long (f) || - (Is_block (f) && - (!Is_in_value_area(f) || Tag_val (f) == Forward_tag - || Tag_val (f) == Lazy_tag -#ifdef FLAT_FLOAT_ARRAY - || Tag_val (f) == Double_tag -#endif - ))){ - /* Do not short-circuit the pointer. */ - }else{ - Field (v, i) = key = f; - goto ephemeron_again; + if (key != caml_ephe_none && Is_block(key)) { + if (Tag_val(key) == Forward_tag) { + f = Forward_val(key); + if (Is_block(f)) { + if (Tag_val(f) == Forward_tag || Tag_val(f) == Lazy_tag || + Tag_val(f) == Double_tag) { + /* Do not short-circuit the pointer */ + } else { + Op_val(v)[i] = key = f; + goto ephemeron_again; + } } } - if (Is_white_val (key)){ + if (is_unmarked (key)) alive_data = 0; - } } } - *work -= Whsize_wosize(i); + budget -= Whsize_wosize(i); - if (alive_data){ - gray_vals_ptr = mark_slice_darken(gray_vals_ptr,v, - CAML_EPHE_DATA_OFFSET, - /*in_ephemeron=*/1, - slice_pointers); - } else { /* not triggered move to the next one */ - ephes_to_check = &Field(v,CAML_EPHE_LINK_OFFSET); - return gray_vals_ptr; + if (alive_data) { + if (data != caml_ephe_none && Is_block(data) && is_unmarked(data)) { + caml_darken (0, data, 0); + } + Ephe_link(v) = domain_state->ephe_info->live; + domain_state->ephe_info->live = v; + *prev_linkp = todo; + made_live++; + } else { + /* Leave this ephemeron on the todo list */ + prev_linkp = &Ephe_link(v); } - } else { /* a simily weak pointer or an already alive data */ - *work -= 1; + marked++; } - /* all keys black or data none or black - move the ephemerons from (3) to the end of (1) */ - if ( ephes_checked_if_pure == ephes_to_check ) { - /* corner case and optim */ - ephes_checked_if_pure = &Field(v,CAML_EPHE_LINK_OFFSET); - ephes_to_check = ephes_checked_if_pure; - } else { - /* - remove v from the list (3) */ - *ephes_to_check = Field(v,CAML_EPHE_LINK_OFFSET); - /* - insert it at the end of (1) */ - Field(v,CAML_EPHE_LINK_OFFSET) = *ephes_checked_if_pure; - *ephes_checked_if_pure = v; - ephes_checked_if_pure = &Field(v,CAML_EPHE_LINK_OFFSET); + caml_gc_log ("Mark Ephemeron: %s. for ephemeron cycle=%"ARCH_INTNAT_PRINTF_FORMAT"d " + "marked=%"ARCH_INTNAT_PRINTF_FORMAT"d made_live=%"ARCH_INTNAT_PRINTF_FORMAT"d", + domain_state->ephe_info->cursor.cycle == for_cycle ? "continued from cursor" : "discarded cursor", + for_cycle, marked, made_live); + + domain_state->ephe_info->cursor.cycle = for_cycle; + domain_state->ephe_info->cursor.todop = prev_linkp; + + return budget; +} + +intnat ephe_sweep (struct domain* d, intnat budget) +{ + value v; + caml_domain_state* domain_state = d->state; + CAMLassert (caml_gc_phase == Phase_sweep_ephe); + + while (domain_state->ephe_info->todo != 0 && budget > 0) { + v = domain_state->ephe_info->todo; + domain_state->ephe_info->todo = Ephe_link(v); + CAMLassert (Tag_val(v) == Abstract_tag); + + if (is_unmarked(v)) { + /* The whole array is dead, drop this ephemeron */ + budget -= 1; + } else { + caml_ephe_clean(v); + Ephe_link(v) = domain_state->ephe_info->live; + domain_state->ephe_info->live = v; + budget -= Whsize_val(v); + } } - return gray_vals_ptr; + return budget; +} + +static struct gc_stats sampled_gc_stats[Max_domains]; + +void caml_accum_heap_stats(struct heap_stats* acc, const struct heap_stats* h) +{ + acc->pool_words += h->pool_words; + if (acc->pool_max_words < h->pool_max_words) + acc->pool_max_words = h->pool_max_words; + acc->pool_live_words += h->pool_live_words; + acc->pool_live_blocks += h->pool_live_blocks; + acc->pool_frag_words += h->pool_frag_words; + acc->large_words += h->large_words; + if (acc->large_max_words < h->large_max_words) + acc->large_max_words = h->large_max_words; + acc->large_blocks += h->large_blocks; } +void caml_remove_heap_stats(struct heap_stats* acc, const struct heap_stats* h) +{ + acc->pool_words -= h->pool_words; + acc->pool_live_words -= h->pool_live_words; + acc->pool_live_blocks -= h->pool_live_blocks; + acc->pool_frag_words -= h->pool_frag_words; + acc->large_words -= h->large_words; + acc->large_blocks -= h->large_blocks; +} -static void mark_slice (intnat work) +void caml_sample_gc_stats(struct gc_stats* buf) { - value *gray_vals_ptr; /* Local copy of [gray_vals_cur] */ - value v; - header_t hd; - mlsize_t size, i, start, end; /* [start] is a local copy of [current_index] */ -#ifdef CAML_INSTR - int slice_fields = 0; /** eventlog counters */ -#endif /*CAML_INSTR*/ - int slice_pointers = 0; - - caml_gc_message (0x40, "Marking %"ARCH_INTNAT_PRINTF_FORMAT"d words\n", work); - caml_gc_message (0x40, "Subphase = %d\n", caml_gc_subphase); - gray_vals_ptr = gray_vals_cur; - v = current_value; - start = current_index; - while (work > 0){ - if (v == 0 && gray_vals_ptr > gray_vals){ - CAMLassert (start == 0); - v = *--gray_vals_ptr; - CAMLassert (Is_gray_val (v)); -#ifdef NO_NAKED_POINTERS - if (Tag_val(v) == Closure_tag) { - /* Skip the code pointers and integers at beginning of closure; - start scanning at the first word of the environment part. */ - start = Start_env_closinfo(Closinfo_val(v)); - CAMLassert(start <= Wosize_val(v)); - } -#endif + int i; + intnat pool_max = 0, large_max = 0; + struct domain* domain_self = caml_domain_self (); + int my_id = domain_self->state->id; + memset(buf, 0, sizeof(*buf)); + + for (i=0; i<Max_domains; i++) { + struct gc_stats* s = &sampled_gc_stats[i]; + struct heap_stats* h = &s->major_heap; + if (i != my_id) { + buf->minor_words += s->minor_words; + buf->promoted_words += s->promoted_words; + buf->major_words += s->major_words; + buf->minor_collections += s->minor_collections; + buf->forced_major_collections += s->forced_major_collections; } - if (v != 0){ - hd = Hd_val(v); - CAMLassert (Is_gray_hd (hd)); - size = Wosize_hd (hd); - end = start + work; - if (Tag_hd (hd) < No_scan_tag){ - start = size < start ? size : start; - end = size < end ? size : end; - CAMLassert (end >= start); - CAML_EVENTLOG_DO({ - slice_fields += end - start; - if (size > end) - CAML_EV_COUNTER (EV_C_MAJOR_MARK_SLICE_REMAIN, size - end); - }); - for (i = start; i < end; i++){ - gray_vals_ptr = mark_slice_darken(gray_vals_ptr,v,i, - /*in_ephemeron=*/ 0, - &slice_pointers); - } - 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; - } - }else if (markhp != NULL){ - if (markhp == limit){ - chunk = Chunk_next (chunk); - if (chunk == NULL){ - markhp = NULL; - }else{ - markhp = chunk; - limit = chunk + Chunk_size (chunk); - } - }else{ - if (Is_gray_val (Val_hp (markhp))){ - CAMLassert (gray_vals_ptr == gray_vals); - CAMLassert (v == 0 && start == 0); - v = Val_hp (markhp); -#ifdef NO_NAKED_POINTERS - if (Tag_val(v) == Closure_tag) { - start = Start_env_closinfo(Closinfo_val(v)); - CAMLassert(start <= Wosize_val(v)); - } -#endif - } - markhp += Bhsize_hp (markhp); - } - }else if (!heap_is_pure){ - heap_is_pure = 1; - chunk = caml_heap_start; - markhp = chunk; - limit = chunk + Chunk_size (chunk); - } else if (caml_gc_subphase == Subphase_mark_roots) { - CAML_EV_BEGIN(EV_MAJOR_MARK_ROOTS); - gray_vals_cur = gray_vals_ptr; - work = caml_darken_all_roots_slice (work); - gray_vals_ptr = gray_vals_cur; - CAML_EV_END(EV_MAJOR_MARK_ROOTS); - if (work > 0){ - caml_gc_subphase = Subphase_mark_main; - } - } else if (*ephes_to_check != (value) NULL) { - /* Continue to scan the list of ephe */ - gray_vals_ptr = mark_ephe_aux(gray_vals_ptr,&work,&slice_pointers); - } else if (!ephe_list_pure){ - /* We must scan again the list because some value have been darken */ - ephe_list_pure = 1; - ephes_to_check = ephes_checked_if_pure; - }else{ - switch (caml_gc_subphase){ - case Subphase_mark_main: { - /* Subphase_mark_main is done. - Mark finalised values. */ - CAML_EV_BEGIN(EV_MAJOR_MARK_MAIN); - gray_vals_cur = gray_vals_ptr; - caml_final_update_mark_phase (); - gray_vals_ptr = gray_vals_cur; - if (gray_vals_ptr > gray_vals){ - v = *--gray_vals_ptr; - CAMLassert (start == 0); -#ifdef NO_NAKED_POINTERS - if (Tag_val(v) == Closure_tag) { - start = Start_env_closinfo(Closinfo_val(v)); - CAMLassert(start <= Wosize_val(v)); - } -#endif + else { + buf->minor_words += Caml_state->stat_minor_words; + buf->promoted_words += Caml_state->stat_promoted_words; + buf->major_words += Caml_state->stat_major_words; + buf->minor_collections += Caml_state->stat_minor_collections; + buf->forced_major_collections += s->forced_major_collections; + //FIXME handle the case for major heap stats [h] + } + /* The instantaneous maximum heap size cannot be computed + from per-domain statistics, and would be very expensive + to maintain directly. Here, we just sum the per-domain + maxima, which is statistically dubious. + + FIXME: maybe maintain coarse global maxima? */ + pool_max += h->pool_max_words; + large_max += h->large_max_words; + caml_accum_heap_stats(&buf->major_heap, h); + } + buf->major_heap.pool_max_words = pool_max; + buf->major_heap.large_max_words = large_max; +} + +/* update GC stats for this given domain */ +inline void caml_sample_gc_collect(caml_domain_state* domain) +{ + struct gc_stats* stats = &sampled_gc_stats[domain->id]; + + stats->minor_words = domain->stat_minor_words; + stats->promoted_words = domain->stat_promoted_words; + stats->major_words = domain->stat_major_words; + stats->minor_collections = domain->stat_minor_collections; + stats->forced_major_collections = domain->stat_forced_major_collections; + caml_sample_heap_stats(domain->shared_heap, &stats->major_heap); +} + +static void cycle_all_domains_callback(struct domain* domain, void* unused, + int participating_count, struct domain** participating) +{ + uintnat num_domains_in_stw; + + CAML_EV_BEGIN(EV_MAJOR_GC_CYCLE_DOMAINS); + + CAMLassert(domain == caml_domain_self()); + CAMLassert(atomic_load_acq(&ephe_cycle_info.num_domains_todo) == + atomic_load_acq(&ephe_cycle_info.num_domains_done)); + CAMLassert(atomic_load(&num_domains_to_mark) == 0); + CAMLassert(atomic_load(&num_domains_to_sweep) == 0); + CAMLassert(atomic_load(&num_domains_to_ephe_sweep) == 0); + CAMLassert(caml_global_barrier_leave_when_done() == 0); + + caml_empty_minor_heap_no_major_slice_from_stw(domain, (void*)0, participating_count, participating); + + CAML_EV_BEGIN(EV_MAJOR_GC_STW); + + { + /* Cycle major heap */ + // FIXME: delete caml_cycle_heap_stw and have per-domain copies of the data? + barrier_status b = caml_global_barrier_begin(); + if (caml_global_barrier_is_final(b)) { + caml_cycle_heap_stw(); + caml_gc_log("GC cycle %lu completed (heap cycled)", + (long unsigned int)caml_major_cycles_completed); + + caml_major_cycles_completed++; + caml_gc_message(0x40, "Starting major GC cycle\n"); + + if (caml_params->verb_gc & 0x400) { + struct gc_stats s; + intnat heap_words, not_garbage_words, swept_words; + + caml_sample_gc_stats(&s); + heap_words = s.major_heap.pool_words + s.major_heap.large_words; + not_garbage_words = s.major_heap.pool_live_words + s.major_heap.large_words; + swept_words = domain->state->swept_words; + caml_gc_log ("heap_words: %"ARCH_INTNAT_PRINTF_FORMAT"d " + "not_garbage_words %"ARCH_INTNAT_PRINTF_FORMAT"d " + "swept_words %"ARCH_INTNAT_PRINTF_FORMAT"d", + heap_words, not_garbage_words, swept_words); + + if (caml_stat_space_overhead.heap_words_last_cycle != 0) { + /* At the end of a major cycle, no object has colour MARKED. + * + * [not_garbage_words] counts all objects which are UNMARKED. + * Importantly, this includes both live objects and objects which are + * unreachable in the current cycle (i.e, garbage). But we don't get to + * know which objects are garbage until the end of the next cycle. + * + * live_words@N = not_garbage_words@N - swept_words@N+1 + * + * space_overhead@N = 100.0 * (heap_words@N - live_words@N) / live_words@N + */ + double live_words_last_cycle = + caml_stat_space_overhead.not_garbage_words_last_cycle - swept_words; + double space_overhead = + 100.0 * (double)(caml_stat_space_overhead.heap_words_last_cycle + - live_words_last_cycle) / live_words_last_cycle; + + if (caml_stat_space_overhead.l == NULL || + caml_stat_space_overhead.index == BUFFER_SIZE) { + struct buf_list_t *l = + (struct buf_list_t*)caml_stat_alloc_noexc(sizeof(struct buf_list_t)); + l->next = caml_stat_space_overhead.l; + caml_stat_space_overhead.l = l; + caml_stat_space_overhead.index = 0; } - /* Complete the marking */ - ephes_to_check = ephes_checked_if_pure; - CAML_EV_END(EV_MAJOR_MARK_MAIN); - caml_gc_subphase = Subphase_mark_final; - } - break; - case Subphase_mark_final: { - /** The set of unreachable value will not change anymore for - this cycle. Start clean phase. */ - CAML_EV_BEGIN(EV_MAJOR_MARK_FINAL); - caml_gc_phase = Phase_clean; - caml_final_update_clean_phase (); - caml_memprof_update_clean_phase (); - if (caml_ephe_list_head != (value) NULL){ - /* Initialise the clean phase. */ - ephes_to_check = &caml_ephe_list_head; - } else { - /* Initialise the sweep phase. */ - init_sweep_phase(); + caml_stat_space_overhead.l->buffer[caml_stat_space_overhead.index++] = + space_overhead; + caml_gc_log("Previous cycle's space_overhead: %lf", space_overhead); } - work = 0; - CAML_EV_END(EV_MAJOR_MARK_FINAL); - } - break; - default: CAMLassert (0); + caml_stat_space_overhead.heap_words_last_cycle = heap_words; + caml_stat_space_overhead.not_garbage_words_last_cycle = not_garbage_words; } + domain->state->swept_words = 0; + + num_domains_in_stw = (uintnat)caml_global_barrier_num_domains(); + atomic_store_rel(&num_domains_to_sweep, num_domains_in_stw); + atomic_store_rel(&num_domains_to_mark, num_domains_in_stw); + + caml_gc_phase = Phase_sweep_and_mark_main; + atomic_store(&ephe_cycle_info.num_domains_todo, num_domains_in_stw); + atomic_store(&ephe_cycle_info.ephe_cycle, 0); + atomic_store(&ephe_cycle_info.num_domains_done, 0); + atomic_store_rel(&num_domains_to_ephe_sweep, num_domains_in_stw); + atomic_store_rel(&num_domains_to_final_update_first, num_domains_in_stw); + atomic_store_rel(&num_domains_to_final_update_last, num_domains_in_stw); + + atomic_store(&domain_global_roots_started, WORK_UNSTARTED); + } + // should interrupts be processed here or not? + // depends on whether marking above may need interrupts + caml_global_barrier_end(b); + } + + /* If the heap is to be verified, do it before the domains continue + running OCaml code. */ + if (caml_params->verify_heap) { + struct heap_verify_state* ver = caml_verify_begin(); + caml_do_roots (&caml_verify_root, ver, domain, 1); + caml_scan_global_roots(&caml_verify_root, ver); + caml_verify_heap(ver); + caml_gc_log("Heap verified"); + caml_global_barrier(); + } + + domain->state->stat_major_collections++; + caml_cycle_heap(domain->state->shared_heap); + domain->state->sweeping_done = 0; + + /* Mark roots for new cycle */ + domain->state->marking_done = 0; + domain->state->major_work_computed = 0; + domain->state->major_work_todo = 0; + domain->state->major_gc_clock = 0.0; + + CAML_EV_BEGIN(EV_MAJOR_MARK_ROOTS); + caml_do_roots (&caml_darken, NULL, domain, 0); + { + uintnat work_unstarted = WORK_UNSTARTED; + if(atomic_compare_exchange_strong(&domain_global_roots_started, &work_unstarted, WORK_STARTED)){ + caml_scan_global_roots(&caml_darken, NULL); } } - gray_vals_cur = gray_vals_ptr; - current_value = v; - current_index = start; - CAML_EV_COUNTER(EV_C_MAJOR_MARK_SLICE_FIELDS, slice_fields); - CAML_EV_COUNTER(EV_C_MAJOR_MARK_SLICE_POINTERS, slice_pointers); + CAML_EV_END(EV_MAJOR_MARK_ROOTS); + + if (domain->state->mark_stack->count == 0) { + atomic_fetch_add_verify_ge0(&num_domains_to_mark, -1); + domain->state->marking_done = 1; + } + + /* Ephemerons */ + CAMLassert(domain->state->ephe_info->todo == (value) NULL); + domain->state->ephe_info->todo = domain->state->ephe_info->live; + domain->state->ephe_info->live = (value) NULL; + domain->state->ephe_info->cycle = 0; + domain->state->ephe_info->cursor.todop = NULL; + domain->state->ephe_info->cursor.cycle = 0; + if (domain->state->ephe_info->todo == (value) NULL) + caml_ephe_todo_list_emptied(); + + /* Finalisers */ + domain->state->final_info->updated_first = 0; + domain->state->final_info->updated_last = 0; + + CAML_EV_END(EV_MAJOR_GC_STW); + CAML_EV_END(EV_MAJOR_GC_CYCLE_DOMAINS); } -/* Clean ephemerons */ -static void clean_slice (intnat work) +static int is_complete_phase_sweep_and_mark_main (struct domain *d) { - value v; + return + caml_gc_phase == Phase_sweep_and_mark_main && + atomic_load_acq (&num_domains_to_sweep) == 0 && + atomic_load_acq (&num_domains_to_mark) == 0 && + /* Marking is done */ + atomic_load_acq(&ephe_cycle_info.num_domains_todo) == + atomic_load_acq(&ephe_cycle_info.num_domains_done) && + /* Ephemeron marking is done */ + no_orphaned_work(); + /* All orphaned ephemerons have been adopted */ +} - caml_gc_message (0x40, "Cleaning %" - ARCH_INTNAT_PRINTF_FORMAT "d words\n", work); - while (work > 0){ - v = *ephes_to_check; - if (v != (value) NULL){ - if (Is_white_val (v)){ - /* The whole array is dead, remove it from the list. */ - *ephes_to_check = Field (v, CAML_EPHE_LINK_OFFSET); - work -= 1; - }else{ - caml_ephe_clean(v); - ephes_to_check = &Field (v, CAML_EPHE_LINK_OFFSET); - work -= Whsize_val (v); - } - }else{ /* End of list reached */ - /* Phase_clean is done. */ - /* Initialise the sweep phase. */ - init_sweep_phase(); - work = 0; +static int is_complete_phase_mark_final (struct domain *d) +{ + return + caml_gc_phase == Phase_mark_final && + atomic_load_acq (&num_domains_to_final_update_first) == 0 && + /* updated finalise first values */ + atomic_load_acq (&num_domains_to_mark) == 0 && + /* Marking is done */ + atomic_load_acq(&ephe_cycle_info.num_domains_todo) == + atomic_load_acq(&ephe_cycle_info.num_domains_done) && + /* Ephemeron marking is done */ + no_orphaned_work(); + /* All orphaned ephemerons have been adopted */ +} + +static int is_complete_phase_sweep_ephe (struct domain *d) +{ + return + caml_gc_phase == Phase_sweep_ephe && + atomic_load_acq (&num_domains_to_ephe_sweep) == 0 && + /* All domains have swept their ephemerons */ + atomic_load_acq (&num_domains_to_final_update_last) == 0 && + /* All domains have updated finalise last values */ + no_orphaned_work(); + /* All orphaned structures have been adopted */ +} + +static void try_complete_gc_phase (struct domain* domain, void* unused, + int participating_count, struct domain** participating) +{ + barrier_status b; + CAML_EV_BEGIN(EV_MAJOR_GC_PHASE_CHANGE); + + b = caml_global_barrier_begin (); + if (caml_global_barrier_is_final(b)) { + if (is_complete_phase_sweep_and_mark_main(domain)) { + caml_gc_phase = Phase_mark_final; + } else if (is_complete_phase_mark_final(domain)) { + caml_gc_phase = Phase_sweep_ephe; } } + caml_global_barrier_end(b); + CAML_EV_END(EV_MAJOR_GC_PHASE_CHANGE); } -static void sweep_slice (intnat work) +intnat caml_opportunistic_major_work_available () { - char *hp; - header_t hd; + struct domain* d = caml_domain_self(); + caml_domain_state* domain_state = d->state; + return !domain_state->sweeping_done || !domain_state->marking_done; +} - caml_gc_message (0x40, "Sweeping %" - ARCH_INTNAT_PRINTF_FORMAT "d words\n", work); - while (work > 0){ - if (caml_gc_sweep_hp < limit){ - hp = caml_gc_sweep_hp; - hd = Hd_hp (hp); - work -= Whsize_hd (hd); - caml_gc_sweep_hp += Bhsize_hd (hd); - switch (Color_hd (hd)){ - case Caml_white: - caml_gc_sweep_hp = (char *) caml_fl_merge_block (Val_hp (hp), limit); - break; - case Caml_blue: - /* Only the blocks of the free-list are blue. See [freelist.c]. */ - caml_fl_merge = Bp_hp (hp); - break; - default: /* gray or black */ - CAMLassert (Color_hd (hd) == Caml_black); - Hd_hp (hp) = Whitehd_hd (hd); - break; - } - CAMLassert (caml_gc_sweep_hp <= limit); - }else{ - chunk = Chunk_next (chunk); - if (chunk == NULL){ - /* Sweeping is done. */ - ++ Caml_state->stat_major_collections; - work = 0; - caml_gc_phase = Phase_idle; - caml_request_minor_gc (); - }else{ - caml_gc_sweep_hp = chunk; - limit = chunk + Chunk_size (chunk); - } - } +typedef enum { + Slice_uninterruptible, + Slice_interruptible, + Slice_opportunistic +} collection_slice_mode; + +static char collection_slice_mode_char(collection_slice_mode mode) +{ + switch(mode) { + case Slice_uninterruptible: + return 'u'; + case Slice_interruptible: + return 'i'; + case Slice_opportunistic: + return 'o'; + default: + return ' '; } } -/* 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 - */ -void caml_major_collection_slice (intnat howmuch) +#define Chunk_size 0x400 + +static intnat major_collection_slice(intnat howmuch, + int participant_count, + struct domain** barrier_participants, + collection_slice_mode mode) { - 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_state->stat_heap_wsz * caml_percent_free - / (100 + caml_percent_free) + struct domain* d = caml_domain_self(); + caml_domain_state* domain_state = d->state; + intnat sweep_work = 0, mark_work = 0; + intnat available, left; + uintnat blocks_marked_before = domain_state->stat_blocks_marked; + int was_marking = 0; + uintnat saved_ephe_cycle; + uintnat saved_major_cycle = caml_major_cycles_completed; + int log_events = mode != Slice_opportunistic || (caml_params->verb_gc & 0x40); + intnat computed_work, budget, interrupted_budget = 0; + + update_major_slice_work(); + computed_work = get_major_slice_work(howmuch); + budget = computed_work; + + /* shortcut out if there is no opportunistic work to be done + * NB: needed particularly to avoid caml_ev spam when polling */ + if (mode == Slice_opportunistic && + !caml_opportunistic_major_work_available()) { + return budget; + } - Assuming steady state and enforcing a constant allocation rate, then - FM is divided in 2/3 for garbage and 1/3 for free list. - G = 2 * FM / 3 - G is also the amount of memory that will be used during this cycle - (still assuming steady state). + if (log_events) CAML_EV_BEGIN(EV_MAJOR_SLICE); - Proportion of G consumed since the previous slice: - PH = caml_allocated_words / G - = caml_allocated_words * 3 * (100 + caml_percent_free) - / (2 * Caml_state->stat_heap_wsz * caml_percent_free) - Proportion of extra-heap resources consumed since the previous slice: - PE = caml_extra_heap_resources - Proportion of total work to do in this slice: - P = max (PH, PE) + if (!domain_state->sweeping_done) { + if (log_events) CAML_EV_BEGIN(EV_MAJOR_SWEEP); - 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. + do { + available = budget > Chunk_size ? Chunk_size : budget; + left = caml_sweep(domain_state->shared_heap, available); + budget -= available - left; + sweep_work += available - left; - Amount of marking work for the GC cycle: - MW = Caml_state->stat_heap_wsz * 100 / (100 + caml_percent_free) - + caml_incremental_roots_count - Amount of sweeping work for the GC cycle: - SW = Caml_state->stat_heap_wsz + if (budget > 0 && available == left) { + domain_state->sweeping_done = 1; + atomic_fetch_add_verify_ge0(&num_domains_to_sweep, -1); + } + + if (mode == Slice_interruptible && caml_incoming_interrupts_queued()) + { + interrupted_budget = budget; + budget = 0; + } + } while (budget > 0 && available != left); - 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 (log_events) CAML_EV_END(EV_MAJOR_SWEEP); + } - 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 +mark_again: + while (budget > 0) { + if (!domain_state->marking_done) { + if (!was_marking) { + if (log_events) CAML_EV_BEGIN(EV_MAJOR_MARK); + was_marking = 1; + } + available = budget > Chunk_size ? Chunk_size : budget; + left = mark(available); + budget -= available - left; + mark_work += available - left; + } else { + break; + } - 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_state->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_state->stat_heap_wsz * 5 / 3 - - This slice will either mark MS words or sweep SS words. - */ + if (mode == Slice_interruptible && caml_incoming_interrupts_queued()) { + interrupted_budget = budget; + budget = 0; + } + } + if (was_marking) { + if (log_events) CAML_EV_END(EV_MAJOR_MARK); + was_marking = 0; + } - if (caml_major_slice_begin_hook != NULL) (*caml_major_slice_begin_hook) (); + if (mode != Slice_opportunistic) { + /* Finalisers */ + if (caml_gc_phase == Phase_mark_final && + caml_final_update_first(d)) { + /* This domain has updated finalise first values */ + atomic_fetch_add_verify_ge0(&num_domains_to_final_update_first, -1); + if (budget > 0 && !domain_state->marking_done) + goto mark_again; + } - p = (double) caml_allocated_words * 3.0 * (100 + caml_percent_free) - / Caml_state->stat_heap_wsz / caml_percent_free / 2.0; - if (caml_dependent_size > 0){ - dp = (double) caml_dependent_allocated * (100 + caml_percent_free) - / caml_dependent_size / caml_percent_free; - }else{ - dp = 0.0; + if (caml_gc_phase == Phase_sweep_ephe && + caml_final_update_last(d)) { + /* This domain has updated finalise last values */ + atomic_fetch_add_verify_ge0(&num_domains_to_final_update_last, -1); + /* Nothing has been marked while updating last */ + } + + caml_adopt_orphaned_work(); + + /* Ephemerons */ + saved_ephe_cycle = atomic_load_acq(&ephe_cycle_info.ephe_cycle); + if (domain_state->ephe_info->todo != (value) NULL && + saved_ephe_cycle > domain_state->ephe_info->cycle) { + CAML_EV_BEGIN(EV_MAJOR_EPHE_MARK); + budget = ephe_mark(budget, saved_ephe_cycle); + CAML_EV_END(EV_MAJOR_EPHE_MARK); + if (domain_state->ephe_info->todo == (value) NULL) + caml_ephe_todo_list_emptied (); + else if (budget > 0 && domain_state->marking_done) + record_ephe_marking_done(saved_ephe_cycle); + else if (budget > 0) goto mark_again; + } + + if (caml_gc_phase == Phase_sweep_ephe && + domain_state->ephe_info->todo != 0) { + CAML_EV_BEGIN(EV_MAJOR_EPHE_SWEEP); + budget = ephe_sweep (d, budget); + CAML_EV_END(EV_MAJOR_EPHE_SWEEP); + if (domain_state->ephe_info->todo == 0) { + atomic_fetch_add_verify_ge0(&num_domains_to_ephe_sweep, -1); + } + } + + /* Complete GC phase */ + if (is_complete_phase_sweep_and_mark_main(d) || + is_complete_phase_mark_final (d)) { + if (barrier_participants) { + try_complete_gc_phase (d, (void*)0, participant_count, barrier_participants); + } else { + caml_try_run_on_all_domains (&try_complete_gc_phase, 0, 0, 0); + } + if (budget > 0) goto mark_again; + } } - if (p < dp) p = dp; - if (p < caml_extra_heap_resources) p = caml_extra_heap_resources; - p += p_backlog; - p_backlog = 0.0; - if (p > 0.3){ - p_backlog = p - 0.3; - p = 0.3; + + if (log_events) CAML_EV_END(EV_MAJOR_SLICE); + + caml_gc_log("Major slice [%c%c%c]: %ld work, %ld sweep, %ld mark (%lu blocks)", + collection_slice_mode_char(mode), + interrupted_budget == 0 ? '.' : '*', + caml_gc_phase_char(caml_gc_phase), + (long)computed_work, (long)sweep_work, (long)mark_work, + (unsigned long)(domain_state->stat_blocks_marked - blocks_marked_before)); + + /* we did: work we were asked - interrupted_budget + any overwork */ + commit_major_slice_work(computed_work - interrupted_budget + (budget < 0 ? -budget : 0)); + + if (mode != Slice_opportunistic && is_complete_phase_sweep_ephe(d)) { + saved_major_cycle = caml_major_cycles_completed; + /* To handle the case where multiple domains try to finish the major + cycle simultaneously, we loop until the current cycle has ended, + ignoring whether caml_try_run_on_all_domains succeeds. */ + + + while (saved_major_cycle == caml_major_cycles_completed) { + if (barrier_participants) { + cycle_all_domains_callback(d, (void*)0, participant_count, barrier_participants); + } else { + caml_try_run_on_all_domains(&cycle_all_domains_callback, 0, 0, 0); + } + } } - CAML_EV_COUNTER (EV_C_MAJOR_WORK_EXTRA, - (uintnat) (caml_extra_heap_resources * 1000000)); + return budget; +} - caml_gc_message (0x40, "ordered work = %" - ARCH_INTNAT_PRINTF_FORMAT "d 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, "raw work-to-do = %" - ARCH_INTNAT_PRINTF_FORMAT "du\n", - (intnat) (p * 1000000)); - caml_gc_message (0x40, "work backlog = %" - ARCH_INTNAT_PRINTF_FORMAT "du\n", - (intnat) (p_backlog * 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_state->stat_heap_wsz / caml_percent_free / 2.0; - } - caml_major_work_credit += filt_p; - /* Limit work credit to 1.0 */ - caml_major_work_credit = fmin(caml_major_work_credit, 1.0); - } - - 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_state->young_ptr == Caml_state->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. */ - CAML_EV_BEGIN(EV_MAJOR_ROOTS); - start_cycle (); - CAML_EV_END(EV_MAJOR_ROOTS); +intnat caml_opportunistic_major_collection_slice(intnat howmuch) +{ + return major_collection_slice(howmuch, 0, 0, Slice_opportunistic); +} + +intnat caml_major_collection_slice(intnat howmuch) +{ + intnat work_left; + + /* if this is an auto-triggered GC slice, make it interruptible */ + if (howmuch == AUTO_TRIGGERED_MAJOR_SLICE) { + work_left = major_collection_slice(AUTO_TRIGGERED_MAJOR_SLICE, 0, 0, Slice_interruptible); + if (get_major_slice_work(AUTO_TRIGGERED_MAJOR_SLICE) > 0) { + caml_gc_log("Major slice interrupted, rescheduling major slice"); + caml_request_major_slice(); } - p = 0; - goto finished; + } else { + /* TODO: could make forced API slices interruptible, but would need to do accounting or pass up interrupt */ + work_left = major_collection_slice(howmuch, 0, 0, Slice_uninterruptible); } - if (p < 0){ - p = 0; - goto finished; + return work_left; +} + +static void finish_major_cycle_callback (struct domain* domain, void* arg, + int participating_count, struct domain** participating) +{ + uintnat saved_major_cycles = (uintnat)arg; + CAMLassert (domain == caml_domain_self()); + + caml_empty_minor_heap_no_major_slice_from_stw(domain, (void*)0, participating_count, participating); + + while (saved_major_cycles == caml_major_cycles_completed) { + major_collection_slice(10000000, participating_count, participating, 0); } +} - if (caml_gc_phase == Phase_mark || caml_gc_phase == Phase_clean){ - computed_work = (intnat) (p * ((double) Caml_state->stat_heap_wsz * 250 - / (100 + caml_percent_free) - + caml_incremental_roots_count)); - }else{ - computed_work = (intnat) (p * Caml_state->stat_heap_wsz * 5 / 3); +void caml_finish_major_cycle () +{ + uintnat saved_major_cycles = caml_major_cycles_completed; + + while( saved_major_cycles == caml_major_cycles_completed ) { + caml_try_run_on_all_domains(&finish_major_cycle_callback, (void*)caml_major_cycles_completed, 0, 0); } - caml_gc_message (0x40, "computed work = %" - ARCH_INTNAT_PRINTF_FORMAT "d words\n", computed_work); - if (caml_gc_phase == Phase_mark){ - CAML_EV_COUNTER (EV_C_MAJOR_WORK_MARK, computed_work); - CAML_EV_BEGIN(EV_MAJOR_MARK); - mark_slice (computed_work); - CAML_EV_END(EV_MAJOR_MARK); - caml_gc_message (0x02, "!"); - }else if (caml_gc_phase == Phase_clean){ - clean_slice (computed_work); - caml_gc_message (0x02, "%%"); - }else{ - CAMLassert (caml_gc_phase == Phase_sweep); - CAML_EV_COUNTER (EV_C_MAJOR_WORK_SWEEP, computed_work); - CAML_EV_BEGIN(EV_MAJOR_SWEEP); - sweep_slice (computed_work); - CAML_EV_END(EV_MAJOR_SWEEP); - caml_gc_message (0x02, "$"); - } - - if (caml_gc_phase == Phase_idle){ - CAML_EV_BEGIN(EV_MAJOR_CHECK_AND_COMPACT); - caml_compact_heap_maybe (); - CAML_EV_END(EV_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_state->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) (); -} - -/* 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 itself is called by [caml_compact_heap_maybe]. -*/ -void caml_finish_major_cycle (void) -{ - if (caml_gc_phase == Phase_idle){ - p_backlog = 0.0; /* full major GC cycle, the backlog becomes irrelevant */ - start_cycle (); - } - while (caml_gc_phase == Phase_mark) mark_slice (LONG_MAX); - while (caml_gc_phase == Phase_clean) clean_slice (LONG_MAX); - CAMLassert (caml_gc_phase == Phase_sweep); - while (caml_gc_phase == Phase_sweep) sweep_slice (LONG_MAX); - CAMLassert (caml_gc_phase == Phase_idle); - Caml_state->stat_major_words += caml_allocated_words; - caml_allocated_words = 0; -} - -/* Call this function to make sure [bsz] is greater than or equal - to both [Heap_chunk_min] and the current heap increment. -*/ -asize_t caml_clip_heap_chunk_wsz (asize_t wsz) -{ - asize_t result = wsz; - uintnat incr; - - /* Compute the heap increment as a word size. */ - if (caml_major_heap_increment > 1000){ - incr = caml_major_heap_increment; - }else{ - incr = Caml_state->stat_heap_wsz / 100 * caml_major_heap_increment; +} + +void caml_empty_mark_stack () { + while (!Caml_state->marking_done){ + mark(1000); + caml_handle_incoming_interrupts(); } - if (result < incr){ - result = incr; + if (Caml_state->stat_blocks_marked) + caml_gc_log("Finished marking major heap. Marked %u blocks", + (unsigned)Caml_state->stat_blocks_marked); + Caml_state->stat_blocks_marked = 0; +} + +void caml_finish_marking () { + if (!Caml_state->marking_done) { + CAML_EV_BEGIN(EV_MAJOR_FINISH_MARKING); + caml_empty_mark_stack(); + caml_shrink_mark_stack(); + Caml_state->stat_major_words += Caml_state->allocated_words; + Caml_state->allocated_words = 0; + CAML_EV_END(EV_MAJOR_FINISH_MARKING); } - if (result < Heap_chunk_min){ - result = Heap_chunk_min; +} + +void caml_finish_sweeping () { + if (Caml_state->sweeping_done) return; + CAML_EV_BEGIN(EV_MAJOR_FINISH_SWEEPING); + while (!Caml_state->sweeping_done) { + if (caml_sweep(Caml_state->shared_heap, 10) > 0) { + /* just finished sweeping */ + CAMLassert(Caml_state->sweeping_done == 0); + Caml_state->sweeping_done = 1; + atomic_fetch_add_verify_ge0(&num_domains_to_sweep, -1); + break; + } + caml_handle_incoming_interrupts(); } - return result; + CAML_EV_END(EV_MAJOR_FINISH_SWEEPING); } -/* [heap_size] is a number of bytes */ -void caml_init_major_heap (asize_t heap_size) +static struct pool* find_pool_to_rescan() { - int i; + struct pool* p; - Caml_state->stat_heap_wsz = - caml_clip_heap_chunk_wsz (Wsize_bsize (heap_size)); - Caml_state->stat_top_heap_wsz = Caml_state->stat_heap_wsz; - CAMLassert (Bsize_wsize (Caml_state->stat_heap_wsz) % Page_size == 0); - caml_heap_start = - (char *) caml_alloc_for_heap (Bsize_wsize (Caml_state->stat_heap_wsz)); - if (caml_heap_start == NULL) - caml_fatal_error ("cannot allocate initial major heap"); - Chunk_next (caml_heap_start) = NULL; - Caml_state->stat_heap_wsz = Wsize_bsize (Chunk_size (caml_heap_start)); - Caml_state->stat_heap_chunks = 1; - Caml_state->stat_top_heap_wsz = Caml_state->stat_heap_wsz; - - if (caml_page_table_add(In_heap, caml_heap_start, - caml_heap_start + Bsize_wsize (Caml_state->stat_heap_wsz)) - != 0) { - caml_fatal_error ("cannot allocate initial page table"); - } - - caml_fl_init_merge (); - caml_make_free_blocks ((value *) caml_heap_start, - Caml_state->stat_heap_wsz, 1, Caml_white); - caml_gc_phase = Phase_idle; - gray_vals_size = 2048; - gray_vals = (value *) caml_stat_alloc_noexc (gray_vals_size * sizeof (value)); - if (gray_vals == NULL) - caml_fatal_error ("not enough memory for the gray cache"); - gray_vals_cur = gray_vals; - gray_vals_end = gray_vals + gray_vals_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]; + if (Caml_state->pools_to_rescan_count > 0) { + p = Caml_state->pools_to_rescan[--Caml_state->pools_to_rescan_count]; + caml_gc_log("Redarkening pool %p (%d others left)", p, Caml_state->pools_to_rescan_count); + } else { + p = 0; } - /* Redistribute to the new buckets. */ - for (i = 0; i < w; i++){ - caml_major_ring[i] = total / w; + + return p; +} + +static void mark_stack_prune (struct mark_stack* stk) +{ + int entry_idx, large_idx = 0; + mark_entry* mark_stack = stk->stack; + + struct skiplist chunk_sklist = SKIPLIST_STATIC_INITIALIZER; + /* Insert used pools into skiplist */ + for(entry_idx = 0; entry_idx < stk->count; entry_idx++){ + mark_entry me = mark_stack[entry_idx]; + struct pool* pool = caml_pool_of_shared_block(me.block); + if (!pool) { + // This could be a large allocation - which is off-heap. Hold on to it. + mark_stack[large_idx++] = me; + continue; + } + caml_skiplist_insert(&chunk_sklist, (uintnat)pool, + (uintnat)pool + sizeof(pool)); } - caml_major_window = w; + + /* Traverse through entire skiplist and put it into pools to rescan */ + FOREACH_SKIPLIST_ELEMENT(e, &chunk_sklist, { + if(Caml_state->pools_to_rescan_len == Caml_state->pools_to_rescan_count){ + Caml_state->pools_to_rescan_len = Caml_state->pools_to_rescan_len * 2 + 128; + Caml_state->pools_to_rescan = + caml_stat_resize(Caml_state->pools_to_rescan, Caml_state->pools_to_rescan_len * sizeof(struct pool *)); + } + Caml_state->pools_to_rescan[Caml_state->pools_to_rescan_count++] = (struct pool*) (e->key);; + }); + + caml_gc_log("Mark stack overflow. Postponing %d pools", Caml_state->pools_to_rescan_count); + + stk->count = large_idx; +} + +int caml_init_major_gc(caml_domain_state* d) { + Caml_state->mark_stack = caml_stat_alloc_noexc(sizeof(struct mark_stack)); + if(Caml_state->mark_stack == NULL) { + return -1; + } + Caml_state->mark_stack->stack = + caml_stat_alloc_noexc(MARK_STACK_INIT_SIZE * sizeof(mark_entry)); + if(Caml_state->mark_stack->stack == NULL) { + caml_stat_free(Caml_state->mark_stack); + Caml_state->mark_stack = NULL; + return -1; + } + Caml_state->mark_stack->count = 0; + Caml_state->mark_stack->size = MARK_STACK_INIT_SIZE; + /* Fresh domains do not need to performing marking or sweeping. */ + d->sweeping_done = 1; + d->marking_done = 1; + d->major_work_computed = 0; + d->major_work_todo = 0; + d->major_gc_clock = 0.0; + /* Finalisers. Fresh domains participate in updating finalisers. */ + d->final_info = caml_alloc_final_info (); + if(d->final_info == NULL) { + caml_stat_free(Caml_state->mark_stack->stack); + caml_stat_free(Caml_state->mark_stack); + return -1; + } + d->ephe_info = caml_alloc_ephe_info(); + if(d->ephe_info == NULL) { + caml_stat_free(d->final_info); + caml_stat_free(Caml_state->mark_stack->stack); + caml_stat_free(Caml_state->mark_stack); + d->final_info = NULL; + Caml_state->mark_stack = NULL; + return -1; + } + atomic_fetch_add(&num_domains_to_final_update_first, 1); + atomic_fetch_add(&num_domains_to_final_update_last, 1); + + Caml_state->pools_to_rescan = caml_stat_alloc_noexc(INITIAL_POOLS_TO_RESCAN_LEN * sizeof(struct pool*)); + Caml_state->pools_to_rescan_len = INITIAL_POOLS_TO_RESCAN_LEN; + Caml_state->pools_to_rescan_count = 0; + + return 0; +} + +void caml_teardown_major_gc() { + CAMLassert(Caml_state->mark_stack->count == 0); + caml_stat_free(Caml_state->mark_stack->stack); + caml_stat_free(Caml_state->mark_stack); + if( Caml_state->pools_to_rescan_len > 0 ) caml_stat_free(Caml_state->pools_to_rescan); + Caml_state->mark_stack = NULL; } void caml_finalise_heap (void) { - /* Finishing major cycle (all values become white) */ - caml_empty_minor_heap (); - caml_finish_major_cycle (); - CAMLassert (caml_gc_phase == Phase_idle); - - /* Finalising all values (by means of forced sweeping) */ - caml_fl_init_merge (); - caml_gc_phase = Phase_sweep; - chunk = caml_heap_start; - caml_gc_sweep_hp = chunk; - limit = chunk + Chunk_size (chunk); - while (caml_gc_phase == Phase_sweep) - sweep_slice (LONG_MAX); + return; } diff --git a/runtime/md5.c b/runtime/md5.c index 2e1280105e..628e556dd8 100644 --- a/runtime/md5.c +++ b/runtime/md5.c @@ -45,26 +45,26 @@ CAMLexport value caml_md5_channel(struct channel *chan, intnat toread) intnat read; char buffer[4096]; - Lock(chan); - caml_MD5Init(&ctx); - if (toread < 0){ - while (1){ - read = caml_getblock (chan, buffer, sizeof(buffer)); - if (read == 0) break; - caml_MD5Update (&ctx, (unsigned char *) buffer, read); - } - }else{ - while (toread > 0) { - read = caml_getblock(chan, buffer, - toread > sizeof(buffer) ? sizeof(buffer) : toread); - if (read == 0) caml_raise_end_of_file(); - caml_MD5Update(&ctx, (unsigned char *) buffer, read); - toread -= read; + With_mutex(&chan->mutex, { + caml_MD5Init(&ctx); + if (toread < 0){ + while (1){ + read = caml_getblock (chan, buffer, sizeof(buffer)); + if (read == 0) break; + caml_MD5Update (&ctx, (unsigned char *) buffer, read); + } + }else{ + while (toread > 0) { + read = caml_getblock(chan, buffer, + toread > sizeof(buffer) ? sizeof(buffer) : toread); + if (read == 0) caml_raise_end_of_file(); + caml_MD5Update(&ctx, (unsigned char *) buffer, read); + toread -= read; + } } - } - res = caml_alloc_string(16); - caml_MD5Final(&Byte_u(res, 0), &ctx); - Unlock(chan); + res = caml_alloc_string(16); + caml_MD5Final(&Byte_u(res, 0), &ctx); + } ); CAMLreturn (res); } diff --git a/runtime/memory.c b/runtime/memory.c index a58c689767..970ab0a6f8 100644 --- a/runtime/memory.c +++ b/runtime/memory.c @@ -15,689 +15,398 @@ #define CAML_INTERNALS -#include <stdlib.h> #include <string.h> +#include <stdlib.h> +#include <stdio.h> #include <stdarg.h> #include <stddef.h> -#include "caml/address_class.h" #include "caml/config.h" +#include "caml/misc.h" #include "caml/fail.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/major_gc.h" -#include "caml/minor_gc.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/signals.h" -#include "caml/memprof.h" +#include "caml/shared_heap.h" +#include "caml/domain.h" +#include "caml/addrmap.h" +#include "caml/roots.h" +#include "caml/alloc.h" +#include "caml/fiber.h" +#include "caml/platform.h" #include "caml/eventlog.h" -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. +/* Note [MM]: Enforcing the memory model. + + Multicore OCaml implements the memory consistency model defined in + + Bounding Data Races in Space and Time (PLDI '18) + Stephen Dolan, KC Sivaramakrishnan, Anil Madhavapeddy. + + Unlike the C++ (also used in C11) memory model, this model gives + well-defined behaviour to data races, ensuring that they do not + affect unrelated computations. In C++, plain (non-atomic) accesses + have undefined semantics if they race, so it is necessary to use at + least relaxed atomics to implement all accesses. + + However, simply using C++ relaxed atomics for non-atomic accesses + and C++ SC atomics for atomic ones is not enough, since the OCaml + memory model is stronger. The prototypical example where C++ + exhibits a behaviour not allowed by OCaml is below. Assume that the + reference b and the atomic reference a are initially 0: + + Thread 1 Thread 2 + Atomic.set a 1; let x = !b in + b := 1 let y = Atomic.get a in + ... + Outcome: x = 1, y = 0 + + This outcome is not permitted by the OCaml memory model, as can be + seen from the operational model: if !b sees the write b := 1, then + the Atomic.set must have executed before the Atomic.get, and since + it is atomic the most recent set must be returned by the get, + yielding y = 1. In the equivalent axiomatic model, this would be a + violation of Causality. + + If this example is naively translated to C++ (using atomic_{load, + store} for atomics, and atomic_{load, store}_explicit(..., + memory_order_relaxed) for nonatomics), then this outcome becomes + possible. The C++ model specifies that there is a total order on SC + accesses, but this total order is surprisingly weak. In this + example, we can have: + + x = !b ... + [happens-before] + y = Atomic.get a + [SC-before] + Atomic.set a 1 + [happens-before] + b := 1 + + Sadly, the composition of happens-before and SC-before does not add + up to anything useful, and the C++ model permits the read 'x = !b' + to read from the write 'b := 1' in this example, allowing the + outcome above. + + To remedy this, we need to strengthen the relaxed accesses used for + non-atomic loads and stores. The most straightforward way to do + this is to use acquire loads and release stores instead of relaxed + for non-atomic accesses, which ensures that all reads-from edges + appear in the C++ synchronises-with relation, outlawing the outcome + above. + + Using release stores for all writes also ensures publication safety + for newly-allocated objects, and isn't necessary for initialising + writes. The cost is free on x86, but requires a fence in + caml_modify_field on weakly-ordered architectures (ARM, Power). + + However, instead of using acquire loads for all reads, an + optimisation is possible. (Optimising reads is more important than + optimising writes because reads are vastly more common). The OCaml + memory model does not require ordering between non-atomic reads, + which acquire loads provide. The acquire semantics are only + necessary between a non-atomic read and an atomic access or a + write, so we delay the acquire fence until one of those operations + occurs. + + So, our non-atomic reads (Field/caml_read_field in mlvalues.h) are + implemented as relaxed loads, but non-atomic writes and atomic + operations (in this file, below) contain an odd-looking line: + + atomic_thread_fence(memory_order_acquire) + + which serves to upgrade previous relaxed loads to acquire loads. + This encodes the OCaml memory model in the primitives provided by + the C++ model. + + On x86, all loads and all stores have acquire/release semantics by + default anyway, so all of these fences compile away to nothing + (They're still useful, though: they serve to inhibit an overeager C + compiler's optimisations). On ARMv8, actual hardware fences are + generated. */ -extern uintnat caml_percent_free; /* major_gc.c */ - -/* Page table management */ - -#define Page(p) ((uintnat) (p) >> Page_log) -#define Page_mask ((~(uintnat)0) << Page_log) - -#ifdef ARCH_SIXTYFOUR - -/* 64-bit implementation: - The page table is represented sparsely as a hash table - with linear probing */ - -struct page_table { - mlsize_t size; /* size == 1 << (wordsize - shift) */ - int shift; - mlsize_t mask; /* mask == size - 1 */ - mlsize_t occupancy; - uintnat * entries; /* [size] */ -}; - -static struct page_table caml_page_table; +__attribute__((always_inline)) inline static void write_barrier(value obj, intnat field, value old_val, value new_val) ; -/* Page table entries are the logical 'or' of - - the key: address of a page (low Page_log bits = 0) - - the data: a 8-bit integer */ - -#define Page_entry_matches(entry,addr) \ - ((((entry) ^ (addr)) & Page_mask) == 0) +/* The write barrier does not read or write the heap, it just + modifies domain-local data structures. */ +static void write_barrier(value obj, intnat field, value old_val, value new_val) +{ + /* HACK: can't assert when get old C-api style pointers + Assert (Is_block(obj)); */ -/* Multiplicative Fibonacci hashing - (Knuth, TAOCP vol 3, section 6.4, page 518). - HASH_FACTOR is (sqrt(5) - 1) / 2 * 2^wordsize. */ -#ifdef ARCH_SIXTYFOUR -#define HASH_FACTOR 11400714819323198486UL -#else -#define HASH_FACTOR 2654435769UL -#endif -#define Hash(v) (((v) * HASH_FACTOR) >> caml_page_table.shift) + if (!Is_young(obj)) { -int caml_page_table_lookup(void * addr) -{ - uintnat h, e; - - h = Hash(Page(addr)); - /* The first hit is almost always successful, so optimize for this case */ - e = caml_page_table.entries[h]; - if (Page_entry_matches(e, (uintnat)addr)) return e & 0xFF; - while(1) { - if (e == 0) return 0; - h = (h + 1) & caml_page_table.mask; - e = caml_page_table.entries[h]; - if (Page_entry_matches(e, (uintnat)addr)) return e & 0xFF; - } + if (Is_block(old_val)) { + /* if old is in the minor heap, then this is in a remembered set already */ + if (Is_young(old_val)) return; + /* old is a block and in the major heap */ + caml_darken(0, old_val, 0); + } + /* this update is creating a new link from major to minor, remember it */ + if (Is_block_and_young(new_val)) { + Ref_table_add(&Caml_state->minor_tables->major_ref, Op_val(obj) + field); + } + } } -int caml_page_table_initialize(mlsize_t bytesize) +CAMLexport void caml_modify_field (value obj, intnat field, value val) { - uintnat pagesize = Page(bytesize); - - caml_page_table.size = 1; - caml_page_table.shift = 8 * sizeof(uintnat); - /* Aim for initial load factor between 1/4 and 1/2 */ - while (caml_page_table.size < 2 * pagesize) { - caml_page_table.size <<= 1; - caml_page_table.shift -= 1; - } - caml_page_table.mask = caml_page_table.size - 1; - caml_page_table.occupancy = 0; - caml_page_table.entries = - caml_stat_calloc_noexc(caml_page_table.size, sizeof(uintnat)); - if (caml_page_table.entries == NULL) - return -1; - else - return 0; + Assert (Is_block(obj)); + Assert(field >= 0 && field < Wosize_val(obj)); + + write_barrier(obj, field, Op_val(obj)[field], val); +#if defined(COLLECT_STATS) && defined(NATIVE_CODE) + Caml_state->mutable_stores++; +#endif + /* See Note [MM] above */ + atomic_thread_fence(memory_order_acquire); + atomic_store_explicit(&Op_atomic_val(obj)[field], val, + memory_order_release); } -static int caml_page_table_resize(void) +/* Compatability with old C-API + bit of a HACK as less Assert possible here + */ +CAMLexport CAMLweakdef void caml_modify (value *fp, value val) { - struct page_table old = caml_page_table; - uintnat * new_entries; - uintnat i, h; - - caml_gc_message (0x08, "Growing page table to %" - ARCH_INTNAT_PRINTF_FORMAT "u entries\n", - caml_page_table.size); - - new_entries = caml_stat_calloc_noexc(2 * old.size, sizeof(uintnat)); - if (new_entries == NULL) { - caml_gc_message (0x08, "No room for growing page table\n"); - return -1; - } - - caml_page_table.size = 2 * old.size; - caml_page_table.shift = old.shift - 1; - caml_page_table.mask = caml_page_table.size - 1; - caml_page_table.occupancy = old.occupancy; - caml_page_table.entries = new_entries; - - for (i = 0; i < old.size; i++) { - uintnat e = old.entries[i]; - if (e == 0) continue; - h = Hash(Page(e)); - while (caml_page_table.entries[h] != 0) - h = (h + 1) & caml_page_table.mask; - caml_page_table.entries[h] = e; - } + write_barrier((value)fp, 0, *fp, val); + #if defined(COLLECT_STATS) && defined(NATIVE_CODE) + Caml_state->mutable_stores++; + #endif - caml_stat_free(old.entries); - return 0; + /* See Note [MM] above */ + atomic_thread_fence(memory_order_acquire); + atomic_store_explicit(&Op_atomic_val((value)fp)[0], val, + memory_order_release); } -static int caml_page_table_modify(uintnat page, int toclear, int toset) +CAMLexport void caml_initialize_field (value obj, intnat field, value val) { - uintnat h; - - CAMLassert ((page & ~Page_mask) == 0); + Assert(Is_block(obj)); + Assert(0 <= field && field < Wosize_val(obj)); +#ifdef DEBUG + /* caml_initialize_field can only be used on just-allocated objects */ + if (Is_young(obj)) + Assert(Op_val(obj)[field] == Debug_uninit_minor || + Op_val(obj)[field] == Val_unit); + else + Assert(Op_val(obj)[field] == Debug_uninit_major || + Op_val(obj)[field] == Val_unit); +#endif - /* Resize to keep load factor below 1/2 */ - if (caml_page_table.occupancy * 2 >= caml_page_table.size) { - if (caml_page_table_resize() != 0) return -1; - } - h = Hash(Page(page)); - while (1) { - if (caml_page_table.entries[h] == 0) { - caml_page_table.entries[h] = page | toset; - caml_page_table.occupancy++; - break; - } - if (Page_entry_matches(caml_page_table.entries[h], page)) { - caml_page_table.entries[h] = - (caml_page_table.entries[h] & ~toclear) | toset; - break; - } - h = (h + 1) & caml_page_table.mask; - } - return 0; + write_barrier(obj, field, Op_val(obj)[field], val); + Op_val(obj)[field] = val; } -#else - -/* 32-bit implementation: - The page table is represented as a 2-level array of unsigned char */ - -CAMLexport unsigned char * caml_page_table[Pagetable1_size]; -static unsigned char caml_page_table_empty[Pagetable2_size] = { 0, }; - -int caml_page_table_initialize(mlsize_t bytesize) +/* Compatability with old C-API + bit of a HACK as less Assert possible here + */ +CAMLexport CAMLweakdef void caml_initialize (value *fp, value val) { - int i; - for (i = 0; i < Pagetable1_size; i++) - caml_page_table[i] = caml_page_table_empty; - return 0; +#ifdef DEBUG + /* caml_initialize_field can only be used on just-allocated objects */ + if (Is_young((value)fp)) + Assert(*fp == Debug_uninit_minor || + *fp == Val_unit); + else + Assert(*fp == Debug_uninit_major || + *fp == Val_unit); +#endif + write_barrier((value)fp, 0, *fp, val); + *fp = val; } -static int caml_page_table_modify(uintnat page, int toclear, int toset) +CAMLexport int caml_atomic_cas_field (value obj, intnat field, value oldval, value newval) { - uintnat i = Pagetable_index1(page); - uintnat j = Pagetable_index2(page); - - if (caml_page_table[i] == caml_page_table_empty) { - unsigned char * new_tbl = caml_stat_calloc_noexc(Pagetable2_size, 1); - if (new_tbl == 0) return -1; - caml_page_table[i] = new_tbl; + if (caml_domain_alone()) { + /* non-atomic CAS since only this thread can access the object */ + value* p = &Op_val(obj)[field]; + if (*p == oldval) { + *p = newval; + write_barrier(obj, field, oldval, newval); + return 1; + } else { + return 0; + } + } else { + /* need a real CAS */ + atomic_value* p = &Op_atomic_val(obj)[field]; + if (atomic_compare_exchange_strong(p, &oldval, newval)) { + write_barrier(obj, field, oldval, newval); + return 1; + } else { + return 0; + } } - caml_page_table[i][j] = (caml_page_table[i][j] & ~toclear) | toset; - return 0; } -#endif -int caml_page_table_add(int kind, void * start, void * end) +CAMLprim value caml_atomic_load (value ref) { - uintnat pstart = (uintnat) start & Page_mask; - uintnat pend = ((uintnat) end - 1) & Page_mask; - uintnat p; - - for (p = pstart; p <= pend; p += Page_size) - if (caml_page_table_modify(p, 0, kind) != 0) return -1; - return 0; -} - -int caml_page_table_remove(int kind, void * start, void * end) -{ - uintnat pstart = (uintnat) start & Page_mask; - uintnat pend = ((uintnat) end - 1) & Page_mask; - uintnat p; - - for (p = pstart; p <= pend; p += Page_size) - if (caml_page_table_modify(p, kind, 0) != 0) return -1; - return 0; -} - -/* Allocate a block of the requested size, to be passed to - [caml_add_to_heap] later. - [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) -{ - 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_stat_alloc_aligned_noexc (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_domain_alone()) { + return Op_val(ref)[0]; + } else { + value v; + /* See Note [MM] above */ + atomic_thread_fence(memory_order_acquire); + v = atomic_load(Op_atomic_val(ref)); + return v; } } -/* Use this function if a block allocated with [caml_alloc_for_heap] is - not actually going to be added to the heap. The caller is responsible - for freeing it. */ -void caml_disown_for_heap (char* mem) +/* stores are implemented as exchanges */ +CAMLprim value caml_atomic_exchange (value ref, value v) { - /* Currently a no-op. */ - (void)mem; /* can CAMLunused_{start,end} be used here? */ -} - -/* Use this function to free a block allocated with [caml_alloc_for_heap] - if you don't add it with [caml_add_to_heap]. -*/ -void caml_free_for_heap (char *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{ - caml_stat_free (Chunk_block (mem)); + value ret; + if (caml_domain_alone()) { + ret = Op_val(ref)[0]; + Op_val(ref)[0] = v; + } else { + /* See Note [MM] above */ + atomic_thread_fence(memory_order_acquire); + ret = atomic_exchange(Op_atomic_val(ref), v); } + write_barrier(ref, 0, ret, v); + return ret; } -/* Take a chunk of memory as argument, which must be the result of a - call to [caml_alloc_for_heap], and insert it into the heap chaining. - The contents of the chunk must be a sequence of valid blocks and - fragments: no space between blocks and no trailing garbage. If - some blocks are blue, they must be added to the free list by the - caller. All other blocks must have the color [caml_allocation_color(m)]. - The caller must update [caml_allocated_words] if applicable. - Return value: 0 if no error; -1 in case of error. - - See also: caml_compact_heap, which duplicates most of this function. -*/ -int caml_add_to_heap (char *m) +CAMLprim value caml_atomic_cas (value ref, value oldv, value newv) { -#ifdef DEBUG - /* Should check the contents of the block. */ -#endif /* DEBUG */ - - caml_gc_message (0x04, "Growing heap to %" - ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n", - (Bsize_wsize (Caml_state->stat_heap_wsz) + Chunk_size (m)) / 1024); - - /* Register block in page table */ - if (caml_page_table_add(In_heap, m, m + Chunk_size(m)) != 0) - return -1; - - /* Chain this heap chunk. */ - { - char **last = &caml_heap_start; - char *cur = *last; - - while (cur != NULL && cur < m){ - last = &(Chunk_next (cur)); - cur = *last; + if (caml_domain_alone()) { + value* p = Op_val(ref); + if (*p == oldv) { + *p = newv; + write_barrier(ref, 0, oldv, newv); + return Val_int(1); + } else { + return Val_int(0); + } + } else { + atomic_value* p = &Op_atomic_val(ref)[0]; + if (atomic_compare_exchange_strong(p, &oldv, newv)) { + write_barrier(ref, 0, oldv, newv); + return Val_int(1); + } else { + return Val_int(0); } - Chunk_next (m) = cur; - *last = m; - - ++ Caml_state->stat_heap_chunks; } +} - Caml_state->stat_heap_wsz += Wsize_bsize (Chunk_size (m)); - if (Caml_state->stat_heap_wsz > Caml_state->stat_top_heap_wsz){ - Caml_state->stat_top_heap_wsz = Caml_state->stat_heap_wsz; - } - return 0; -} - -/* Allocate more memory from malloc for the heap. - Return a blue block of at least the requested size. - The blue block is chained to a sequence of blue blocks (through their - field 0); the last block of the chain is pointed by field 1 of the - first. There may be a fragment after the last block. - The caller must insert the blocks into the free list. - [request] is a number of words and must be less than or equal - to [Max_wosize]. - Return NULL when out of memory. -*/ -static value *expand_heap (mlsize_t request) +CAMLprim value caml_atomic_fetch_add (value ref, value incr) { - /* these point to headers, but we do arithmetic on them, hence [value *]. */ - value *mem, *hp, *prev; - asize_t over_request, malloc_request, remain; - - CAMLassert (request <= Max_wosize); - 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"); - return NULL; - } - 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){ - Hd_hp (hp) = Make_header (Max_wosize, 0, Caml_blue); -#ifdef DEBUG - caml_set_fields (Val_hp (hp), 0, Debug_free_major); -#endif - hp += Whsize_wosize (Max_wosize); - remain -= Whsize_wosize (Max_wosize); - Field (Val_hp (mem), 1) = Field (Val_hp (prev), 0) = Val_hp (hp); - prev = hp; - } - if (remain > 1){ - Hd_hp (hp) = Make_header (Wosize_whsize (remain), 0, Caml_blue); -#ifdef DEBUG - caml_set_fields (Val_hp (hp), 0, Debug_free_major); -#endif - Field (Val_hp (mem), 1) = Field (Val_hp (prev), 0) = Val_hp (hp); - Field (Val_hp (hp), 0) = (value) NULL; - }else{ - Field (Val_hp (prev), 0) = (value) NULL; - if (remain == 1) { - Hd_hp (hp) = Make_header_allocated_here (0, 0, Caml_white); - } - } - CAMLassert (Wosize_hp (mem) >= request); - if (caml_add_to_heap ((char *) mem) != 0){ - caml_free_for_heap ((char *) mem); - return NULL; + value ret; + if (caml_domain_alone()) { + value* p = Op_val(ref); + CAMLassert(Is_long(*p)); + ret = *p; + *p = Val_long(Long_val(ret) + Long_val(incr)); + /* no write barrier needed, integer write */ + } else { + atomic_value *p = &Op_atomic_val(ref)[0]; + ret = atomic_fetch_add(p, 2*Long_val(incr)); } - return Op_hp (mem); + return ret; } -/* Remove the heap chunk [chunk] from the heap and give the memory back - to [free]. -*/ -void caml_shrink_heap (char *chunk) +CAMLexport void caml_set_fields (value obj, value v) { - char **cp; - - /* Never deallocate the first chunk, because caml_heap_start is both the - first block and the base address for page numbers, and we don't - want to shift the page table, it's too messy (see above). - It will never happen anyway, because of the way compaction works. - (see compact.c) - XXX FIXME this has become false with the fix to PR#5389 (see compact.c) - */ - if (chunk == caml_heap_start) return; - - Caml_state->stat_heap_wsz -= Wsize_bsize (Chunk_size (chunk)); - caml_gc_message (0x04, "Shrinking heap to %" - ARCH_INTNAT_PRINTF_FORMAT "dk words\n", - Caml_state->stat_heap_wsz / 1024); + int i; + Assert (Is_block(obj)); -#ifdef DEBUG - { - mlsize_t i; - for (i = 0; i < Wsize_bsize (Chunk_size (chunk)); i++){ - ((value *) chunk) [i] = Debug_free_shrink; - } + for (i = 0; i < Wosize_val(obj); i++) { + caml_modify_field(obj, i, v); } -#endif - - -- Caml_state->stat_heap_chunks; - - /* Remove [chunk] from the list of chunks. */ - cp = &caml_heap_start; - while (*cp != chunk) cp = &(Chunk_next (*cp)); - *cp = Chunk_next (chunk); - - /* Remove the pages of [chunk] from the page table. */ - caml_page_table_remove(In_heap, chunk, chunk + Chunk_size (chunk)); - - /* Free the [malloc] block that contains [chunk]. */ - caml_free_for_heap (chunk); } -color_t caml_allocation_color (void *hp) +CAMLexport void caml_blit_fields (value src, int srcoff, value dst, int dstoff, int n) { - if (caml_gc_phase == Phase_mark || caml_gc_phase == Phase_clean || - (caml_gc_phase == Phase_sweep && (char *)hp >= (char *)caml_gc_sweep_hp)){ - return Caml_black; - }else{ - CAMLassert (caml_gc_phase == Phase_idle - || (caml_gc_phase == Phase_sweep - && (char *)hp < (char *)caml_gc_sweep_hp)); - return Caml_white; + CAMLparam2(src, dst); + CAMLlocal1(x); + int i; + Assert(Is_block(src)); + Assert(Is_block(dst)); + Assert(srcoff + n <= Wosize_val(src)); + Assert(dstoff + n <= Wosize_val(dst)); + Assert(Tag_val(src) != Infix_tag); + Assert(Tag_val(dst) != Infix_tag); + + /* we can't use memcpy/memmove since they may not do atomic word writes. + for instance, they may copy a byte at a time */ + if (src == dst && srcoff < dstoff) { + /* copy descending */ + for (i = n; i > 0; i--) { + caml_read_field(src, srcoff + i - 1, &x); + caml_modify_field(dst, dstoff + i - 1, x); + } + } else { + /* copy ascending */ + for (i = 0; i < n; i++) { + caml_read_field(src, srcoff + i, &x); + caml_modify_field(dst, dstoff + i, x); + } } + CAMLreturn0; } -Caml_inline value caml_alloc_shr_aux (mlsize_t wosize, tag_t tag, int track, - int raise_oom, uintnat profinfo) +Caml_inline value alloc_shr(mlsize_t wosize, tag_t tag, int noexc) { - header_t *hp; - value *new_block; - - if (wosize > Max_wosize) { - if (raise_oom) - caml_raise_out_of_memory (); + caml_domain_state *dom_st = Caml_state; + value *v = caml_shared_try_alloc(dom_st->shared_heap, wosize, tag, 0); + if (v == NULL) { + if (!noexc) + caml_raise_out_of_memory(); else - return 0; + return (value)NULL; } CAML_EV_ALLOC(wosize); - hp = caml_fl_allocate (wosize); - if (hp == NULL){ - new_block = expand_heap (wosize); - if (new_block == NULL) { - if (!raise_oom) - return 0; - else if (Caml_state->in_minor_collection) - caml_fatal_error ("out of memory"); - else - caml_raise_out_of_memory (); - } - caml_fl_add_blocks ((value) new_block); - hp = caml_fl_allocate (wosize); - } - - CAMLassert (Is_in_heap (Val_hp (hp))); - - /* Inline expansion of caml_allocation_color. */ - if (caml_gc_phase == Phase_mark || caml_gc_phase == Phase_clean || - (caml_gc_phase == Phase_sweep && (char *)hp >= (char *)caml_gc_sweep_hp)){ - Hd_hp (hp) = Make_header_with_profinfo (wosize, tag, Caml_black, profinfo); - }else{ - CAMLassert (caml_gc_phase == Phase_idle - || (caml_gc_phase == Phase_sweep - && (char *)hp < (char *)caml_gc_sweep_hp)); - Hd_hp (hp) = Make_header_with_profinfo (wosize, tag, Caml_white, profinfo); - } - CAMLassert (Hd_hp (hp) - == Make_header_with_profinfo (wosize, tag, caml_allocation_color (hp), - profinfo)); - caml_allocated_words += Whsize_wosize (wosize); - if (caml_allocated_words > Caml_state->minor_heap_wsz){ + dom_st->allocated_words += Whsize_wosize(wosize); + if (dom_st->allocated_words > dom_st->minor_heap_wsz) { CAML_EV_COUNTER (EV_C_REQUEST_MAJOR_ALLOC_SHR, 1); - caml_request_major_slice (); + caml_request_major_slice(); } + + if (tag < No_scan_tag) { + mlsize_t i; + for (i = 0; i < wosize; i++) { + value init_val = Val_unit; #ifdef DEBUG - { - uintnat i; - for (i = 0; i < wosize; i++){ - Field (Val_hp (hp), i) = Debug_uninit_major; + init_val = Debug_uninit_major; +#endif + Op_hp(v)[i] = init_val; } } +#if defined(COLLECT_STATS) && defined(NATIVE_CODE) + dom_st->allocations++; #endif - if(track) - caml_memprof_track_alloc_shr(Val_hp (hp)); - return Val_hp (hp); + return Val_hp(v); } -#ifdef WITH_PROFINFO - -/* Use this to debug problems with macros... */ -#define NO_PROFINFO 0xff - -CAMLexport value caml_alloc_shr_with_profinfo (mlsize_t wosize, tag_t tag, - intnat profinfo) +CAMLexport value caml_alloc_shr(mlsize_t wosize, tag_t tag) { - return caml_alloc_shr_aux(wosize, tag, 1, 1, profinfo); + return alloc_shr(wosize, tag, 0); } -CAMLexport value caml_alloc_shr_for_minor_gc (mlsize_t wosize, - tag_t tag, header_t old_header) -{ - return caml_alloc_shr_aux (wosize, tag, 0, 1, Profinfo_hd(old_header)); +CAMLexport value caml_alloc_shr_noexc(mlsize_t wosize, tag_t tag) { + return alloc_shr(wosize, tag, 1); } -#else -#define NO_PROFINFO 0 - -CAMLexport value caml_alloc_shr_for_minor_gc (mlsize_t wosize, - tag_t tag, header_t old_header) -{ - return caml_alloc_shr_aux (wosize, tag, 0, 1, NO_PROFINFO); +#ifdef DEBUG +header_t hd_val (value v) { + return (header_t)Hd_val(v); } -#endif /* WITH_PROFINFO */ - -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) -#include "caml/spacetime.h" -CAMLexport value caml_alloc_shr (mlsize_t wosize, tag_t tag) -{ - return caml_alloc_shr_with_profinfo (wosize, tag, - caml_spacetime_my_profinfo (NULL, wosize)); +int is_young(value v) { + return Is_young(v); } -CAMLexport value caml_alloc_shr_no_track_noexc (mlsize_t wosize, tag_t tag) -{ - return caml_alloc_shr_aux (wosize, tag, 0, 0, - caml_spacetime_my_profinfo (NULL, wosize)); -} -#else -CAMLexport value caml_alloc_shr (mlsize_t wosize, tag_t tag) -{ - return caml_alloc_shr_aux (wosize, tag, 1, 1, NO_PROFINFO); +int has_status(value v, status s) { + return Has_status_hd(Hd_val(v),s); } -CAMLexport value caml_alloc_shr_no_track_noexc (mlsize_t wosize, tag_t tag) -{ - return caml_alloc_shr_aux (wosize, tag, 0, 0, NO_PROFINFO); +int tag_val(value v) { + return (int)Tag_val(v); } #endif -/* Dependent memory is all memory blocks allocated out of the heap - that depend on the GC (and finalizers) for deallocation. - For the GC to take dependent memory into account when computing - its automatic speed setting, - you must call [caml_alloc_dependent_memory] when you allocate some - dependent memory, and [caml_free_dependent_memory] when you - free it. In both cases, you pass as argument the size (in bytes) - of the block being allocated or freed. -*/ -CAMLexport void caml_alloc_dependent_memory (mlsize_t nbytes) -{ - caml_dependent_size += nbytes / sizeof (value); - caml_dependent_allocated += nbytes / sizeof (value); -} - -CAMLexport void caml_free_dependent_memory (mlsize_t nbytes) -{ - if (caml_dependent_size < nbytes / sizeof (value)){ - caml_dependent_size = 0; - }else{ - caml_dependent_size -= nbytes / sizeof (value); - } -} - -/* Use this function to tell the major GC to speed up when you use - finalized blocks to automatically deallocate resources (other - than memory). The GC will do at least one cycle every [max] - allocated resources; [res] is the number of resources allocated - this time. - Note that only [res/max] is relevant. The units (and kind of - resource) can change between calls to [caml_adjust_gc_speed]. -*/ -CAMLexport void caml_adjust_gc_speed (mlsize_t res, mlsize_t max) -{ - if (max == 0) max = 1; - if (res > max) res = max; - caml_extra_heap_resources += (double) res / (double) max; - if (caml_extra_heap_resources > 1.0){ - CAML_EV_COUNTER (EV_C_REQUEST_MAJOR_ADJUST_GC_SPEED, 1); - caml_extra_heap_resources = 1.0; - caml_request_major_slice (); - } -} - -/* You must use [caml_initialize] to store the initial value in a field of - a shared block, unless you are sure the value is not a young block. - A block value [v] is a shared block if and only if [Is_in_heap (v)] - is true. -*/ -/* [caml_initialize] never calls the GC, so you may call it while a block is - unfinished (i.e. just after a call to [caml_alloc_shr].) */ -/* PR#6084 workaround: define it as a weak symbol */ -CAMLexport CAMLweakdef void caml_initialize (value *fp, value val) -{ - CAMLassert(Is_in_heap_or_young(fp)); - *fp = val; - if (!Is_young((value)fp) && Is_block (val) && Is_young (val)) { - add_to_ref_table (Caml_state->ref_table, fp); - } -} - -/* You must use [caml_modify] to change a field of an existing shared block, - unless you are sure the value being overwritten is not a shared block and - the value being written is not a young block. */ -/* [caml_modify] never calls the GC. */ -/* [caml_modify] can also be used to do assignment on data structures that are - in the minor heap instead of in the major heap. In this case, it - is a bit slower than simple assignment. - In particular, you can use [caml_modify] when you don't know whether the - block being changed is in the minor heap or the major heap. */ -/* PR#6084 workaround: define it as a weak symbol */ - -CAMLexport CAMLweakdef void caml_modify (value *fp, value val) -{ - /* The write barrier implemented by [caml_modify] checks for the - following two conditions and takes appropriate action: - 1- a pointer from the major heap to the minor heap is created - --> add [fp] to the remembered set - 2- a pointer from the major heap to the major heap is overwritten, - while the GC is in the marking phase - --> call [caml_darken] on the overwritten pointer so that the - major GC treats it as an additional root. - - The logic implemented below is duplicated in caml_array_fill to - avoid repeated calls to caml_modify and repeated tests on the - values. Don't forget to update caml_array_fill if the logic - below changes! - */ - value old; - - if (Is_young((value)fp)) { - /* The modified object resides in the minor heap. - Conditions 1 and 2 cannot occur. */ - *fp = val; - } else { - /* The modified object resides in the major heap. */ - CAMLassert(Is_in_heap(fp)); - old = *fp; - *fp = val; - if (Is_block(old)) { - /* If [old] is a pointer within the minor heap, we already - have a major->minor pointer and [fp] is already in the - remembered set. Conditions 1 and 2 cannot occur. */ - if (Is_young(old)) return; - /* Here, [old] can be a pointer within the major heap. - Check for condition 2. */ - if (caml_gc_phase == Phase_mark) caml_darken(old, NULL); - } - /* Check for condition 1. */ - if (Is_block(val) && Is_young(val)) { - add_to_ref_table (Caml_state->ref_table, fp); - } - } -} - - /* Global memory pool. The pool is structured as a ring of blocks, where each block's header @@ -748,7 +457,7 @@ struct pool_block { #endif static struct pool_block *pool = NULL; - +static caml_plat_mutex pool_mutex = CAML_PLAT_MUTEX_INITIALIZER; /* Returns a pointer to the block header, given a pointer to "data" */ static struct pool_block* get_pool_block(caml_stat_block b) @@ -771,7 +480,7 @@ CAMLexport void caml_stat_create_pool(void) if (pool == NULL) { pool = malloc(SIZEOF_POOL_BLOCK); if (pool == NULL) - caml_fatal_error("out of memory"); + caml_fatal_error("Fatal error: out of memory.\n"); #ifdef DEBUG pool->magic = Debug_pool_magic; #endif @@ -782,6 +491,7 @@ CAMLexport void caml_stat_create_pool(void) CAMLexport void caml_stat_destroy_pool(void) { + caml_plat_lock(&pool_mutex); if (pool != NULL) { pool->prev->next = NULL; while (pool != NULL) { @@ -791,6 +501,33 @@ CAMLexport void caml_stat_destroy_pool(void) } pool = NULL; } + caml_plat_unlock(&pool_mutex); +} + +/* [sz] is a number of bytes */ +CAMLexport caml_stat_block caml_stat_alloc_noexc(asize_t sz) +{ + /* Backward compatibility mode */ + if (pool == NULL) + return malloc(sz); + else { + struct pool_block *pb = malloc(sz + SIZEOF_POOL_BLOCK); + if (pb == NULL) return NULL; +#ifdef DEBUG + memset(&(pb->data), Debug_uninit_stat, sz); + pb->magic = Debug_pool_magic; +#endif + + /* Linking the block into the ring */ + caml_plat_lock(&pool_mutex); + pb->next = pool->next; + pb->prev = pool; + pool->next->prev = pb; + pool->next = pb; + caml_plat_unlock(&pool_mutex); + + return &(pb->data); + } } /* [sz] and [modulo] are numbers of bytes */ @@ -832,30 +569,6 @@ CAMLexport void* caml_stat_alloc_aligned(asize_t sz, int modulo, } /* [sz] is a number of bytes */ -CAMLexport caml_stat_block caml_stat_alloc_noexc(asize_t sz) -{ - /* Backward compatibility mode */ - if (pool == NULL) - return malloc(sz); - else { - struct pool_block *pb = malloc(sz + SIZEOF_POOL_BLOCK); - if (pb == NULL) return NULL; -#ifdef DEBUG - memset(&(pb->data), Debug_uninit_stat, sz); - pb->magic = Debug_pool_magic; -#endif - - /* Linking the block into the ring */ - pb->next = pool->next; - pb->prev = pool; - pool->next->prev = pb; - pool->next = pb; - - return &(pb->data); - } -} - -/* [sz] is a number of bytes */ CAMLexport caml_stat_block caml_stat_alloc(asize_t sz) { void *result = caml_stat_alloc_noexc(sz); @@ -875,8 +588,10 @@ CAMLexport void caml_stat_free(caml_stat_block b) if (pb == NULL) return; /* Unlinking the block from the ring */ + caml_plat_lock(&pool_mutex); pb->prev->next = pb->next; pb->next->prev = pb->prev; + caml_plat_unlock(&pool_mutex); free(pb); } @@ -896,8 +611,10 @@ CAMLexport caml_stat_block caml_stat_resize_noexc(caml_stat_block b, asize_t sz) if (pb_new == NULL) return NULL; /* Relinking the new block into the ring in place of the old one */ + caml_plat_lock(&pool_mutex); pb_new->prev->next = pb_new; pb_new->next->prev = pb_new; + caml_plat_unlock(&pool_mutex); return &(pb_new->data); } diff --git a/runtime/meta.c b/runtime/meta.c index cbacc9a03d..b092a8718d 100644 --- a/runtime/meta.c +++ b/runtime/meta.c @@ -24,6 +24,7 @@ #include "caml/config.h" #include "caml/debugger.h" #include "caml/fail.h" +#include "caml/fiber.h" #include "caml/fix_code.h" #include "caml/interp.h" #include "caml/intext.h" @@ -33,31 +34,27 @@ #include "caml/misc.h" #include "caml/mlvalues.h" #include "caml/prims.h" -#include "caml/signals.h" -#include "caml/stacks.h" +#include "caml/startup_aux.h" #ifndef NATIVE_CODE CAMLprim value caml_get_global_data(value unit) { - return caml_global_data; + return caml_read_root(caml_global_data); } -char * caml_section_table = NULL; -asize_t caml_section_table_size; - CAMLprim value caml_get_section_table(value unit) { - if (caml_section_table == NULL) caml_raise_not_found(); - return caml_input_value_from_block(caml_section_table, - caml_section_table_size); + if (caml_params->section_table == NULL) caml_raise_not_found(); + return caml_input_value_from_block(caml_params->section_table, + caml_params->section_table_size); } struct bytecode { code_t prog; asize_t len; }; -#define Bytecode_val(p) ((struct bytecode*)Data_abstract_val(p)) +#define Bc_val(p) ((struct bytecode*)Data_abstract_val(p)) /* Convert a bytes array (= LongString.t) to a contiguous buffer. The result is allocated with caml_stat_alloc */ @@ -121,15 +118,19 @@ CAMLprim value caml_reify_bytecode(value ls_prog, caml_thread_code((code_t) prog, len); #endif +#if 0 + /* TODO: support dynlink debugger: PR8654 */ /* Notify debugger after fragment gets added and reified. */ caml_debugger(CODE_LOADED, Val_long(fragnum)); +#endif + (void)fragnum; /* clobber warning */ clos = caml_alloc_small (2, Closure_tag); - Code_val(clos) = (code_t) prog; + Field(clos, 0) = Val_bytecode(prog); Closinfo_val(clos) = Make_closinfo(0, 2); bytecode = caml_alloc_small (2, Abstract_tag); - Bytecode_val(bytecode)->prog = prog; - Bytecode_val(bytecode)->len = len; + Bc_val(bytecode)->prog = prog; + Bc_val(bytecode)->len = len; retval = caml_alloc_small (2, 0); Field(retval, 0) = bytecode; Field(retval, 1) = clos; @@ -144,7 +145,7 @@ CAMLprim value caml_static_release_bytecode(value bc) code_t prog; struct code_fragment *cf; - prog = Bytecode_val(bc)->prog; + prog = Bc_val(bc)->prog; caml_remove_debug_info(prog); cf = caml_find_code_fragment_by_pc((char *) prog); @@ -161,11 +162,13 @@ CAMLprim value caml_static_release_bytecode(value bc) CAMLprim value caml_realloc_global(value size) { + CAMLparam1(size); + CAMLlocal2(old_global_data, new_global_data); mlsize_t requested_size, actual_size, i; - value new_global_data; + old_global_data = caml_read_root(caml_global_data); requested_size = Long_val(size); - actual_size = Wosize_val(caml_global_data); + actual_size = Wosize_val(old_global_data); if (requested_size >= actual_size) { requested_size = (requested_size + 0x100) & 0xFFFFFF00; caml_gc_message (0x08, "Growing global data to %" @@ -173,20 +176,18 @@ CAMLprim value caml_realloc_global(value size) requested_size); new_global_data = caml_alloc_shr(requested_size, 0); for (i = 0; i < actual_size; i++) - caml_initialize(&Field(new_global_data, i), Field(caml_global_data, i)); + caml_initialize(&Field(new_global_data, i), Field(old_global_data, i)); for (i = actual_size; i < requested_size; i++){ Field (new_global_data, i) = Val_long (0); } - // Give gc a chance to run, and run memprof callbacks - caml_global_data = new_global_data; - caml_process_pending_actions(); + caml_modify_root(caml_global_data, new_global_data); } - return Val_unit; + CAMLreturn (Val_unit); } CAMLprim value caml_get_current_environment(value unit) { - return *Caml_state->extern_sp; + return *Caml_state->current_stack->sp; } CAMLprim value caml_invoke_traced_function(value codeptr, value env, value arg) @@ -219,9 +220,9 @@ CAMLprim value caml_invoke_traced_function(value codeptr, value env, value arg) value * osp, * nsp; int i; - osp = Caml_state->extern_sp; - Caml_state->extern_sp -= 4; - nsp = Caml_state->extern_sp; + osp = Caml_state->current_stack->sp; + Caml_state->current_stack->sp -= 4; + nsp = Caml_state->current_stack->sp; for (i = 0; i < 7; i++) nsp[i] = osp[i]; nsp[7] = (value) Nativeint_val(codeptr); nsp[8] = env; @@ -270,4 +271,6 @@ value caml_static_release_bytecode(value prog, value len) return Val_unit; /* not reached */ } +void (* volatile caml_async_action_hook)(void); + #endif diff --git a/runtime/minor_gc.c b/runtime/minor_gc.c index b8661bc7e2..09981635df 100644 --- a/runtime/minor_gc.c +++ b/runtime/minor_gc.c @@ -16,76 +16,42 @@ #define CAML_INTERNALS #include <string.h> -#include "caml/custom.h" +#include <stdio.h> + +#include "caml/addrmap.h" #include "caml/config.h" +#include "caml/custom.h" +#include "caml/domain.h" +#include "caml/eventlog.h" #include "caml/fail.h" +#include "caml/fiber.h" #include "caml/finalise.h" #include "caml/gc.h" #include "caml/gc_ctrl.h" +#include "caml/globroots.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/platform.h" #include "caml/roots.h" +#include "caml/shared_heap.h" #include "caml/signals.h" +#include "caml/startup_aux.h" #include "caml/weak.h" -#include "caml/memprof.h" -#ifdef WITH_SPACETIME -#include "caml/spacetime.h" -#endif -#include "caml/eventlog.h" - -/* Pointers into the minor heap. - [Caml_state->young_base] - The [malloc] block that contains the heap. - [Caml_state->young_start] ... [Caml_state->young_end] - The whole range of the minor heap: all young blocks are inside - this interval. - [Caml_state->young_alloc_start]...[Caml_state->young_alloc_end] - The allocation arena: newly-allocated blocks are carved from - this interval, starting at [Caml_state->young_alloc_end]. - [Caml_state->young_alloc_mid] is the mid-point of this interval. - [Caml_state->young_ptr], [Caml_state->young_trigger], - [Caml_state->young_limit] - These pointers are all inside the allocation arena. - - [Caml_state->young_ptr] is where the next allocation will take place. - - [Caml_state->young_trigger] is how far we can allocate before - triggering [caml_gc_dispatch]. Currently, it is either - [Caml_state->young_alloc_start] or the mid-point of the allocation - arena. - - [Caml_state->young_limit] is the pointer that is compared to - [Caml_state->young_ptr] for allocation. It is either: - + [Caml_state->young_alloc_end] if a signal handler or - finaliser or memprof callback is pending, or if a major - or minor collection has been requested, or an - asynchronous callback has just raised an exception, - + [caml_memprof_young_trigger] if a memprof sample is planned, - + or [Caml_state->young_trigger]. -*/ +extern value caml_ephe_none; /* See weak.c */ struct generic_table CAML_TABLE_STRUCT(char); -void caml_alloc_minor_tables () -{ - Caml_state->ref_table = - caml_stat_alloc_noexc(sizeof(struct caml_ref_table)); - if (Caml_state->ref_table == NULL) - caml_fatal_error ("cannot initialize minor heap"); - memset(Caml_state->ref_table, 0, sizeof(struct caml_ref_table)); +static atomic_intnat domains_finished_minor_gc; +static atomic_intnat domain_finished_root; - Caml_state->ephe_ref_table = - caml_stat_alloc_noexc(sizeof(struct caml_ephe_ref_table)); - if (Caml_state->ephe_ref_table == NULL) - caml_fatal_error ("cannot initialize minor heap"); - memset(Caml_state->ephe_ref_table, 0, sizeof(struct caml_ephe_ref_table)); +static atomic_uintnat caml_minor_cycles_started = 0; - Caml_state->custom_table = - caml_stat_alloc_noexc(sizeof(struct caml_custom_table)); - if (Caml_state->custom_table == NULL) - caml_fatal_error ("cannot initialize minor heap"); - memset(Caml_state->custom_table, 0, sizeof(struct caml_custom_table)); -} +static caml_plat_mutex global_roots_lock = CAML_PLAT_MUTEX_INITIALIZER; + +double caml_extra_heap_resources_minor = 0; /* [sz] and [rsv] are numbers of entries */ static void alloc_generic_table (struct generic_table *tbl, asize_t sz, @@ -111,20 +77,6 @@ void caml_alloc_table (struct caml_ref_table *tbl, asize_t sz, asize_t rsv) alloc_generic_table ((struct generic_table *) tbl, sz, rsv, sizeof (value *)); } -void caml_alloc_ephe_table (struct caml_ephe_ref_table *tbl, asize_t sz, - asize_t rsv) -{ - alloc_generic_table ((struct generic_table *) tbl, sz, rsv, - sizeof (struct caml_ephe_ref_elt)); -} - -void caml_alloc_custom_table (struct caml_custom_table *tbl, asize_t sz, - asize_t rsv) -{ - alloc_generic_table ((struct generic_table *) tbl, sz, rsv, - sizeof (struct caml_custom_elt)); -} - static void reset_table (struct generic_table *tbl) { tbl->size = 0; @@ -139,437 +91,740 @@ static void clear_table (struct generic_table *tbl) tbl->limit = tbl->threshold; } -void caml_set_minor_heap_size (asize_t bsz) +struct caml_minor_tables* caml_alloc_minor_tables() +{ + struct caml_minor_tables *r = + caml_stat_alloc_noexc(sizeof(struct caml_minor_tables)); + if(r != NULL) + memset(r, 0, sizeof(*r)); + return r; +} + +void reset_minor_tables(struct caml_minor_tables* r) +{ + reset_table((struct generic_table *)&r->major_ref); + reset_table((struct generic_table *)&r->ephe_ref); + reset_table((struct generic_table *)&r->custom); +} + +void caml_free_minor_tables(struct caml_minor_tables* r) { - char *new_heap; - void *new_heap_base; - - CAMLassert (bsz >= Bsize_wsize(Minor_heap_min)); - CAMLassert (bsz <= Bsize_wsize(Minor_heap_max)); - CAMLassert (bsz % Page_size == 0); - CAMLassert (bsz % sizeof (value) == 0); - if (Caml_state->young_ptr != Caml_state->young_alloc_end){ - CAML_EV_COUNTER (EV_C_FORCE_MINOR_SET_MINOR_HEAP_SIZE, 1); - Caml_state->requested_minor_gc = 0; - Caml_state->young_trigger = Caml_state->young_alloc_mid; - caml_update_young_limit(); - caml_empty_minor_heap (); + CAMLassert(r->major_ref.ptr == r->major_ref.base); + + reset_minor_tables(r); + caml_stat_free(r); +} + +#ifdef DEBUG +extern int caml_debug_is_minor(value val) { + return Is_young(val); +} + +extern int caml_debug_is_major(value val) { + return Is_block(val) && !Is_young(val); +} +#endif + +void caml_set_minor_heap_size (asize_t wsize) +{ + caml_domain_state* domain_state = Caml_state; + struct caml_minor_tables *r = domain_state->minor_tables; + if (domain_state->young_ptr != domain_state->young_end) caml_minor_collection (); + + if(caml_reallocate_minor_heap(wsize) < 0) { + caml_fatal_error("Fatal error: No memory for minor heap"); } - CAMLassert (Caml_state->young_ptr == Caml_state->young_alloc_end); - new_heap = caml_stat_alloc_aligned_noexc(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 + bsz) != 0) - caml_raise_out_of_memory(); - - if (Caml_state->young_start != NULL){ - caml_page_table_remove(In_young, Caml_state->young_start, - Caml_state->young_end); - caml_stat_free (Caml_state->young_base); + + reset_minor_tables(r); +} + +//***************************************************************************** + +struct oldify_state { + value todo_list; + uintnat live_bytes; + struct domain* promote_domain; +}; + +static value alloc_shared(mlsize_t wosize, tag_t tag) +{ + void* mem = caml_shared_try_alloc(Caml_state->shared_heap, wosize, tag, + 0 /* not pinned */); + Caml_state->allocated_words += Whsize_wosize(wosize); + if (mem == NULL) { + caml_fatal_error("allocation failure during minor GC"); } - Caml_state->young_base = new_heap_base; - Caml_state->young_start = (value *) new_heap; - Caml_state->young_end = (value *) (new_heap + bsz); - Caml_state->young_alloc_start = Caml_state->young_start; - Caml_state->young_alloc_mid = - Caml_state->young_alloc_start + Wsize_bsize (bsz) / 2; - Caml_state->young_alloc_end = Caml_state->young_end; - Caml_state->young_trigger = Caml_state->young_alloc_start; - caml_update_young_limit(); - Caml_state->young_ptr = Caml_state->young_alloc_end; - Caml_state->minor_heap_wsz = Wsize_bsize (bsz); - caml_memprof_renew_minor_sample(); - - reset_table ((struct generic_table *) Caml_state->ref_table); - reset_table ((struct generic_table *) Caml_state->ephe_ref_table); - reset_table ((struct generic_table *) Caml_state->custom_table); -} - -static value oldify_todo_list = 0; + return Val_hp(mem); +} + +#if 0 +static inline void log_gc_value(const char* prefix, value v) +{ + if (Is_block(v)) { + header_t hd = Hd_val(v); + int sz = Wosize_hd (hd); + caml_gc_log("%s 0x%lx hd=0x%lx tag=%d sz=%d", prefix, v, hd, Tag_val(v), sz); + } else { + caml_gc_log("%s not block 0x%lx", prefix, v); + } +} +#endif + +/* in progress updates are zeros except for the lowest color bit set to 1 + that is a header with: wosize == 0 && color == 1 && tag == 0 */ +#define In_progress_update_val ((header_t)0x100) +#define Is_update_in_progress(hd) ((hd) == In_progress_update_val) + +/* TODO: Probably a better spinlock needed here though doesn't happen often */ +static void spin_on_header(value v) { + SPIN_WAIT { + if (atomic_load(Hp_atomic_val(v)) == 0) + return; + } +} + +static inline header_t get_header_val(value v) { + header_t hd = atomic_load_explicit(Hp_atomic_val(v), memory_order_relaxed); + if (!Is_update_in_progress(hd)) + return hd; + + spin_on_header(v); + return 0; +} + +header_t caml_get_header_val(value v) { + return get_header_val(v); +} + +static int try_update_object_header(value v, value *p, value result, mlsize_t infix_offset) { + int success = 0; + + if( caml_domain_alone() ) { + *Hp_val (v) = 0; + Op_val(v)[0] = result; + success = 1; + } else { + header_t hd = atomic_load(Hp_atomic_val(v)); + if( hd == 0 ) { + // in this case this has been updated by another domain, throw away result + // and return the one in the object + result = Op_val(v)[0]; + } else if( Is_update_in_progress(hd) ) { + // here we've caught a domain in the process of moving a minor heap object + // we need to wait for it to finish + spin_on_header(v); + // Also throw away result and use the one from the other domain + result = Op_val(v)[0]; + } else { + // Here the header is neither zero nor an in-progress update + header_t desired_hd = In_progress_update_val; + if( atomic_compare_exchange_strong(Hp_atomic_val(v), &hd, desired_hd) ) { + // Success + // Now we can write the forwarding pointer + atomic_store_explicit(Op_atomic_val(v), result, memory_order_relaxed); + // And update header ('release' to ensure after update of fwd pointer) + atomic_store_explicit(Hp_atomic_val(v), 0, memory_order_release); + // Let the caller know we were responsible for the update + success = 1; + } else { + // We were sniped by another domain, spin for that to complete then + // throw away result and use the one from the other domain + spin_on_header(v); + result = Op_val(v)[0]; + } + } + } + + *p = result + infix_offset; + return success; +} + +/* If [*v] is an [Infix_tag] object, [v] is updated to point to the first + * object in the block. */ +static inline void resolve_infix_val (value* v) +{ + int offset = 0; + if (get_header_val(*v) == Infix_tag) { + offset = Infix_offset_val(*v); + CAMLassert (offset > 0); + *v -= offset; + } +} /* Note that the tests on the tag depend on the fact that Infix_tag, Forward_tag, and No_scan_tag are contiguous. */ - -void caml_oldify_one (value v, value *p) +static void oldify_one (void* st_v, value v, value *p) { + struct oldify_state* st = st_v; value result; header_t hd; mlsize_t sz, i; + mlsize_t infix_offset; tag_t tag; - tail_call: - if (Is_block (v) && Is_young (v)){ - CAMLassert ((value *) Hp_val (v) >= Caml_state->young_ptr); - hd = Hd_val (v); - if (hd == 0){ /* If already forwarded */ - *p = Field (v, 0); /* then forward pointer is first field. */ - }else{ - CAMLassert_young_header(hd); - tag = Tag_hd (hd); - if (tag < Infix_tag){ - value field0; - - sz = Wosize_hd (hd); - result = caml_alloc_shr_for_minor_gc (sz, tag, hd); - *p = result; - field0 = Field (v, 0); - Hd_val (v) = 0; /* Set forward flag */ - Field (v, 0) = result; /* and forward pointer. */ - if (sz > 1){ - Field (result, 0) = field0; - Field (result, 1) = oldify_todo_list; /* Add this block */ - oldify_todo_list = v; /* to the "to do" list. */ - }else{ - CAMLassert (sz == 1); - p = &Field (result, 0); - v = field0; - goto tail_call; - } - }else if (tag >= No_scan_tag){ - sz = Wosize_hd (hd); - result = caml_alloc_shr_for_minor_gc (sz, tag, hd); - for (i = 0; i < sz; i++) Field (result, i) = Field (v, i); - Hd_val (v) = 0; /* Set forward flag */ - Field (v, 0) = result; /* and forward pointer. */ - *p = result; - }else if (tag == Infix_tag){ - mlsize_t offset = Infix_offset_hd (hd); - caml_oldify_one (v - offset, p); /* Cannot recurse deeper than 1. */ - *p += offset; - }else{ - value f = Forward_val (v); - tag_t ft = 0; - int vv = 1; - - CAMLassert (tag == Forward_tag); - if (Is_block (f)){ - if (Is_young (f)){ - vv = 1; - ft = Tag_val (Hd_val (f) == 0 ? Field (f, 0) : f); - }else{ - vv = Is_in_value_area(f); - if (vv){ - ft = Tag_val (f); - } - } - } - if (!vv || ft == Forward_tag || ft == Lazy_tag -#ifdef FLAT_FLOAT_ARRAY - || ft == Double_tag -#endif - ){ - /* Do not short-circuit the pointer. Copy as a normal block. */ - CAMLassert (Wosize_hd (hd) == 1); - result = caml_alloc_shr_for_minor_gc (1, Forward_tag, hd); - *p = result; - Hd_val (v) = 0; /* Set (GC) forward flag */ - Field (v, 0) = result; /* and forward pointer. */ - p = &Field (result, 0); - v = f; - goto tail_call; - }else{ - v = f; /* Follow the forwarding */ - goto tail_call; /* then oldify. */ + tail_call: + if (!(Is_block(v) && Is_young(v))) { + /* not a minor block */ + *p = v; + return; + } + + infix_offset = 0; + do { + hd = get_header_val(v); + if (hd == 0) { + /* already forwarded, another domain is likely working on this. */ + *p = Op_val(v)[0] + infix_offset; + return; + } + tag = Tag_hd (hd); + if (tag == Infix_tag) { + /* Infix header, retry with the real block */ + CAMLassert (infix_offset == 0); + infix_offset = Infix_offset_hd (hd); + CAMLassert(infix_offset > 0); + v -= infix_offset; + } + } while (tag == Infix_tag); + + if (tag == Cont_tag) { + value stack_value = Op_val(v)[0]; + CAMLassert(Wosize_hd(hd) == 1 && infix_offset == 0); + result = alloc_shared(1, Cont_tag); + if( try_update_object_header(v, p, result, 0) ) { + struct stack_info* stk = Ptr_val(stack_value); + Op_val(result)[0] = Val_ptr(stk); + if (stk != NULL) { + caml_scan_stack(&oldify_one, st, stk, 0); + } + } + else + { + // Conflict - fix up what we allocated on the major heap + *Hp_val(result) = Make_header(1, No_scan_tag, global.MARKED); + #ifdef DEBUG + Op_val(result)[0] = Val_long(1); + #endif + } + } else if (tag < Infix_tag) { + value field0; + sz = Wosize_hd (hd); + st->live_bytes += Bhsize_hd(hd); + result = alloc_shared (sz, tag); + field0 = Op_val(v)[0]; + if( try_update_object_header(v, p, result, infix_offset) ) { + if (sz > 1){ + Op_val (result)[0] = field0; + Op_val (result)[1] = st->todo_list; + st->todo_list = v; + } else { + CAMLassert (sz == 1); + p = Op_val(result); + v = field0; + goto tail_call; + } + } else { + // Conflict - fix up what we allocated on the major heap + *Hp_val(result) = Make_header(sz, No_scan_tag, global.MARKED); + #ifdef DEBUG + { + int c; + for( c = 0; c < sz ; c++ ) { + Op_val(result)[c] = Val_long(1); } } + #endif + } + + } else if (tag >= No_scan_tag) { + sz = Wosize_hd (hd); + st->live_bytes += Bhsize_hd(hd); + result = alloc_shared(sz, tag); + for (i = 0; i < sz; i++) { + value curr = Op_val(v)[i]; + Op_val (result)[i] = curr; + } + CAMLassert (infix_offset == 0); + if( !try_update_object_header(v, p, result, 0) ) { + // Conflict + *Hp_val(result) = Make_header(sz, No_scan_tag, global.MARKED); + #ifdef DEBUG + for( i = 0; i < sz ; i++ ) { + Op_val(result)[i] = Val_long(1); + } + #endif + } + } else { + value f; + tag_t ft; + CAMLassert (tag == Forward_tag); + CAMLassert (infix_offset == 0); + + f = Forward_val (v); + ft = 0; + + if (Is_block (f)) { + ft = Tag_val (get_header_val(f) == 0 ? Op_val (f)[0] : f); + } + + if (ft == Forward_tag || ft == Lazy_tag || ft == Double_tag) { + /* Do not short-circuit the pointer. Copy as a normal block. */ + CAMLassert (Wosize_hd (hd) == 1); + st->live_bytes += Bhsize_hd(hd); + result = alloc_shared (1, Forward_tag); + if( try_update_object_header(v, p, result, 0) ) { + p = Op_val (result); + v = f; + goto tail_call; + } else { + *Hp_val(result) = Make_header(1, No_scan_tag, global.MARKED); + #ifdef DEBUG + Op_val(result)[0] = Val_long(1); + #endif + } + } else { + v = f; /* Follow the forwarding */ + goto tail_call; /* then oldify. */ } - }else{ - *p = v; } } -/* Test if the ephemeron is alive, everything outside minor heap is alive */ -Caml_inline int ephe_check_alive_data(struct caml_ephe_ref_elt *re){ +#if 0 +/* Test if the ephemeron is alive */ +/* Care needed with this test. It will only make sense if + all minor heaps have been promoted + as the liveness of the keys can only be known at that point */ +static inline int ephe_check_alive_data (struct caml_ephe_ref_elt *re) +{ mlsize_t i; value child; - for (i = CAML_EPHE_FIRST_KEY; i < Wosize_val(re->ephe); i++){ - child = Field (re->ephe, i); - if(child != caml_ephe_none - && Is_block (child) && Is_young (child) - && Hd_val (child) != 0){ /* Value not copied to major heap */ - return 0; + + for (i = CAML_EPHE_FIRST_KEY; i < Wosize_val(re->ephe); i++) { + child = Op_val(re->ephe)[i]; + if (child != caml_ephe_none + && Is_block (child) && Is_young(child)) { + resolve_infix_val(&child); + if (get_header_val(child) != 0) { + /* value not copied to major heap */ + return 0; + } } } + return 1; } +#endif -/* Finish the work that was put off by [caml_oldify_one]. - Note that [caml_oldify_one] itself is called by oldify_mopup, so we +/* Finish the work that was put off by [oldify_one]. + Note that [oldify_one] itself is called by oldify_mopup, so we have to be careful to remove the first entry from the list before oldifying its fields. */ -void caml_oldify_mopup (void) +static void oldify_mopup (struct oldify_state* st, int do_ephemerons) { value v, new_v, f; mlsize_t i; + caml_domain_state* domain_state = + st->promote_domain ? st->promote_domain->state : Caml_state; + struct caml_ephe_ref_table ephe_ref_table = domain_state->minor_tables->ephe_ref; struct caml_ephe_ref_elt *re; int redo = 0; - while (oldify_todo_list != 0){ - v = oldify_todo_list; /* Get the head. */ - CAMLassert (Hd_val (v) == 0); /* It must be forwarded. */ - new_v = Field (v, 0); /* Follow forward pointer. */ - oldify_todo_list = Field (new_v, 1); /* Remove from list. */ - - f = Field (new_v, 0); - if (Is_block (f) && Is_young (f)){ - caml_oldify_one (f, &Field (new_v, 0)); + while (st->todo_list != 0) { + v = st->todo_list; /* Get the head. */ + /* I'm not convinced we can ever have something in todo_list that was updated + by another domain, so this assert using get_header_val is probably not + neccessary */ + CAMLassert (get_header_val(v) == 0); /* It must be forwarded. */ + new_v = Op_val (v)[0]; /* Follow forward pointer. */ + st->todo_list = Op_val (new_v)[1]; /* Remove from list. */ + + f = Op_val (new_v)[0]; + CAMLassert (!Is_debug_tag(f)); + if (Is_block (f) && Is_young(f)) { + oldify_one (st, f, Op_val (new_v)); } for (i = 1; i < Wosize_val (new_v); i++){ - f = Field (v, i); - if (Is_block (f) && Is_young (f)){ - caml_oldify_one (f, &Field (new_v, i)); - }else{ - Field (new_v, i) = f; + f = Op_val (v)[i]; + CAMLassert (!Is_debug_tag(f)); + if (Is_block (f) && Is_young(f)) { + oldify_one (st, f, Op_val (new_v) + i); + } else { + Op_val (new_v)[i] = f; } } + CAMLassert (Wosize_val(new_v)); } - /* Oldify the data in the minor heap of alive ephemeron - During minor collection keys outside the minor heap are considered alive */ - for (re = Caml_state->ephe_ref_table->base; - re < Caml_state->ephe_ref_table->ptr; re++){ - /* look only at ephemeron with data in the minor heap */ - if (re->offset == 1){ - value *data = &Field(re->ephe,1); - if (*data != caml_ephe_none && Is_block (*data) && Is_young (*data)){ - if (Hd_val (*data) == 0){ /* Value copied to major heap */ - *data = Field (*data, 0); + /* Oldify the key and data in the minor heap of all ephemerons touched in this + cycle + We are doing this to allow concurrent minor collections to resume + executing mutating code while others are still collecting. + */ + if( do_ephemerons ) { + for (re = ephe_ref_table.base; + re < ephe_ref_table.ptr; re++) { + value *data = re->offset == CAML_EPHE_DATA_OFFSET + ? &Ephe_data(re->ephe) + : &Op_val(re->ephe)[re->offset]; + if (*data != caml_ephe_none && Is_block(*data) && Is_young(*data) ) { + resolve_infix_val(data); + if (get_header_val(*data) == 0) { /* Value copied to major heap */ + *data = Op_val(*data)[0]; } else { - if (ephe_check_alive_data(re)){ - caml_oldify_one(*data,data); - redo = 1; /* oldify_todo_list can still be 0 */ - } + oldify_one(st, *data, data); + redo = 1; /* oldify_todo_list can still be 0 */ } } } } - if (redo) caml_oldify_mopup (); + if (redo) oldify_mopup (st, 1); } -/* Make sure the minor heap is empty by performing a minor collection - if needed. -*/ -void caml_empty_minor_heap (void) +//***************************************************************************** + + + +void caml_minor_heap_domain_finalizers_admin (struct domain* domain, void* unused) { - value **r; + /* need to do the finalizer data structure book-keeping */ + caml_final_update_last_minor(domain); + + /*caml_domain_state* domain_state = domain->state; + struct caml_minor_tables *minor_tables = domain_state->minor_tables; + struct caml_custom_elt *elt; */ + + /* There will be no dead minor values as we can not tell the state of + a minor heap aliveness until all domains complete */ + /*for (elt = minor_tables->custom.base; elt < minor_tables->custom.ptr; elt++) { + value v = elt->block; + if (get_header_val(v) == 0) {*/ + /* !!caml_adjust_gc_speed(elt->mem, elt->max); */ + /*} else {*/ + /* Block will be freed: call finalisation function, if any */ + /* void (*final_fun)(value) = Custom_ops_val(v)->finalize; + if (final_fun != NULL) final_fun(v); + } + }*/ +} + +void caml_empty_minor_heap_domain_clear (struct domain* domain, void* unused) +{ + caml_domain_state* domain_state = domain->state; + struct caml_minor_tables *minor_tables = domain_state->minor_tables; + + caml_final_empty_young(domain); + + clear_table ((struct generic_table *)&minor_tables->major_ref); + clear_table ((struct generic_table *)&minor_tables->ephe_ref); + clear_table ((struct generic_table *)&minor_tables->custom); +} + +void caml_empty_minor_heap_promote (struct domain* domain, int participating_count, struct domain** participating, int not_alone) +{ + caml_domain_state* domain_state = domain->state; + struct caml_minor_tables *self_minor_tables = domain_state->minor_tables; struct caml_custom_elt *elt; + unsigned rewrite_successes = 0; + unsigned rewrite_failures = 0; + char* young_ptr = domain_state->young_ptr; + char* young_end = domain_state->young_end; + uintnat minor_allocated_bytes = young_end - young_ptr; uintnat prev_alloc_words; - struct caml_ephe_ref_elt *re; - - if (Caml_state->young_ptr != Caml_state->young_alloc_end){ - CAMLassert_young_header(*(header_t*)Caml_state->young_ptr); - if (caml_minor_gc_begin_hook != NULL) (*caml_minor_gc_begin_hook) (); - prev_alloc_words = caml_allocated_words; - Caml_state->in_minor_collection = 1; - caml_gc_message (0x02, "<"); - CAML_EV_BEGIN(EV_MINOR_LOCAL_ROOTS); - caml_oldify_local_roots(); - CAML_EV_END(EV_MINOR_LOCAL_ROOTS); - CAML_EV_BEGIN(EV_MINOR_REF_TABLES); - for (r = Caml_state->ref_table->base; - r < Caml_state->ref_table->ptr; r++) { - caml_oldify_one (**r, *r); + struct oldify_state st = {0}; + value **r; + intnat c, curr_idx; + int remembered_roots = 0; + + st.promote_domain = domain; + + /* TODO: are there any optimizations we can make where we don't need to scan + when minor heaps can reference each other? */ + prev_alloc_words = domain_state->allocated_words; + + caml_gc_log ("Minor collection of domain %d starting", domain->state->id); + CAML_EV_BEGIN(EV_MINOR); + + if( participating[0] == caml_domain_self() || !not_alone ) { // TODO: We should distribute this work + if(domain_finished_root == 0){ + if (caml_plat_try_lock(&global_roots_lock)){ + CAML_EV_BEGIN(EV_MINOR_GLOBAL_ROOTS); + caml_scan_global_young_roots(oldify_one, &st); + CAML_EV_END(EV_MINOR_GLOBAL_ROOTS); + atomic_store_explicit(&domain_finished_root, 1, memory_order_release); + caml_plat_unlock(&global_roots_lock); + } } - CAML_EV_END(EV_MINOR_REF_TABLES); - CAML_EV_BEGIN(EV_MINOR_COPY); - caml_oldify_mopup (); - CAML_EV_END(EV_MINOR_COPY); - /* Update the ephemerons */ - for (re = Caml_state->ephe_ref_table->base; - re < Caml_state->ephe_ref_table->ptr; re++){ - if(re->offset < Wosize_val(re->ephe)){ - /* If it is not the case, the ephemeron has been truncated */ - value *key = &Field(re->ephe,re->offset); - if (*key != caml_ephe_none && Is_block (*key) && Is_young (*key)){ - if (Hd_val (*key) == 0){ /* Value copied to major heap */ - *key = Field (*key, 0); - }else{ /* Value not copied so it's dead */ - CAMLassert(!ephe_check_alive_data(re)); - *key = caml_ephe_none; - Field(re->ephe,1) = caml_ephe_none; - } - } + } + + CAML_EV_BEGIN(EV_MINOR_REF_TABLES); + + if( not_alone ) { + int participating_idx = -1; + struct domain* domain_self = caml_domain_self(); + + for( int i = 0; i < participating_count ; i++ ) { + if( participating[i] == domain_self ) { + participating_idx = i; + break; } } - /* Update the OCaml finalise_last values */ - CAML_EV_BEGIN(EV_MINOR_UPDATE_WEAK); - caml_final_update_minor_roots(); - /* Trigger memprofs callbacks for blocks in the minor heap. */ - caml_memprof_minor_update(); - /* Run custom block finalisation of dead minor values */ - for (elt = Caml_state->custom_table->base; - elt < Caml_state->custom_table->ptr; elt++){ - value v = elt->block; - if (Hd_val (v) == 0){ - /* Block was copied to the major heap: adjust GC speed numbers. */ - caml_adjust_gc_speed(elt->mem, elt->max); - }else{ - /* Block will be freed: call finalization function, if any. */ - void (*final_fun)(value) = Custom_ops_val(v)->finalize; - if (final_fun != NULL) final_fun(v); + + CAMLassert(participating_idx != -1); + + // We use this rather odd scheme because it better smoothes the remainder + for( curr_idx = 0, c = participating_idx; curr_idx < participating_count; curr_idx++) { + struct domain* foreign_domain = participating[c]; + struct caml_minor_tables* foreign_minor_tables = foreign_domain->state->minor_tables; + struct caml_ref_table* foreign_major_ref = &foreign_minor_tables->major_ref; + // calculate the size of the remembered set + intnat major_ref_size = foreign_major_ref->ptr - foreign_major_ref->base; + // number of remembered set entries each domain takes here + intnat refs_per_domain = (major_ref_size / participating_count); + // where to start in the remembered set + value** ref_start = foreign_major_ref->base + (curr_idx * refs_per_domain); + // where to end in the remembered set + value** ref_end = foreign_major_ref->base + ((curr_idx+1) * refs_per_domain); + // if we're the last domain this time, cover all the remaining refs + if( curr_idx == participating_count-1 ) { + caml_gc_log("taking remainder"); + ref_end = foreign_major_ref->ptr; + } + + caml_gc_log("idx: %d, foreign_domain: %d, ref_size: %"ARCH_INTNAT_PRINTF_FORMAT"d, refs_per_domain: %"ARCH_INTNAT_PRINTF_FORMAT"d, ref_base: %p, ref_ptr: %p, ref_start: %p, ref_end: %p", + participating_idx, foreign_domain->state->id, major_ref_size, refs_per_domain, foreign_major_ref->base, foreign_major_ref->ptr, ref_start, ref_end); + + for( r = ref_start ; r < foreign_major_ref->ptr && r < ref_end ; r++ ) + { + oldify_one (&st, **r, *r); + remembered_roots++; } + + c = (c+1) % participating_count; } - CAML_EV_END(EV_MINOR_UPDATE_WEAK); - CAML_EV_BEGIN(EV_MINOR_FINALIZED); - Caml_state->stat_minor_words += - Caml_state->young_alloc_end - Caml_state->young_ptr; - caml_gc_clock += - (double) (Caml_state->young_alloc_end - Caml_state->young_ptr) - / Caml_state->minor_heap_wsz; - Caml_state->young_ptr = Caml_state->young_alloc_end; - clear_table ((struct generic_table *) Caml_state->ref_table); - clear_table ((struct generic_table *) Caml_state->ephe_ref_table); - clear_table ((struct generic_table *) Caml_state->custom_table); - Caml_state->extra_heap_resources_minor = 0; - caml_gc_message (0x02, ">"); - Caml_state->in_minor_collection = 0; - caml_final_empty_young (); - CAML_EV_END(EV_MINOR_FINALIZED); - Caml_state->stat_promoted_words += caml_allocated_words - prev_alloc_words; - CAML_EV_COUNTER (EV_C_MINOR_PROMOTED, - caml_allocated_words - prev_alloc_words); - ++ Caml_state->stat_minor_collections; - caml_memprof_renew_minor_sample(); - if (caml_minor_gc_end_hook != NULL) (*caml_minor_gc_end_hook) (); - }else{ - /* The minor heap is empty nothing to do. */ - caml_final_empty_young (); } -#ifdef DEBUG + else { - value *p; - for (p = Caml_state->young_alloc_start; p < Caml_state->young_alloc_end; - ++p) { - *p = Debug_free_minor; + // If we're alone, we just do our own remembered set + for( r = self_minor_tables->major_ref.base ; r < self_minor_tables->major_ref.ptr ; r++ ) + { + oldify_one (&st, **r, *r); + remembered_roots++; + } + } + + #ifdef DEBUG + caml_global_barrier(); + // At this point all domains should have gone through all remembered set entries + // We need to verify that all our remembered set entries are now in the major heap or promoted + for( r = self_minor_tables->major_ref.base ; r < self_minor_tables->major_ref.ptr ; r++ ) { + // Everything should be promoted + CAMLassert(!(Is_block(**r)) || !(Is_young(**r))); } + #endif + + /* promote the finalizers unconditionally as we want to allow early release */ + CAML_EV_BEGIN(EV_MINOR_FINALIZERS_OLDIFY); + for (elt = self_minor_tables->custom.base; elt < self_minor_tables->custom.ptr; elt++) { + value *v = &elt->block; + if (Is_block(*v) && Is_young(*v)) { + if (get_header_val(*v) == 0) { /* value copied to major heap */ + *v = Op_val(*v)[0]; + } else { + oldify_one(&st, *v, v); + } + } + } + caml_final_do_young_roots (&oldify_one, &st, domain, 0); + CAML_EV_END(EV_MINOR_FINALIZERS_OLDIFY); + + oldify_mopup (&st, 1); /* ephemerons promoted here */ + CAML_EV_END(EV_MINOR_REF_TABLES); + caml_gc_log("promoted %d roots, %lu bytes", remembered_roots, st.live_bytes); + + CAML_EV_BEGIN(EV_MINOR_FINALIZERS_ADMIN); + caml_gc_log("running stw minor_heap_domain_finalizers_admin"); + caml_minor_heap_domain_finalizers_admin(domain, 0); + CAML_EV_END(EV_MINOR_FINALIZERS_ADMIN); + +#ifdef DEBUG + caml_global_barrier(); + caml_gc_log("ref_base: %p, ref_ptr: %p", + self_minor_tables->major_ref.base, self_minor_tables->major_ref.ptr); + for (r = self_minor_tables->major_ref.base; + r < self_minor_tables->major_ref.ptr; r++) { + value vnew = **r; + CAMLassert (!Is_block(vnew) || (get_header_val(vnew) != 0 && !Is_young(vnew))); + } + + for (elt = self_minor_tables->custom.base; elt < self_minor_tables->custom.ptr; elt++) { + value vnew = elt->block; + CAMLassert (!Is_block(vnew) || (get_header_val(vnew) != 0 && !Is_young(vnew))); } #endif + + CAML_EV_BEGIN(EV_MINOR_LOCAL_ROOTS); + caml_do_local_roots(&oldify_one, &st, domain->state->local_roots, domain->state->current_stack, domain->state->gc_regs); + if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(&oldify_one, &st, domain); + oldify_mopup (&st, 0); + CAML_EV_END(EV_MINOR_LOCAL_ROOTS); + + /* we reset these pointers before allowing any mutators to be + released to avoid races where another domain signals an interrupt + and we clobber it */ + atomic_store_rel((atomic_uintnat*)&domain_state->young_limit, (uintnat)domain_state->young_start); + atomic_store_rel((atomic_uintnat*)&domain_state->young_ptr, (uintnat)domain_state->young_end); + + if( not_alone ) { + atomic_fetch_add_explicit(&domains_finished_minor_gc, 1, memory_order_release); + } + + domain_state->stat_minor_words += Wsize_bsize (minor_allocated_bytes); + domain_state->stat_minor_collections++; + domain_state->stat_promoted_words += domain_state->allocated_words - prev_alloc_words; + + CAML_EV_END(EV_MINOR); + caml_gc_log ("Minor collection of domain %d completed: %2.0f%% of %u KB live, rewrite: successes=%u failures=%u", + domain->state->id, + 100.0 * (double)st.live_bytes / (double)minor_allocated_bytes, + (unsigned)(minor_allocated_bytes + 512)/1024, rewrite_successes, rewrite_failures); } -#ifdef CAML_INSTR -extern uintnat caml_instr_alloc_jump; -#endif /*CAML_INSTR*/ +void caml_do_opportunistic_major_slice(struct domain* domain, void* unused) +{ + /* NB: need to put guard around the ev logs to prevent + spam when we poll */ + if (caml_opportunistic_major_work_available()) { + int log_events = caml_params->verb_gc & 0x40; + if (log_events) CAML_EV_BEGIN(EV_MAJOR_MARK_OPPORTUNISTIC); + caml_opportunistic_major_collection_slice(0x200); + if (log_events) CAML_EV_END(EV_MAJOR_MARK_OPPORTUNISTIC); + } +} -/* Do a minor collection or a slice of major collection, call finalisation - functions, etc. - Leave enough room in the minor heap to allocate at least one object. - Guaranteed not to call any OCaml callback. +/* Make sure the minor heap is empty by performing a minor collection + if needed. */ -CAMLexport void caml_gc_dispatch (void) +void caml_empty_minor_heap_setup(struct domain* domain) { + atomic_store_explicit(&domains_finished_minor_gc, 0, memory_order_release); + atomic_store_explicit(&domain_finished_root, 0, memory_order_release); +} + +/* must be called within a STW section */ +static void caml_stw_empty_minor_heap_no_major_slice (struct domain* domain, void* unused, int participating_count, struct domain** participating) { - value *trigger = Caml_state->young_trigger; /* save old value of trigger */ - - CAML_EVENTLOG_DO({ - CAML_EV_COUNTER(EV_C_ALLOC_JUMP, caml_instr_alloc_jump); - caml_instr_alloc_jump = 0; - }); - - if (trigger == Caml_state->young_alloc_start - || Caml_state->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_EV_BEGIN(EV_MINOR); - Caml_state->requested_minor_gc = 0; - Caml_state->young_trigger = Caml_state->young_alloc_mid; - caml_update_young_limit(); - caml_empty_minor_heap (); - /* The minor heap is empty, we can start a major collection. */ - CAML_EV_END(EV_MINOR); - if (caml_gc_phase == Phase_idle) - { - CAML_EV_BEGIN(EV_MAJOR); - caml_major_collection_slice (-1); - CAML_EV_END(EV_MAJOR); + int not_alone = !caml_domain_alone(); + + #ifdef DEBUG + CAMLassert(caml_domain_is_in_stw()); + #endif + + if( not_alone ) { + if( participating[0] == caml_domain_self() ) { + atomic_fetch_add(&caml_minor_cycles_started, 1); } } - if (trigger != Caml_state->young_alloc_start - || Caml_state->requested_major_slice) { - /* The minor heap is half-full, do a major GC slice. */ - Caml_state->requested_major_slice = 0; - Caml_state->young_trigger = Caml_state->young_alloc_start; - caml_update_young_limit(); - CAML_EV_BEGIN(EV_MAJOR); - caml_major_collection_slice (-1); - CAML_EV_END(EV_MAJOR); + else + { + atomic_fetch_add(&caml_minor_cycles_started, 1); } -} -/* Called by young allocations when [Caml_state->young_ptr] reaches - [Caml_state->young_limit]. We may have to either call memprof or - the gc. */ -void caml_alloc_small_dispatch (intnat wosize, int flags, - int nallocs, unsigned char* encoded_alloc_lens) -{ - intnat whsize = Whsize_wosize (wosize); - - /* First, we un-do the allocation performed in [Alloc_small] */ - Caml_state->young_ptr += whsize; - - while(1) { - /* We might be here because of an async callback / urgent GC - request. Take the opportunity to do what has been requested. */ - if (flags & CAML_FROM_CAML) - /* In the case of allocations performed from OCaml, execute - asynchronous callbacks. */ - caml_raise_if_exception(caml_do_pending_actions_exn ()); - else { - caml_check_urgent_gc (Val_unit); - /* In the case of long-running C code that regularly polls with - caml_process_pending_actions, force a query of all callbacks - at every minor collection or major slice. */ - caml_something_to_do = 1; - } + caml_gc_log("running stw empty_minor_heap_promote"); + caml_empty_minor_heap_promote(domain, participating_count, participating, not_alone); - /* Now, there might be enough room in the minor heap to do our - allocation. */ - if (Caml_state->young_ptr - whsize >= Caml_state->young_trigger) - break; - - /* If not, then empty the minor heap, and check again for async - callbacks. */ - CAML_EV_COUNTER (EV_C_FORCE_MINOR_ALLOC_SMALL, 1); - caml_gc_dispatch (); -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - if (caml_young_ptr == caml_young_alloc_end) { - caml_spacetime_automatic_snapshot(); + /* collect gc stats before leaving the barrier */ + caml_sample_gc_collect(domain->state); + + if( not_alone ) { + CAML_EV_BEGIN(EV_MINOR_LEAVE_BARRIER); + { + SPIN_WAIT { + if( atomic_load_explicit(&domains_finished_minor_gc, memory_order_acquire) == participating_count ) { + break; + } + + caml_do_opportunistic_major_slice(domain, 0); + } } -#endif + CAML_EV_END(EV_MINOR_LEAVE_BARRIER); } - /* Re-do the allocation: we now have enough space in the minor heap. */ - Caml_state->young_ptr -= whsize; - - /* Check if the allocated block has been sampled by memprof. */ - if(Caml_state->young_ptr < caml_memprof_young_trigger){ - if(flags & CAML_DO_TRACK) { - caml_memprof_track_young(wosize, flags & CAML_FROM_CAML, - nallocs, encoded_alloc_lens); - /* Until the allocation actually takes place, the heap is in an invalid - state (see comments in [caml_memprof_track_young]). Hence, very little - heap operations are allowed before the actual allocation. - - Moreover, [Caml_state->young_ptr] should not be modified before the - allocation, because its value has been used as the pointer to - the sampled block. - */ - } else caml_memprof_renew_minor_sample(); + CAML_EV_BEGIN(EV_MINOR_CLEAR); + caml_gc_log("running stw empty_minor_heap_domain_clear"); + caml_empty_minor_heap_domain_clear(domain, 0); + CAML_EV_END(EV_MINOR_CLEAR); + caml_gc_log("finished stw empty_minor_heap"); +} + +static void caml_stw_empty_minor_heap (struct domain* domain, void* unused, int participating_count, struct domain** participating) +{ + caml_stw_empty_minor_heap_no_major_slice(domain, unused, participating_count, participating); + + /* schedule a major collection slice for this domain */ + caml_request_major_slice(); + + /* can change how we account clock in future, here just do raw count */ + domain->state->major_gc_clock += 1.0; +} + +/* must be called within a STW section */ +void caml_empty_minor_heap_no_major_slice_from_stw (struct domain* domain, void* unused, int participating_count, struct domain** participating) +{ + barrier_status b = caml_global_barrier_begin(); + if( caml_global_barrier_is_final(b) ) { + caml_empty_minor_heap_setup(domain); } + caml_global_barrier_end(b); + + /* if we are entering from within a major GC STW section then + we do not schedule another major collection slice */ + caml_stw_empty_minor_heap_no_major_slice(domain, (void*)0, participating_count, participating); +} + +/* must be called outside a STW section */ +int caml_try_stw_empty_minor_heap_on_all_domains () +{ + #ifdef DEBUG + CAMLassert(!caml_domain_is_in_stw()); + #endif + + caml_gc_log("requesting stw empty_minor_heap"); + return caml_try_run_on_all_domains_with_spin_work( + &caml_stw_empty_minor_heap, 0, /* stw handler */ + &caml_empty_minor_heap_setup, /* leader setup */ + &caml_do_opportunistic_major_slice, 0, /* enter spin work */ + 0, 0, /* leave spin work */ + 1); /* leave when done */ +} + +/* must be called outside a STW section, will retry until we have emptied our minor heap */ +void caml_empty_minor_heaps_once () +{ + uintnat saved_minor_cycle = atomic_load(&caml_minor_cycles_started); + + #ifdef DEBUG + CAMLassert(!caml_domain_is_in_stw()); + #endif + + /* To handle the case where multiple domains try to execute a minor gc STW section */ + do { + caml_try_stw_empty_minor_heap_on_all_domains(); + } while (saved_minor_cycle == atomic_load(&caml_minor_cycles_started)); } -/* Exported for backward compatibility with Lablgtk: do a minor - collection to ensure that the minor heap is empty. +/* Request a minor collection and enter as if it were an interrupt. */ CAMLexport void caml_minor_collection (void) { - Caml_state->requested_minor_gc = 1; - caml_gc_dispatch (); + caml_request_minor_gc(); + caml_handle_gc_interrupt(); } CAMLexport value caml_check_urgent_gc (value extra_root) { - if (Caml_state->requested_major_slice || Caml_state->requested_minor_gc){ - CAMLparam1 (extra_root); - caml_gc_dispatch(); + if (Caml_check_gc_interrupt(Caml_state)) { + CAMLparam1(extra_root); + caml_handle_gc_interrupt(); CAMLdrop; } return extra_root; @@ -577,8 +832,7 @@ CAMLexport value caml_check_urgent_gc (value extra_root) static void realloc_generic_table (struct generic_table *tbl, asize_t element_size, - ev_gc_counter ev_counter_name, - char *msg_threshold, char *msg_growing, char *msg_error) + char * msg_intr_int, char *msg_threshold, char *msg_growing, char *msg_error) { CAMLassert (tbl->ptr == tbl->limit); CAMLassert (tbl->limit <= tbl->end); @@ -588,14 +842,12 @@ static void realloc_generic_table alloc_generic_table (tbl, Caml_state->minor_heap_wsz / 8, 256, element_size); }else if (tbl->limit == tbl->threshold){ - CAML_EV_COUNTER (ev_counter_name, 1); caml_gc_message (0x08, msg_threshold, 0); tbl->limit = tbl->end; caml_request_minor_gc (); }else{ asize_t sz; asize_t cur_ptr = tbl->ptr - tbl->base; - CAMLassert (Caml_state->requested_minor_gc); tbl->size *= 2; sz = (tbl->size + tbl->reserve) * element_size; @@ -615,7 +867,7 @@ void caml_realloc_ref_table (struct caml_ref_table *tbl) { realloc_generic_table ((struct generic_table *) tbl, sizeof (value *), - EV_C_REQUEST_MINOR_REALLOC_REF_TABLE, + "request_minor/realloc_ref_table@", "ref_table threshold crossed\n", "Growing ref_table to %" ARCH_INTNAT_PRINTF_FORMAT "dk bytes\n", "ref_table overflow"); @@ -625,7 +877,7 @@ void caml_realloc_ephe_ref_table (struct caml_ephe_ref_table *tbl) { realloc_generic_table ((struct generic_table *) tbl, sizeof (struct caml_ephe_ref_elt), - EV_C_REQUEST_MINOR_REALLOC_EPHE_REF_TABLE, + "request_minor/realloc_ephe_ref_table@", "ephe_ref_table threshold crossed\n", "Growing ephe_ref_table to %" ARCH_INTNAT_PRINTF_FORMAT "dk bytes\n", "ephe_ref_table overflow"); @@ -635,7 +887,7 @@ void caml_realloc_custom_table (struct caml_custom_table *tbl) { realloc_generic_table ((struct generic_table *) tbl, sizeof (struct caml_custom_elt), - EV_C_REQUEST_MINOR_REALLOC_CUSTOM_TABLE, + "request_minor/realloc_custom_table@", "custom_table threshold crossed\n", "Growing custom_table to %" ARCH_INTNAT_PRINTF_FORMAT "dk bytes\n", "custom_table overflow"); diff --git a/runtime/misc.c b/runtime/misc.c index 397bd7cff3..c303ee108e 100644 --- a/runtime/misc.c +++ b/runtime/misc.c @@ -28,11 +28,16 @@ __declspec(noreturn) void __cdecl abort(void); #include <stdio.h> #include <string.h> #include <stdarg.h> +#include <execinfo.h> +#include <stdlib.h> #include "caml/config.h" #include "caml/misc.h" #include "caml/memory.h" #include "caml/osdeps.h" #include "caml/version.h" +#include "caml/domain.h" +#include "caml/startup.h" +#include "caml/startup_aux.h" caml_timing_hook caml_major_slice_begin_hook = NULL; caml_timing_hook caml_major_slice_end_hook = NULL; @@ -41,33 +46,71 @@ caml_timing_hook caml_minor_gc_end_hook = NULL; caml_timing_hook caml_finalise_begin_hook = NULL; caml_timing_hook caml_finalise_end_hook = NULL; -#ifdef DEBUG +#if defined(DEBUG) || defined(NATIVE_CODE) + +void print_trace (void) +{ + void *array[10]; + size_t size; + char **strings; + size_t i; + + size = backtrace (array, 10); + strings = backtrace_symbols (array, size); + + caml_gc_log ("Obtained %zd stack frames.", size); + + for (i = 0; i < size; i++) + caml_gc_log ("%s", strings[i]); + + free (strings); +} void caml_failed_assert (char * expr, char_os * file_os, int line) { char* file = caml_stat_strdup_of_os(file_os); - fprintf (stderr, "file %s; line %d ### Assertion failed: %s\n", - file, line, expr); + fprintf (stderr, "[%02d] file %s; line %d ### Assertion failed: %s\n", + Caml_state ? Caml_state->id : -1, file, line, expr); + print_trace (); fflush (stderr); caml_stat_free(file); abort(); } +#endif -void caml_set_fields (value v, uintnat start, uintnat filler) +#if defined(DEBUG) +static __thread int noalloc_level = 0; +int caml_noalloc_begin() { - mlsize_t i; - for (i = start; i < Wosize_val (v); i++){ - Field (v, i) = (value) filler; - } + return noalloc_level++; +} +void caml_noalloc_end(int* noalloc) +{ + int curr = --noalloc_level; + CAMLassert(*noalloc == curr); +} +void caml_alloc_point_here() +{ + CAMLassert(noalloc_level == 0); } - #endif /* DEBUG */ -uintnat caml_verb_gc = 0; +void caml_gc_log (char *msg, ...) +{ + if ((caml_params->verb_gc & 0x800) != 0) { + char fmtbuf[512]; + va_list args; + va_start (args, msg); + sprintf(fmtbuf, "[%02d] %s\n", Caml_state ? Caml_state->id : -1, msg); + vfprintf(stderr, fmtbuf, args); + va_end (args); + fflush(stderr); + } +} void caml_gc_message (int level, char *msg, ...) { - if ((caml_verb_gc & level) != 0){ + if ((caml_params->verb_gc & level) != 0){ va_list ap; va_start(ap, msg); vfprintf (stderr, msg, ap); @@ -93,6 +136,20 @@ CAMLexport void caml_fatal_error (char *msg, ...) abort(); } +CAMLexport void caml_fatal_error_arg (const char *fmt, const char *arg) +{ + fprintf (stderr, fmt, arg); + exit(2); +} + +CAMLexport void caml_fatal_error_arg2 (const char *fmt1, const char *arg1, + const char *fmt2, const char *arg2) +{ + fprintf (stderr, fmt1, arg1); + fprintf (stderr, fmt2, arg2); + exit(2); +} + /* If you change the caml_ext_table* functions, also update runtime/spacetime_nat.c:find_trie_node_from_libunwind. */ diff --git a/runtime/obj.c b/runtime/obj.c index 8cb560ddce..ab885dd8ca 100644 --- a/runtime/obj.c +++ b/runtime/obj.c @@ -18,6 +18,7 @@ /* Operations on objects */ #include <string.h> +#include "caml/camlatomic.h" #include "caml/alloc.h" #include "caml/fail.h" #include "caml/gc.h" @@ -28,7 +29,7 @@ #include "caml/misc.h" #include "caml/mlvalues.h" #include "caml/prims.h" -#include "caml/signals.h" +#include "caml/platform.h" #include "caml/spacetime.h" CAMLprim value caml_obj_tag(value arg) @@ -37,10 +38,8 @@ CAMLprim value caml_obj_tag(value arg) return Val_int (1000); /* int_tag */ }else if ((long) arg & (sizeof (value) - 1)){ return Val_int (1002); /* unaligned_tag */ - }else if (Is_in_value_area (arg)){ - return Val_int(Tag_val(arg)); }else{ - return Val_int (1001); /* out_of_heap_tag */ + return Val_int(Tag_val(arg)); } } @@ -50,6 +49,34 @@ CAMLprim value caml_obj_set_tag (value arg, value new_tag) return Val_unit; } +static int obj_update_tag (value blk, int old_tag, int new_tag) +{ + header_t hd; + tag_t tag; + + SPIN_WAIT { + hd = Hd_val(blk); + tag = Tag_hd(hd); + + if (tag != old_tag) return 0; + if (caml_domain_alone()) { + Tag_val (blk) = new_tag; + return 1; + } + + if (atomic_compare_exchange_strong(Hp_atomic_val(blk), &hd, + (hd & ~0xFF) | new_tag)) + return 1; + } +} + +CAMLprim value caml_obj_update_tag (value blk, value old_tag, value new_tag) +{ + if (obj_update_tag(blk, Int_val(old_tag), Int_val(new_tag))) + return Val_true; + return Val_false; +} + CAMLprim value caml_obj_raw_field(value arg, value pos) { /* Represent field contents as a native integer */ @@ -64,8 +91,14 @@ CAMLprim value caml_obj_set_raw_field(value arg, value pos, value bits) CAMLprim value caml_obj_make_forward (value blk, value fwd) { - caml_modify(&Field(blk, 0), fwd); - Tag_val (blk) = Forward_tag; + /* Modify field before setting tag */ + caml_modify_field(blk, 0, fwd); + + /* This function is only called on Lazy_tag objects. The only racy write to + * this object is by the GC threads. */ + CAMLassert (Tag_val(blk) == Forcing_tag); + obj_update_tag (blk, Forcing_tag, Forward_tag); + return Val_unit; } @@ -137,7 +170,7 @@ CAMLprim value caml_obj_block(value tag, value size) CAMLprim value caml_obj_with_tag(value new_tag_v, value arg) { CAMLparam2 (new_tag_v, arg); - CAMLlocal1 (res); + CAMLlocal2 (res, x); mlsize_t sz, i; tag_t tg; @@ -158,9 +191,8 @@ CAMLprim value caml_obj_with_tag(value new_tag_v, value arg) and some of the "values" being copied are actually code pointers. That's because the new "value" does not point to the minor heap. */ for (i = 0; i < sz; i++) caml_initialize(&Field(res, i), Field(arg, i)); - /* Give gc a chance to run, and run memprof callbacks */ - caml_process_pending_actions(); } + CAMLreturn (res); } @@ -188,39 +220,7 @@ CAMLprim value caml_obj_dup(value arg) */ CAMLprim value caml_obj_truncate (value v, value newsize) { - mlsize_t new_wosize = Long_val (newsize); - header_t hd = Hd_val (v); - tag_t tag = Tag_hd (hd); - color_t color = Color_hd (hd); - color_t frag_color = Is_young(v) ? 0 : Caml_black; - mlsize_t wosize = Wosize_hd (hd); - mlsize_t i; - - if (tag == Double_array_tag) new_wosize *= Double_wosize; /* PR#2520 */ - - if (new_wosize <= 0 || new_wosize > wosize){ - caml_invalid_argument ("Obj.truncate"); - } - if (new_wosize == wosize) return Val_unit; - /* PR#2400: since we're about to lose our references to the elements - beyond new_wosize in v, erase them explicitly so that the GC - can darken them as appropriate. */ - if (tag < No_scan_tag) { - for (i = new_wosize; i < wosize; i++){ - caml_modify(&Field(v, i), Val_unit); -#ifdef DEBUG - Field (v, i) = Debug_free_truncate; -#endif - } - } - /* We must use an odd tag for the header of the leftovers so it does not - 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), Abstract_tag, frag_color); - Hd_val (v) = - Make_header_with_profinfo (new_wosize, tag, color, Profinfo_val(v)); - return Val_unit; + caml_failwith("Obj.truncate not supported"); } CAMLprim value caml_obj_add_offset (value v, value offset) @@ -228,6 +228,36 @@ CAMLprim value caml_obj_add_offset (value v, value offset) return v + (unsigned long) Int32_val (offset); } +CAMLprim value caml_obj_compare_and_swap (value v, value f, value oldv, value newv) +{ + int res = caml_atomic_cas_field(v, Int_val(f), oldv, newv); + caml_check_urgent_gc(Val_unit); + return Val_int(res); +} + +/* caml_promote_to(obj, upto) may promote obj to be as least as shared as upto. + Skips promotion if there is only a single domain. This should only be used in + situations where there is a performance need to 'front-load' the promotion + across domains, such as for queues. If you need to guarantee promotion to the + major heap for correctness, use caml_obj_force_promote_to*/ +CAMLprim value caml_obj_promote_to (value obj, value upto) +{ + /* ctk21: now no-op */ + return obj; +} + +/* caml_force_promote_to(obj, upto) force promotes obj to be as least as shared as upto */ +CAMLprim value caml_obj_force_promote_to (value obj, value upto) +{ + /* ctk21: now no-op */ + return obj; +} + +CAMLprim value caml_obj_is_shared (value obj) +{ + return Val_int(Is_long(obj) || !Is_young(obj)); +} + /* The following function is used in stdlib/lazy.ml. It is not written in OCaml because it must be atomic with respect to the GC. @@ -249,7 +279,7 @@ CAMLprim value caml_lazy_make_forward (value v) CAMLprim value caml_get_public_method (value obj, value tag) { - value meths = Field (obj, 0); + value meths = Field(obj, 0); int li = 3, hi = Field(meths,0), mi; while (li < hi) { mi = ((li+hi) >> 1) | 1; @@ -260,20 +290,26 @@ CAMLprim value caml_get_public_method (value obj, value tag) return (tag == Field(meths,li) ? Field (meths, li-1) : 0); } -static value oo_last_id = Val_int(0); +/* Allocate OO ids in chunks, to avoid contention */ +#define Id_chunk 1024 -CAMLprim value caml_set_oo_id (value obj) { - Field(obj, 1) = oo_last_id; - oo_last_id += 2; - return obj; -} +static atomic_uintnat oo_next_id; CAMLprim value caml_fresh_oo_id (value v) { - v = oo_last_id; - oo_last_id += 2; + if (Caml_state->oo_next_id_local % Id_chunk == 0) { + Caml_state->oo_next_id_local = + atomic_fetch_add(&oo_next_id, Id_chunk); + } + v = Val_long(Caml_state->oo_next_id_local++); return v; } +CAMLprim value caml_set_oo_id (value obj) { + value v = Val_unit; + Op_val(obj)[1] = caml_fresh_oo_id(v); + return obj; +} + CAMLprim value caml_int_as_pointer (value n) { return n - 1; } diff --git a/runtime/parsing.c b/runtime/parsing.c index 990eb1f6fc..94aea71821 100644 --- a/runtime/parsing.c +++ b/runtime/parsing.c @@ -23,6 +23,7 @@ #include "caml/mlvalues.h" #include "caml/memory.h" #include "caml/alloc.h" +#include "caml/startup.h" #define ERRCODE 256 @@ -72,8 +73,6 @@ struct parser_env { /* Mirrors parser_env in ../stdlib/parsing.ml */ #define Short(tbl,n) (((short *)(tbl))[n]) #endif -int caml_parser_trace = 0; - /* Input codes */ /* Mirrors parser_input in ../stdlib/parsing.ml */ #define START 0 @@ -117,7 +116,8 @@ static char * token_name(char * names, int number) static void print_token(struct parser_tables *tables, int state, value tok) { - value v; + CAMLparam1 (tok); + CAMLlocal1 (v); if (Is_long(tok)) { fprintf(stderr, "State %d: read token %s\n", @@ -125,7 +125,7 @@ static void print_token(struct parser_tables *tables, int state, value tok) } else { fprintf(stderr, "State %d: read token %s(", state, token_name(tables->names_block, Tag_val(tok))); - v = Field(tok, 0); + caml_read_field(tok, 0, &v); if (Is_long(v)) fprintf(stderr, "%" ARCH_INTNAT_PRINTF_FORMAT "d", Long_val(v)); else if (Tag_val(v) == String_tag) @@ -136,6 +136,12 @@ static void print_token(struct parser_tables *tables, int state, value tok) fprintf(stderr, "_"); fprintf(stderr, ")\n"); } + CAMLreturn0; +} + +static int trace() +{ + return caml_params->parser_trace || Caml_state->parser_trace; } /* The pushdown automata */ @@ -166,13 +172,17 @@ CAMLprim value caml_parse_engine(struct parser_tables *tables, case TOKEN_READ: RESTORE; if (Is_block(arg)) { - env->curr_char = Field(tables->transl_block, Tag_val(arg)); - caml_modify(&env->lval, Field(arg, 0)); + env->curr_char = Val_int(Int_field(tables->transl_block, Tag_val(arg))); + caml_modify_field((value)env, + offsetof(struct parser_env, lval) / sizeof(value), + Field(arg, 0)); } else { - env->curr_char = Field(tables->transl_const, Int_val(arg)); - caml_modify(&env->lval, Val_long(0)); + env->curr_char = Val_int(Int_field(tables->transl_const, Int_val(arg))); + caml_modify_field((value)env, + offsetof(struct parser_env, lval) / sizeof(value), + Val_long(0)); } - if (caml_parser_trace) print_token(tables, state, arg); + if (trace()) print_token(tables, state, arg); testshift: n1 = Short(tables->sindex, state); @@ -196,20 +206,20 @@ CAMLprim value caml_parse_engine(struct parser_tables *tables, if (errflag < 3) { errflag = 3; while (1) { - state1 = Int_val(Field(env->s_stack, sp)); + state1 = Int_field(env->s_stack, sp); n1 = Short(tables->sindex, state1); n2 = n1 + ERRCODE; if (n1 != 0 && n2 >= 0 && n2 <= Int_val(tables->tablesize) && Short(tables->check, n2) == ERRCODE) { - if (caml_parser_trace) + if (trace()) fprintf(stderr, "Recovering in state %d\n", state1); goto shift_recover; } else { - if (caml_parser_trace){ + if (trace()){ fprintf(stderr, "Discarding state %d\n", state1); } if (sp <= Int_val(env->stackbase)) { - if (caml_parser_trace){ + if (trace()){ fprintf(stderr, "No more states to discard\n"); } return RAISE_PARSE_ERROR; /* The ML code raises Parse_error */ @@ -220,7 +230,7 @@ CAMLprim value caml_parse_engine(struct parser_tables *tables, } else { if (Int_val(env->curr_char) == 0) return RAISE_PARSE_ERROR; /* The ML code raises Parse_error */ - if (caml_parser_trace) fprintf(stderr, "Discarding last token read\n"); + if (trace()) fprintf(stderr, "Discarding last token read\n"); env->curr_char = Val_int(-1); goto loop; } @@ -229,7 +239,7 @@ CAMLprim value caml_parse_engine(struct parser_tables *tables, env->curr_char = Val_int(-1); if (errflag > 0) errflag--; shift_recover: - if (caml_parser_trace) + if (trace()) fprintf(stderr, "State %d: shift to state %d\n", state, Short(tables->table, n2)); state = Short(tables->table, n2); @@ -241,14 +251,14 @@ CAMLprim value caml_parse_engine(struct parser_tables *tables, case STACKS_GROWN_1: RESTORE; push: - Field(env->s_stack, sp) = Val_int(state); - caml_modify(&Field(env->v_stack, sp), env->lval); + Store_field (env->s_stack, sp, Val_int(state)); + Store_field (env->v_stack, sp, env->lval); Store_field (env->symb_start_stack, sp, env->symb_start); Store_field (env->symb_end_stack, sp, env->symb_end); goto loop; reduce: - if (caml_parser_trace) + if (trace()) fprintf(stderr, "State %d: reduce by rule %d\n", state, n); m = Short(tables->len, n); env->asp = Val_int(sp); @@ -256,7 +266,7 @@ CAMLprim value caml_parse_engine(struct parser_tables *tables, env->rule_len = Val_int(m); sp = sp - m + 1; m = Short(tables->lhs, n); - state1 = Int_val(Field(env->s_stack, sp - 1)); + state1 = Int_field(env->s_stack, sp - 1); n1 = Short(tables->gindex, m); n2 = n1 + state1; if (n1 != 0 && n2 >= 0 && n2 <= Int_val(tables->tablesize) && @@ -277,8 +287,8 @@ CAMLprim value caml_parse_engine(struct parser_tables *tables, /* The ML code calls the semantic action */ case SEMANTIC_ACTION_COMPUTED: RESTORE; - Field(env->s_stack, sp) = Val_int(state); - caml_modify(&Field(env->v_stack, sp), arg); + Store_field(env->s_stack, sp, Val_int(state)); + caml_modify_field(env->v_stack, sp, arg); asp = Int_val(env->asp); Store_field (env->symb_end_stack, sp, Field(env->symb_end_stack, asp)); if (sp > asp) { @@ -298,7 +308,7 @@ CAMLprim value caml_parse_engine(struct parser_tables *tables, CAMLprim value caml_set_parser_trace(value flag) { - value oldflag = Val_bool(caml_parser_trace); - caml_parser_trace = Bool_val(flag); + value oldflag = Val_bool(trace()); + Caml_state->parser_trace = Bool_val(flag); return oldflag; } diff --git a/runtime/platform.c b/runtime/platform.c new file mode 100644 index 0000000000..5ba3e48786 --- /dev/null +++ b/runtime/platform.c @@ -0,0 +1,225 @@ +#define CAML_INTERNALS + +#include <sys/mman.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <sys/time.h> +#include "caml/platform.h" +#include "caml/fail.h" + +/* Mutexes */ + +void caml_plat_mutex_init(caml_plat_mutex * m) +{ + int rc; + pthread_mutexattr_t attr; + rc = pthread_mutexattr_init(&attr); + if (rc != 0) goto error1; + rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); + if (rc != 0) goto error2; + rc = pthread_mutex_init(m, &attr); + // fall through +error2: + pthread_mutexattr_destroy(&attr); +error1: + check_err("mutex_init", rc); +} + +void caml_plat_assert_locked(caml_plat_mutex* m) +{ +#ifdef DEBUG + int r = pthread_mutex_trylock(m); + if (r == EBUSY) { + /* ok, it was locked */ + return; + } else if (r == 0) { + caml_fatal_error("Required mutex not locked"); + } else { + check_err("assert_locked", r); + } +#endif +} + +void caml_plat_assert_all_locks_unlocked() +{ +#ifdef DEBUG + if (lockdepth) caml_fatal_error("Locks still locked at termination"); +#endif +} + +void caml_plat_mutex_free(caml_plat_mutex* m) +{ + check_err("mutex_free", pthread_mutex_destroy(m)); +} + +static void caml_plat_cond_init_aux(caml_plat_cond *cond) +{ + pthread_condattr_t attr; + pthread_condattr_init(&attr); +#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK != (-1) + pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); +#endif + pthread_cond_init(&cond->cond, &attr); +} + +/* Condition variables */ +void caml_plat_cond_init(caml_plat_cond* cond, caml_plat_mutex* m) +{ + caml_plat_cond_init_aux(cond); + cond->mutex = m; +} + +/* TODO: This specific entrypoint is required for systhreads. + Refactoring conditions in platform context with support for + systhreads style conditions would be useful. */ +void caml_plat_cond_init_no_mutex(caml_plat_cond* cond) +{ + caml_plat_cond_init_aux(cond); + cond->mutex = NULL; +} + +void caml_plat_cond_set_mutex(caml_plat_cond *cond, caml_plat_mutex* m) +{ + if (cond->mutex == NULL) + cond->mutex = m; +} + +void caml_plat_wait(caml_plat_cond* cond) +{ + caml_plat_assert_locked(cond->mutex); + check_err("wait", pthread_cond_wait(&cond->cond, cond->mutex)); +} + +int caml_plat_timedwait(caml_plat_cond* cond, int64_t until) +{ + struct timespec t; + int err; + if (until < 0) { + /* until < 0 has definitely timed out, long ago. + letting the code below run risks feeding negative tv_nsec + to timedwait, since (-1 % 1000000000) = -1. */ + return 1; + } + t.tv_sec = until / 1000000000; + t.tv_nsec = until % 1000000000; + err = pthread_cond_timedwait(&cond->cond, cond->mutex, &t); + if (err == ETIMEDOUT) { + return 1; + } else { + return 0; + } +} + +void caml_plat_broadcast(caml_plat_cond* cond) +{ + caml_plat_assert_locked(cond->mutex); + check_err("cond_broadcast", pthread_cond_broadcast(&cond->cond)); +} + +void caml_plat_signal(caml_plat_cond* cond) +{ + caml_plat_assert_locked(cond->mutex); + check_err("cond_signal", pthread_cond_signal(&cond->cond)); +} + +void caml_plat_cond_free(caml_plat_cond* cond) +{ + check_err("cond_free", pthread_cond_destroy(&cond->cond)); + cond->mutex=0; +} + + +/* Memory management */ + +#define Is_power_2(align) \ + ((align) != 0 && ((align) & ((align) - 1)) == 0) + +static uintnat round_up(uintnat size, uintnat align) { + Assert(Is_power_2(align)); + return (size + align - 1) & ~(align - 1); +} + + +uintnat caml_mem_round_up_pages(uintnat size) +{ + return round_up(size, sysconf(_SC_PAGESIZE)); +} + +void* caml_mem_map(uintnat size, uintnat alignment, int reserve_only) +{ + uintnat alloc_sz = caml_mem_round_up_pages(size + alignment); + void* mem; + uintnat base, aligned_start, aligned_end; + + Assert(Is_power_2(alignment)); + alignment = caml_mem_round_up_pages(alignment); + + Assert (alloc_sz > size); + mem = mmap(0, alloc_sz, reserve_only ? PROT_NONE : (PROT_READ | PROT_WRITE), + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (mem == MAP_FAILED) { + return 0; + } + + /* trim to an aligned region */ + base = (uintnat)mem; + aligned_start = round_up(base, alignment); + aligned_end = aligned_start + caml_mem_round_up_pages(size); + caml_mem_unmap((void*)base, aligned_start - base); + caml_mem_unmap((void*)aligned_end, (base + alloc_sz) - aligned_end); + return (void*)aligned_start; +} +static void* map_fixed(void* mem, uintnat size, int prot) +{ + if (mmap((void*)mem, size, prot, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, + -1, 0) == MAP_FAILED) { + return 0; + } else { + return mem; + } +} + +void* caml_mem_commit(void* mem, uintnat size) +{ + void* p = map_fixed(mem, size, PROT_READ | PROT_WRITE); + /* + FIXME: On Linux, with overcommit, you stand a better + chance of getting good error messages in OOM conditions + by forcing the kernel to allocate actual memory by touching + all the pages. Not sure whether this is a good idea, though. + + if (p) memset(p, 0, size); + */ + return p; +} + +void caml_mem_decommit(void* mem, uintnat size) +{ + map_fixed(mem, size, PROT_NONE); +} + +void caml_mem_unmap(void* mem, uintnat size) +{ + munmap(mem, size); +} + +#define Min_sleep_ns 10000 // 10 us +#define Slow_sleep_ns 1000000 // 1 ms +#define Max_sleep_ns 1000000000 // 1 s + +unsigned caml_plat_spin_wait(unsigned spins, + const char* file, int line, + const char* function) +{ + unsigned next_spins; + if (spins < Min_sleep_ns) spins = Min_sleep_ns; + if (spins > Max_sleep_ns) spins = Max_sleep_ns; + next_spins = spins + spins / 4; + if (spins < Slow_sleep_ns && Slow_sleep_ns <= next_spins) { + caml_gc_log("Slow spin-wait loop in %s at %s:%d", function, file, line); + } + usleep(spins/1000); + return next_spins; +} diff --git a/runtime/printexc.c b/runtime/printexc.c index 2828fdbc5a..8dc24601d4 100644 --- a/runtime/printexc.c +++ b/runtime/printexc.c @@ -28,7 +28,6 @@ #include "caml/mlvalues.h" #include "caml/printexc.h" #include "caml/memory.h" -#include "caml/memprof.h" struct stringbuf { char * ptr; @@ -52,21 +51,34 @@ static void add_string(struct stringbuf *buf, const char *s) CAMLexport char * caml_format_exception(value exn) { mlsize_t start, i; - value bucket, v; struct stringbuf buf; char intbuf[64]; char * res; + CAMLparam1(exn); + CAMLlocal4(bucket, v, exnclass, field1); buf.ptr = buf.data; buf.end = buf.data + sizeof(buf.data) - 1; + /* An exception class is a value with tag Object_tag, whose first + field is a string naming the exception. + Exceptions that take parameters (e.g. Invalid_argument) are blocks + with tag 0, where the first field is the exception class. + Exceptions without parameters (e.g. Not_found) are just the exception + class. */ if (Tag_val(exn) == 0) { - add_string(&buf, String_val(Field(Field(exn, 0), 0))); + /* Field 0 of exn is the exception class, which is immutable */ + exnclass = Field(exn, 0); + add_string(&buf, String_val(Field(exnclass, 0))); /* Check for exceptions in the style of Match_failure and Assert_failure */ - if (Wosize_val(exn) == 2 && - Is_block(Field(exn, 1)) && - Tag_val(Field(exn, 1)) == 0 && - caml_is_special_exception(Field(exn, 0))) { - bucket = Field(exn, 1); + if (Wosize_val(exn) == 2) { + caml_read_field(exn, 1, &field1); + } else { + field1 = Val_unit; + } + if (Is_block(field1) && + Tag_val(field1) == 0 && + caml_is_special_exception(exnclass)) { + bucket = field1; start = 0; } else { bucket = exn; @@ -75,7 +87,7 @@ CAMLexport char * caml_format_exception(value exn) add_char(&buf, '('); for (i = start; i < Wosize_val(bucket); i++) { if (i > start) add_string(&buf, ", "); - v = Field(bucket, i); + caml_read_field(bucket, i, &v); if (Is_long(v)) { snprintf(intbuf, sizeof(intbuf), "%" ARCH_INTNAT_PRINTF_FORMAT "d", Long_val(v)); @@ -89,15 +101,18 @@ CAMLexport char * caml_format_exception(value exn) } } add_char(&buf, ')'); - } else - add_string(&buf, String_val(Field(exn, 0))); + } else { + /* Exception without parameters */ + exnclass = exn; + add_string(&buf, String_val(Field(exnclass, 0))); + } *buf.ptr = 0; /* Terminate string */ i = buf.ptr - buf.data + 1; res = caml_stat_alloc_noexc(i); - if (res == NULL) return NULL; + if (res == NULL) CAMLreturnT (char*, NULL); memmove(res, buf.data, i); - return res; + CAMLreturnT (char*, res); } @@ -112,7 +127,8 @@ static void default_fatal_uncaught_exception(value exn) { char * msg; const value * at_exit; - int saved_backtrace_active, saved_backtrace_pos; + int saved_backtrace_active; + intnat saved_backtrace_pos; /* Build a string representation of the exception */ msg = caml_format_exception(exn); @@ -141,13 +157,6 @@ void caml_fatal_uncaught_exception(value exn) handle_uncaught_exception = caml_named_value("Printexc.handle_uncaught_exception"); - - /* If the callback allocates, memprof could be called. In this case, - memprof's callback could raise an exception while - [handle_uncaught_exception] is running, so that the printing of - the exception fails. */ - caml_memprof_set_suspended(1); - if (handle_uncaught_exception != NULL) /* [Printexc.handle_uncaught_exception] does not raise exception. */ caml_callback2(*handle_uncaught_exception, exn, Val_bool(DEBUGGER_IN_USE)); diff --git a/runtime/roots.c b/runtime/roots.c new file mode 100644 index 0000000000..f8daebb5a5 --- /dev/null +++ b/runtime/roots.c @@ -0,0 +1,75 @@ +/**************************************************************************/ +/* */ +/* OCaml */ +/* */ +/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ +/* */ +/* Copyright 1996 Institut National de Recherche en Informatique et */ +/* en Automatique. */ +/* */ +/* All rights reserved. This file is distributed under the terms of */ +/* the GNU Lesser General Public License version 2.1, with the */ +/* special exception on linking described in the file LICENSE. */ +/* */ +/**************************************************************************/ + +#define CAML_INTERNALS + +/* To walk the memory roots for garbage collection */ + +#include "caml/finalise.h" +#include "caml/globroots.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/roots.h" +#include "caml/major_gc.h" +#include "caml/shared_heap.h" +#include "caml/fiber.h" + +#ifdef NATIVE_CODE +#include "caml/stack.h" +/* Communication with [caml_start_program] and [caml_call_gc]. */ + +/* The global roots. + FIXME: These should be promoted, and not scanned here. + FIXME: caml_globals_inited makes assumptions about store ordering. + XXX KC : What to do here? +*/ + +intnat caml_globals_inited = 0; +#endif + +CAMLexport void (*caml_scan_roots_hook)(scanning_action, void* fdata, struct domain *) = NULL; + +void caml_do_roots (scanning_action f, void* fdata, struct domain* d, int do_final_val) +{ + caml_do_local_roots(f, fdata, d->state->local_roots, d->state->current_stack, d->state->gc_regs); + if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(f, fdata, d); + caml_final_do_roots(f, fdata, d, do_final_val); + +} + +CAMLexport void caml_do_local_roots (scanning_action f, void* fdata, + struct caml__roots_block *local_roots, + struct stack_info *current_stack, + value * v_gc_regs) +{ + struct caml__roots_block *lr; + int i, j; + value* sp; + + for (lr = local_roots; lr != NULL; lr = lr->next) { + for (i = 0; i < lr->ntables; i++){ + for (j = 0; j < lr->nitems; j++){ + sp = &(lr->tables[i][j]); + if (*sp != 0) { + f (fdata, *sp, sp); + } + } + } + } + caml_scan_stack(f, fdata, current_stack, v_gc_regs); +} diff --git a/runtime/roots_byt.c b/runtime/roots_byt.c deleted file mode 100644 index 744495b793..0000000000 --- a/runtime/roots_byt.c +++ /dev/null @@ -1,144 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy and Damien Doligez, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* To walk the memory roots for garbage collection */ - -#include "caml/codefrag.h" -#include "caml/finalise.h" -#include "caml/globroots.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/roots.h" -#include "caml/stacks.h" -#include "caml/memprof.h" -#include "caml/eventlog.h" - -CAMLexport void (*caml_scan_roots_hook) (scanning_action f) = NULL; - -/* FIXME should rename to [caml_oldify_minor_roots] and synchronise with - roots_nat.c */ -/* Call [caml_oldify_one] on (at least) all the roots that point to the minor - heap. */ -void caml_oldify_local_roots (void) -{ - register value * sp; - struct caml__roots_block *lr; - intnat i, j; - - /* The stack */ - /* [caml_oldify_one] acts only on pointers into the minor heap. - So, it is safe to pass code pointers to [caml_oldify_one], - even in no-naked-pointers mode */ - for (sp = Caml_state->extern_sp; sp < Caml_state->stack_high; sp++) { - caml_oldify_one (*sp, sp); - } - /* Local C roots */ /* FIXME do the old-frame trick ? */ - for (lr = Caml_state->local_roots; lr != NULL; lr = lr->next) { - for (i = 0; i < lr->ntables; i++){ - for (j = 0; j < lr->nitems; j++){ - sp = &(lr->tables[i][j]); - caml_oldify_one (*sp, sp); - } - } - } - /* Global C roots */ - caml_scan_global_young_roots(&caml_oldify_one); - /* Finalised values */ - caml_final_oldify_young_roots (); - /* Memprof */ - caml_memprof_oldify_young_roots (); - /* Hook */ - if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(&caml_oldify_one); -} - -/* Call [caml_darken] on all roots */ - -void caml_darken_all_roots_start (void) -{ - caml_do_roots (caml_darken, 1); -} - -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) -{ - /* Global variables */ - CAML_EV_BEGIN(EV_MAJOR_ROOTS_GLOBAL); - f(caml_global_data, &caml_global_data); - CAML_EV_END(EV_MAJOR_ROOTS_GLOBAL); - /* The stack and the local C roots */ - CAML_EV_BEGIN(EV_MAJOR_ROOTS_LOCAL); - caml_do_local_roots(f, Caml_state->extern_sp, Caml_state->stack_high, - Caml_state->local_roots); - CAML_EV_END(EV_MAJOR_ROOTS_LOCAL); - /* Global C roots */ - CAML_EV_BEGIN(EV_MAJOR_ROOTS_C); - caml_scan_global_roots(f); - CAML_EV_END(EV_MAJOR_ROOTS_C); - /* Finalised values */ - CAML_EV_BEGIN(EV_MAJOR_ROOTS_FINALISED); - caml_final_do_roots (f); - CAML_EV_END(EV_MAJOR_ROOTS_FINALISED); - /* Memprof */ - CAML_EV_BEGIN(EV_MAJOR_ROOTS_MEMPROF); - caml_memprof_do_roots (f); - CAML_EV_END(EV_MAJOR_ROOTS_MEMPROF); - /* Hook */ - CAML_EV_BEGIN(EV_MAJOR_ROOTS_HOOK); - if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(f); - CAML_EV_END(EV_MAJOR_ROOTS_HOOK); -} - -CAMLexport void caml_do_local_roots (scanning_action f, value *stack_low, - value *stack_high, - struct caml__roots_block *local_roots) -{ - register value * sp; - struct caml__roots_block *lr; - int i, j; - - for (sp = stack_low; sp < stack_high; sp++) { -#ifdef NO_NAKED_POINTERS - /* Code pointers inside the stack are naked pointers. - We must avoid passing them to function [f]. */ - value v = *sp; - if (Is_block(v) && caml_find_code_fragment_by_pc((char *) v) == NULL) { - f(v, sp); - } -#else - f (*sp, sp); -#endif - } - for (lr = local_roots; lr != NULL; lr = lr->next) { - for (i = 0; i < lr->ntables; i++){ - for (j = 0; j < lr->nitems; j++){ - sp = &(lr->tables[i][j]); - f (*sp, sp); - } - } - } -} diff --git a/runtime/roots_nat.c b/runtime/roots_nat.c deleted file mode 100644 index ec66e2dbf5..0000000000 --- a/runtime/roots_nat.c +++ /dev/null @@ -1,524 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* To walk the memory roots for garbage collection */ - -#include "caml/finalise.h" -#include "caml/globroots.h" -#include "caml/memory.h" -#include "caml/major_gc.h" -#include "caml/minor_gc.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/stack.h" -#include "caml/roots.h" -#include "caml/memprof.h" -#include "caml/eventlog.h" -#include <string.h> -#include <stdio.h> - -/* Roots registered from C functions */ - -void (*caml_scan_roots_hook) (scanning_action) = NULL; - -/* The hashtable of frame descriptors */ -frame_descr ** caml_frame_descriptors = NULL; -uintnat caml_frame_descriptors_mask = 0; - -/* Linked-list */ - -typedef struct link { - void *data; - struct link *next; -} link; - -static link *cons(void *data, link *tl) { - link *lnk = caml_stat_alloc(sizeof(link)); - lnk->data = data; - lnk->next = tl; - return lnk; -} - -#define iter_list(list,lnk) \ - for (lnk = list; lnk != NULL; lnk = lnk->next) - -/* Linked-list of frametables */ - -static link *frametables = NULL; -static intnat num_descr = 0; - -static intnat count_descriptors(link *list) { - intnat num_descr = 0; - link *lnk; - iter_list(list,lnk) { - num_descr += *((intnat*) lnk->data); - } - return num_descr; -} - -static link* frametables_list_tail(link *list) { - link *lnk, *tail = NULL; - iter_list(list,lnk) { - tail = lnk; - } - return tail; -} - -static frame_descr * next_frame_descr(frame_descr * d) { - unsigned char num_allocs = 0, *p; - CAMLassert(d->retaddr >= 4096); - /* Skip to end of live_ofs */ - p = (unsigned char*)&d->live_ofs[d->num_live]; - /* Skip alloc_lengths if present */ - if (d->frame_size & 2) { - num_allocs = *p; - p += num_allocs + 1; - } - /* Skip debug info if present */ - if (d->frame_size & 1) { - /* Align to 32 bits */ - p = Align_to(p, uint32_t); - p += sizeof(uint32_t) * (d->frame_size & 2 ? num_allocs : 1); - } - /* Align to word size */ - p = Align_to(p, void*); - return ((frame_descr*) p); -} - -static void fill_hashtable(link *frametables) { - intnat len, j; - intnat * tbl; - frame_descr * d; - uintnat h; - link *lnk = NULL; - - iter_list(frametables,lnk) { - tbl = (intnat*) lnk->data; - len = *tbl; - d = (frame_descr *)(tbl + 1); - for (j = 0; j < len; j++) { - h = Hash_retaddr(d->retaddr); - while (caml_frame_descriptors[h] != NULL) { - h = (h+1) & caml_frame_descriptors_mask; - } - caml_frame_descriptors[h] = d; - d = next_frame_descr(d); - } - } -} - -static void init_frame_descriptors(link *new_frametables) -{ - intnat tblsize, increase, i; - link *tail = NULL; - - CAMLassert(new_frametables); - - tail = frametables_list_tail(new_frametables); - increase = count_descriptors(new_frametables); - tblsize = caml_frame_descriptors_mask + 1; - - /* Reallocate the caml_frame_descriptor table if it is too small */ - if(tblsize < (num_descr + increase) * 2) { - - /* Merge both lists */ - tail->next = frametables; - frametables = NULL; - - /* [num_descr] can be less than [num_descr + increase] if frame - tables where unregistered */ - num_descr = count_descriptors(new_frametables); - - tblsize = 4; - while (tblsize < 2 * num_descr) tblsize *= 2; - - caml_frame_descriptors_mask = tblsize - 1; - if(caml_frame_descriptors) caml_stat_free(caml_frame_descriptors); - caml_frame_descriptors = - (frame_descr **) caml_stat_alloc(tblsize * sizeof(frame_descr *)); - for (i = 0; i < tblsize; i++) caml_frame_descriptors[i] = NULL; - - fill_hashtable(new_frametables); - } else { - num_descr += increase; - fill_hashtable(new_frametables); - tail->next = frametables; - } - - frametables = new_frametables; -} - -void caml_init_frame_descriptors(void) { - intnat i; - link *new_frametables = NULL; - for (i = 0; caml_frametable[i] != 0; i++) - new_frametables = cons(caml_frametable[i],new_frametables); - init_frame_descriptors(new_frametables); -} - -void caml_register_frametable(intnat *table) { - link *new_frametables = cons(table,NULL); - init_frame_descriptors(new_frametables); -} - -static void remove_entry(frame_descr * d) { - uintnat i; - uintnat r; - uintnat j; - - i = Hash_retaddr(d->retaddr); - while (caml_frame_descriptors[i] != d) { - i = (i+1) & caml_frame_descriptors_mask; - } - - r1: - j = i; - caml_frame_descriptors[i] = NULL; - r2: - i = (i+1) & caml_frame_descriptors_mask; - // r3 - if(caml_frame_descriptors[i] == NULL) return; - r = Hash_retaddr(caml_frame_descriptors[i]->retaddr); - /* If r is between i and j (cyclically), i.e. if - caml_frame_descriptors[i]->retaddr don't need to be moved */ - if(( ( j < r ) && ( r <= i ) ) || - ( ( i < j ) && ( j < r ) ) || /* i cycled, r not */ - ( ( r <= i ) && ( i < j ) ) ) { /* i and r cycled */ - goto r2; - } - // r4 - caml_frame_descriptors[j] = caml_frame_descriptors[i]; - goto r1; -} - -void caml_unregister_frametable(intnat *table) { - intnat len, j; - link *lnk; - link *previous = frametables; - frame_descr * d; - - len = *table; - d = (frame_descr *)(table + 1); - for (j = 0; j < len; j++) { - remove_entry(d); - d = next_frame_descr(d); - } - - iter_list(frametables,lnk) { - if(lnk->data == table) { - previous->next = lnk->next; - caml_stat_free(lnk); - break; - } - previous = lnk; - } -} - -/* Communication with [caml_start_program] and [caml_call_gc]. */ - -intnat caml_globals_inited = 0; -static intnat caml_globals_scanned = 0; -static link * caml_dyn_globals = NULL; - -void caml_register_dyn_global(void *v) { - caml_dyn_globals = cons((void*) v,caml_dyn_globals); -} - -/* Call [caml_oldify_one] on (at least) all the roots that point to the minor - heap. */ -void caml_oldify_local_roots (void) -{ - char * sp; - uintnat retaddr; - value * regs; - frame_descr * d; - uintnat h; - intnat i, j; - int n, ofs; - unsigned short * p; - value * glob; - value * root; - struct caml__roots_block *lr; - link *lnk; - - /* The global roots */ - for (i = caml_globals_scanned; - i <= caml_globals_inited && caml_globals[i] != 0; - i++) { - for(glob = caml_globals[i]; *glob != 0; glob++) { - for (j = 0; j < Wosize_val(*glob); j++){ - Oldify (&Field (*glob, j)); - } - } - } - caml_globals_scanned = caml_globals_inited; - - /* Dynamic global roots */ - iter_list(caml_dyn_globals, lnk) { - for(glob = (value *) lnk->data; *glob != 0; glob++) { - for (j = 0; j < Wosize_val(*glob); j++){ - Oldify (&Field (*glob, j)); - } - } - } - - /* The stack and local roots */ - sp = Caml_state->bottom_of_stack; - retaddr = Caml_state->last_return_address; - regs = Caml_state->gc_regs; - if (sp != NULL) { - while (1) { - /* Find the descriptor corresponding to the return address */ - h = Hash_retaddr(retaddr); - while(1) { - d = caml_frame_descriptors[h]; - if (d->retaddr == retaddr) break; - h = (h+1) & caml_frame_descriptors_mask; - } - if (d->frame_size != 0xFFFF) { - /* Scan the roots in this frame */ - for (p = d->live_ofs, n = d->num_live; n > 0; n--, p++) { - ofs = *p; - if (ofs & 1) { - root = regs + (ofs >> 1); - } else { - root = (value *)(sp + ofs); - } - Oldify (root); - } - /* Move to next frame */ - sp += (d->frame_size & 0xFFFC); - retaddr = Saved_return_address(sp); -#ifdef Already_scanned - /* Stop here if the frame has been scanned during earlier GCs */ - if (Already_scanned(sp, retaddr)) break; - /* Mark frame as already scanned */ - Mark_scanned(sp, retaddr); -#endif - } else { - /* This marks the top of a stack chunk for an ML callback. - Skip C portion of stack and continue with next ML stack chunk. */ - struct caml_context * next_context = Callback_link(sp); - sp = next_context->bottom_of_stack; - retaddr = next_context->last_retaddr; - regs = next_context->gc_regs; - /* A null sp means no more ML stack chunks; stop here. */ - if (sp == NULL) break; - } - } - } - /* Local C roots */ - for (lr = Caml_state->local_roots; lr != NULL; lr = lr->next) { - for (i = 0; i < lr->ntables; i++){ - for (j = 0; j < lr->nitems; j++){ - root = &(lr->tables[i][j]); - Oldify (root); - } - } - } - /* Global C roots */ - caml_scan_global_young_roots(&caml_oldify_one); - /* Finalised values */ - caml_final_oldify_young_roots (); - /* Memprof */ - caml_memprof_oldify_young_roots (); - /* Hook */ - if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(&caml_oldify_one); -} - -uintnat caml_incremental_roots_count = 0; - -/* 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, 0); -} - -/* 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_EV_BEGIN(EV_MAJOR_MARK_GLOBAL_ROOTS_SLICE); - - /* 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_EV_END(EV_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_EV_BEGIN(EV_MAJOR_ROOTS_DYNAMIC_GLOBAL); - 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++) { - for (j = 0; j < Wosize_val(*glob); j++){ - f (Field (*glob, j), &Field (*glob, j)); - } - } - } - CAML_EV_END(EV_MAJOR_ROOTS_DYNAMIC_GLOBAL); - /* The stack and local roots */ - CAML_EV_BEGIN(EV_MAJOR_ROOTS_LOCAL); - caml_do_local_roots(f, Caml_state->bottom_of_stack, - Caml_state->last_return_address, Caml_state->gc_regs, - Caml_state->local_roots); - CAML_EV_END(EV_MAJOR_ROOTS_LOCAL); - /* Global C roots */ - CAML_EV_BEGIN(EV_MAJOR_ROOTS_C); - caml_scan_global_roots(f); - CAML_EV_END(EV_MAJOR_ROOTS_C); - /* Finalised values */ - CAML_EV_BEGIN(EV_MAJOR_ROOTS_FINALISED); - caml_final_do_roots (f); - CAML_EV_END(EV_MAJOR_ROOTS_FINALISED); - /* Memprof */ - CAML_EV_BEGIN(EV_MAJOR_ROOTS_MEMPROF); - caml_memprof_do_roots (f); - CAML_EV_END(EV_MAJOR_ROOTS_MEMPROF); - /* Hook */ - CAML_EV_BEGIN(EV_MAJOR_ROOTS_HOOK); - if (caml_scan_roots_hook != NULL) (*caml_scan_roots_hook)(f); - CAML_EV_END(EV_MAJOR_ROOTS_HOOK); -} - -void caml_do_local_roots(scanning_action f, char * bottom_of_stack, - uintnat last_retaddr, value * gc_regs, - struct caml__roots_block * local_roots) -{ - char * sp; - uintnat retaddr; - value * regs; - frame_descr * d; - uintnat h; - int i, j, n, ofs; - unsigned short * p; - value * root; - struct caml__roots_block *lr; - - sp = bottom_of_stack; - retaddr = last_retaddr; - regs = gc_regs; - if (sp != NULL) { - while (1) { - /* Find the descriptor corresponding to the return address */ - h = Hash_retaddr(retaddr); - while(1) { - d = caml_frame_descriptors[h]; - if (d->retaddr == retaddr) break; - h = (h+1) & caml_frame_descriptors_mask; - } - if (d->frame_size != 0xFFFF) { - /* Scan the roots in this frame */ - for (p = d->live_ofs, n = d->num_live; n > 0; n--, p++) { - ofs = *p; - if (ofs & 1) { - root = regs + (ofs >> 1); - } else { - root = (value *)(sp + ofs); - } - f (*root, root); - } - /* Move to next frame */ - sp += (d->frame_size & 0xFFFC); - retaddr = Saved_return_address(sp); -#ifdef Mask_already_scanned - retaddr = Mask_already_scanned(retaddr); -#endif - } else { - /* This marks the top of a stack chunk for an ML callback. - Skip C portion of stack and continue with next ML stack chunk. */ - struct caml_context * next_context = Callback_link(sp); - sp = next_context->bottom_of_stack; - retaddr = next_context->last_retaddr; - regs = next_context->gc_regs; - /* A null sp means no more ML stack chunks; stop here. */ - if (sp == NULL) break; - } - } - } - /* Local C roots */ - for (lr = local_roots; lr != NULL; lr = lr->next) { - for (i = 0; i < lr->ntables; i++){ - for (j = 0; j < lr->nitems; j++){ - root = &(lr->tables[i][j]); - f (*root, root); - } - } - } -} - -uintnat (*caml_stack_usage_hook)(void) = NULL; - -uintnat caml_stack_usage (void) -{ - uintnat sz; - sz = (value *) Caml_state->top_of_stack - - (value *) Caml_state->bottom_of_stack; - if (caml_stack_usage_hook != NULL) - sz += (*caml_stack_usage_hook)(); - return sz; -} diff --git a/runtime/shared_heap.c b/runtime/shared_heap.c new file mode 100644 index 0000000000..43cf7bc205 --- /dev/null +++ b/runtime/shared_heap.c @@ -0,0 +1,850 @@ +#define CAML_INTERNALS + +#include <stdlib.h> +#include <string.h> + +#include "caml/addrmap.h" +#include "caml/custom.h" +#include "caml/fail.h" +#include "caml/fiber.h" /* for verification */ +#include "caml/gc.h" +#include "caml/globroots.h" +#include "caml/memory.h" +#include "caml/mlvalues.h" +#include "caml/platform.h" +#include "caml/roots.h" +#include "caml/shared_heap.h" +#include "caml/sizeclasses.h" +#include "caml/startup_aux.h" + +typedef unsigned int sizeclass; +struct global_heap_state global = {0 << 8, 1 << 8, 2 << 8}; + +typedef struct pool { + struct pool* next; + value* next_obj; + struct domain* owner; + sizeclass sz; +} pool; +CAML_STATIC_ASSERT(sizeof(pool) == Bsize_wsize(POOL_HEADER_WSIZE)); +#define POOL_HEADER_SZ sizeof(pool) + +typedef struct large_alloc { + struct domain* owner; + struct large_alloc* next; +} large_alloc; +CAML_STATIC_ASSERT(sizeof(large_alloc) % sizeof(value) == 0); +#define LARGE_ALLOC_HEADER_SZ sizeof(large_alloc) + +struct { + caml_plat_mutex lock; + pool* free; + + /* these only contain swept memory of terminated domains*/ + struct heap_stats stats; + pool* global_avail_pools[NUM_SIZECLASSES]; + pool* global_full_pools[NUM_SIZECLASSES]; + large_alloc* global_large; +} pool_freelist = { + CAML_PLAT_MUTEX_INITIALIZER, + NULL, + { 0, }, + { 0, }, + { 0, }, + NULL +}; + +/* readable and writable only by the current thread */ +struct caml_heap_state { + pool* avail_pools[NUM_SIZECLASSES]; + pool* full_pools[NUM_SIZECLASSES]; + pool* unswept_avail_pools[NUM_SIZECLASSES]; + pool* unswept_full_pools[NUM_SIZECLASSES]; + + large_alloc* swept_large; + large_alloc* unswept_large; + + sizeclass next_to_sweep; + + struct domain* owner; + + struct heap_stats stats; +}; + +struct caml_heap_state* caml_init_shared_heap() { + int i; + struct caml_heap_state* heap; + + heap = caml_stat_alloc_noexc(sizeof(struct caml_heap_state)); + if(heap != NULL) { + for (i = 0; i<NUM_SIZECLASSES; i++) { + heap->avail_pools[i] = heap->full_pools[i] = + heap->unswept_avail_pools[i] = heap->unswept_full_pools[i] = 0; + } + heap->next_to_sweep = 0; + heap->swept_large = 0; + heap->unswept_large = 0; + heap->owner = caml_domain_self(); + memset(&heap->stats, 0, sizeof(heap->stats)); + } + return heap; +} + +static int move_all_pools(pool** src, pool** dst, struct domain* new_owner) { + int count = 0; + while (*src) { + pool* p = *src; + *src = p->next; + p->owner = new_owner; + p->next = *dst; + *dst = p; + count++; + } + return count; +} + +void caml_teardown_shared_heap(struct caml_heap_state* heap) { + int i; + int released = 0, released_large = 0; + caml_plat_lock(&pool_freelist.lock); + for (i = 0; i < NUM_SIZECLASSES; i++) { + released += + move_all_pools(&heap->avail_pools[i], &pool_freelist.global_avail_pools[i], NULL); + released += + move_all_pools(&heap->full_pools[i], &pool_freelist.global_full_pools[i], NULL); + /* should be swept by now */ + Assert(!heap->unswept_avail_pools[i]); + Assert(!heap->unswept_full_pools[i]); + } + Assert(!heap->unswept_large); + while (heap->swept_large) { + large_alloc* a = heap->swept_large; + heap->swept_large = a->next; + a->next = pool_freelist.global_large; + pool_freelist.global_large = a; + released_large++; + } + caml_accum_heap_stats(&pool_freelist.stats, &heap->stats); + caml_plat_unlock(&pool_freelist.lock); + caml_stat_free(heap); + caml_gc_log("Shutdown shared heap. Released %d active pools, %d large", + released, released_large); +} + +void caml_sample_heap_stats(struct caml_heap_state* local, struct heap_stats* h) +{ + *h = local->stats; +} + + +/* Allocating and deallocating pools from the global freelist. */ + +#define POOLS_PER_ALLOCATION 16 +static pool* pool_acquire(struct caml_heap_state* local) { + pool* r; + + caml_plat_lock(&pool_freelist.lock); + if (!pool_freelist.free) { + void* mem = caml_mem_map(Bsize_wsize(POOL_WSIZE) * POOLS_PER_ALLOCATION, + Bsize_wsize(POOL_WSIZE), 0 /* allocate */); + int i; + if (mem) { + pool_freelist.free = mem; + for (i=1; i<POOLS_PER_ALLOCATION; i++) { + r = (pool*)(((uintnat)mem) + ((uintnat)i) * Bsize_wsize(POOL_WSIZE)); + r->next = pool_freelist.free; + r->owner = 0; + pool_freelist.free = r; + } + } + } + r = pool_freelist.free; + if (r) + pool_freelist.free = r->next; + caml_plat_unlock(&pool_freelist.lock); + + if (r) Assert (r->owner == 0); + return r; +} + +static void pool_release(struct caml_heap_state* local, pool* pool, sizeclass sz) { + pool->owner = 0; + Assert(pool->sz == sz); + local->stats.pool_words -= POOL_WSIZE; + local->stats.pool_frag_words -= POOL_HEADER_WSIZE + wastage_sizeclass[sz]; + /* FIXME: give free pools back to the OS */ + caml_plat_lock(&pool_freelist.lock); + pool->next = pool_freelist.free; + pool_freelist.free = pool; + caml_plat_unlock(&pool_freelist.lock); +} + +static void calc_pool_stats(pool* a, sizeclass sz, struct heap_stats* s) { + value* p = (value*)((char*)a + POOL_HEADER_SZ); + value* end = (value*)a + POOL_WSIZE; + mlsize_t wh = wsize_sizeclass[sz]; + s->pool_frag_words += Wsize_bsize(POOL_HEADER_SZ); + + while (p + wh <= end) { + header_t hd = (header_t)*p; + if (hd) { + s->pool_live_words += Whsize_hd(hd); + s->pool_frag_words += wh - Whsize_hd(hd); + s->pool_live_blocks++; + } + + p += wh; + } + Assert(end - p == wastage_sizeclass[sz]); + s->pool_frag_words += end - p; + s->pool_words += POOL_WSIZE; +} + +/* Initialize a pool and its object freelist */ +static inline void pool_initialize(pool* r, sizeclass sz, struct domain* owner) +{ + mlsize_t wh = wsize_sizeclass[sz]; + value* p = (value*)((char*)r + POOL_HEADER_SZ); + value* end = (value*)((char*)r + Bsize_wsize(POOL_WSIZE)); + + r->next = 0; + r->owner = owner; + r->next_obj = 0; + r->sz = sz; + + p[0] = 0; + p[1] = 0; + p += wh; + + while (p + wh <= end) { + p[0] = 0; /* zero header indicates free object */ + p[1] = (value)(p - wh); + p += wh; + } + r->next_obj = p - wh; +} + +/* Allocating an object from a pool */ +static intnat pool_sweep(struct caml_heap_state* local, pool**, sizeclass sz , int release_to_global_pool); + +/* Adopt pool from the pool_freelist avail and full pools + to satisfy an alloction */ +static pool* pool_global_adopt(struct caml_heap_state* local, sizeclass sz) +{ + pool* r = NULL; + int adopted_pool = 0; + + /* probably no available pools out there to be had */ + if( !pool_freelist.global_avail_pools[sz] && + !pool_freelist.global_full_pools[sz] ) + return NULL; + + /* Haven't managed to find a pool locally, try the global ones */ + caml_plat_lock(&pool_freelist.lock); + if( pool_freelist.global_avail_pools[sz] ) { + r = pool_freelist.global_avail_pools[sz]; + + if( r ) { + struct heap_stats tmp_stats = { 0 }; + pool_freelist.global_avail_pools[sz] = r->next; + r->next = 0; + local->avail_pools[sz] = r; + + #ifdef DEBUG + { + value* next_obj = r->next_obj; + while( next_obj ) { + Assert(next_obj[0] == 0); + next_obj = (value*)next_obj[1]; + } + } + #endif + + calc_pool_stats(r, sz, &tmp_stats); + caml_accum_heap_stats(&local->stats, &tmp_stats); + caml_remove_heap_stats(&pool_freelist.stats, &tmp_stats); + + if (local->stats.pool_words > local->stats.pool_max_words) + local->stats.pool_max_words = local->stats.pool_words; + } + } + + /* There were no global avail pools, so let's adopt one of the full ones and try + our luck sweeping it later on */ + if( !r ) { + struct heap_stats tmp_stats = { 0 }; + + r = pool_freelist.global_full_pools[sz]; + + if( r ) { + pool_freelist.global_full_pools[sz] = r->next; + r->next = local->full_pools[sz]; + local->full_pools[sz] = r; + + calc_pool_stats(r, sz, &tmp_stats); + caml_accum_heap_stats(&local->stats, &tmp_stats); + caml_remove_heap_stats(&pool_freelist.stats, &tmp_stats); + + adopted_pool = 1; + r = 0; // this pool is full + + if (local->stats.pool_words > local->stats.pool_max_words) { + local->stats.pool_max_words = local->stats.pool_words; + } + } + } + + caml_plat_unlock(&pool_freelist.lock); + + if( !r && adopted_pool ) { + Caml_state->major_work_todo -= + pool_sweep(local, &local->full_pools[sz], sz, 0); + r = local->avail_pools[sz]; + } + return r; +} + +/* Allocating an object from a pool */ +static pool* pool_find(struct caml_heap_state* local, sizeclass sz) { + pool* r; + + /* Hopefully we have a pool we can use directly */ + r = local->avail_pools[sz]; + if (r) return r; + + /* Otherwise, try to sweep until we find one */ + while (!local->avail_pools[sz] && local->unswept_avail_pools[sz]) { + Caml_state->major_work_todo -= + pool_sweep(local, &local->unswept_avail_pools[sz], sz, 0); + } + + r = local->avail_pools[sz]; + if (r) return r; + + /* Haven't managed to find a pool locally, try the global ones */ + r = pool_global_adopt(local, sz); + if (r) return r; + + /* Failing that, we need to allocate a new pool */ + r = pool_acquire(local); + if (!r) return 0; /* if we can't allocate, give up */ + + local->stats.pool_words += POOL_WSIZE; + if (local->stats.pool_words > local->stats.pool_max_words) + local->stats.pool_max_words = local->stats.pool_words; + local->stats.pool_frag_words += POOL_HEADER_WSIZE + wastage_sizeclass[sz]; + + /* Having allocated a new pool, set it up for size sz */ + local->avail_pools[sz] = r; + pool_initialize(r, sz, local->owner); + + return r; +} + +static void* pool_allocate(struct caml_heap_state* local, sizeclass sz) { + value* p; + value* next; + pool* r = pool_find(local, sz); + + if (!r) return 0; + + + p = r->next_obj; + next = (value*)p[1]; + r->next_obj = next; + Assert(p[0] == 0); + if (!next) { + local->avail_pools[sz] = r->next; + r->next = local->full_pools[sz]; + local->full_pools[sz] = r; + } + + Assert(r->next_obj == 0 || *r->next_obj == 0); + return p; +} + +static void* large_allocate(struct caml_heap_state* local, mlsize_t sz) { + large_alloc* a = malloc(sz + LARGE_ALLOC_HEADER_SZ); + if (!a) caml_raise_out_of_memory(); + local->stats.large_words += Wsize_bsize(sz + LARGE_ALLOC_HEADER_SZ); + if (local->stats.large_words > local->stats.large_max_words) + local->stats.large_max_words = local->stats.large_words; + local->stats.large_blocks++; + a->owner = local->owner; + a->next = local->swept_large; + local->swept_large = a; + return (char*)a + LARGE_ALLOC_HEADER_SZ; +} + +value* caml_shared_try_alloc(struct caml_heap_state* local, mlsize_t wosize, + tag_t tag, int pinned) +{ + mlsize_t whsize = Whsize_wosize(wosize); + value* p; + uintnat colour; + + Assert (wosize > 0); + Assert (tag != Infix_tag); + if (whsize <= SIZECLASS_MAX) { + struct heap_stats* s; + sizeclass sz = sizeclass_wsize[whsize]; + Assert(wsize_sizeclass[sz] >= whsize); + p = pool_allocate(local, sz); + if (!p) return 0; + s = &local->stats; + s->pool_live_blocks++; + s->pool_live_words += whsize; + s->pool_frag_words += wsize_sizeclass[sz] - whsize; + } else { + p = large_allocate(local, Bsize_wsize(whsize)); + if (!p) return 0; + } + colour = pinned ? NOT_MARKABLE : global.MARKED; + Hd_hp (p) = Make_header(wosize, tag, colour); +#ifdef DEBUG + { + int i; + for (i = 0; i < wosize; i++) { + Op_val(Val_hp(p))[i] = Debug_free_major; + } + } +#endif + return p; +} + +struct pool* caml_pool_of_shared_block(value v) +{ + mlsize_t whsize; + Assert (Is_block(v) && !Is_young(v)); + whsize = Whsize_wosize(Wosize_val(v)); + if (whsize > 0 && whsize <= SIZECLASS_MAX) { + return (pool*)((uintnat)v &~(POOL_WSIZE * sizeof(value) - 1)); + } else { + return 0; + } +} + +/* Sweeping */ + +static intnat pool_sweep(struct caml_heap_state* local, pool** plist, sizeclass sz, int release_to_global_pool) { + intnat work = 0; + pool* a = *plist; + if (!a) return 0; + *plist = a->next; + + { + value* p = (value*)((char*)a + POOL_HEADER_SZ); + value* end = (value*)a + POOL_WSIZE; + mlsize_t wh = wsize_sizeclass[sz]; + int all_used = 1; + struct heap_stats* s = &local->stats; + + while (p + wh <= end) { + header_t hd = (header_t)*p; + if (hd == 0) { + /* already on freelist */ + all_used = 0; + } else if (Has_status_hd(hd, global.GARBAGE)) { + Assert(Whsize_hd(hd) <= wh); + if (Tag_hd (hd) == Custom_tag) { + void (*final_fun)(value) = Custom_ops_val(Val_hp(p))->finalize; + if (final_fun != NULL) final_fun(Val_hp(p)); + } + /* add to freelist */ + p[0] = 0; + p[1] = (value)a->next_obj; + Assert(Is_block((value)p)); + a->next_obj = p; + all_used = 0; + /* update stats */ + s->pool_live_blocks--; + s->pool_live_words -= Whsize_hd(hd); + local->owner->state->swept_words += Whsize_hd(hd); + s->pool_frag_words -= (wh - Whsize_hd(hd)); + } else { + /* still live, the pool can't be released to the global freelist */ + release_to_global_pool = 0; + } + p += wh; + work += wh; + } + + if (release_to_global_pool) { + pool_release(local, a, sz); + } else { + pool** list = all_used ? &local->full_pools[sz] : &local->avail_pools[sz]; + a->next = *list; + *list = a; + } + } + + return work; +} + +static intnat large_alloc_sweep(struct caml_heap_state* local) { + value* p; + header_t hd; + large_alloc* a = local->unswept_large; + if (!a) return 0; + local->unswept_large = a->next; + + p = (value*)((char*)a + LARGE_ALLOC_HEADER_SZ); + hd = (header_t)*p; + if (Has_status_hd(hd, global.GARBAGE)) { + if (Tag_hd (hd) == Custom_tag) { + void (*final_fun)(value) = Custom_ops_val(Val_hp(p))->finalize; + if (final_fun != NULL) final_fun(Val_hp(p)); + } + + local->stats.large_words -= + Whsize_hd(hd) + Wsize_bsize(LARGE_ALLOC_HEADER_SZ); + local->owner->state->swept_words += + Whsize_hd(hd) + Wsize_bsize(LARGE_ALLOC_HEADER_SZ); + local->stats.large_blocks--; + free(a); + } else { + a->next = local->swept_large; + local->swept_large = a; + } + + return Whsize_hd(hd); +} + +static void verify_swept(struct caml_heap_state*); + +intnat caml_sweep(struct caml_heap_state* local, intnat work) { + /* Sweep local pools */ + while (work > 0 && local->next_to_sweep < NUM_SIZECLASSES) { + sizeclass sz = local->next_to_sweep; + intnat full_sweep_work = 0; + intnat avail_sweep_work = + pool_sweep(local, &local->unswept_avail_pools[sz], sz, 1); + work -= avail_sweep_work; + + if (work > 0) { + full_sweep_work = pool_sweep(local, &local->unswept_full_pools[sz], sz, 1); + work -= full_sweep_work; + } + + if(full_sweep_work+avail_sweep_work == 0) { + local->next_to_sweep++; + } + } + + /* Sweep global pools */ + while (work > 0 && local->unswept_large) { + work -= large_alloc_sweep(local); + } + + if (caml_params->verify_heap && work > 0) { + /* sweeping is complete, check everything worked */ + verify_swept(local); + } + return work; +} + +uintnat caml_heap_size(struct caml_heap_state* local) { + return Bsize_wsize(local->stats.pool_words + local->stats.large_words); +} + +uintnat caml_top_heap_words(struct caml_heap_state* local) { + return local->stats.pool_max_words + local->stats.large_max_words; +} + + +uintnat caml_heap_blocks(struct caml_heap_state* local) { + return local->stats.pool_live_blocks + local->stats.large_blocks; +} + +void caml_redarken_pool(struct pool* r, scanning_action f, void* fdata) { + mlsize_t wh = wsize_sizeclass[r->sz]; + value* p = (value*)((char*)r + POOL_HEADER_SZ); + value* end = (value*)((char*)r + Bsize_wsize(POOL_WSIZE)); + + while (p + wh <= end) { + header_t hd = p[0]; + if (hd != 0 && Has_status_hd(hd, global.MARKED)) { + f(fdata, Val_hp(p), 0); + } + p += wh; + } +} + + +const header_t atoms[256] = { +#define A(i) Make_header(0, i, NOT_MARKABLE) +A(0),A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),A(10), +A(11),A(12),A(13),A(14),A(15),A(16),A(17),A(18),A(19),A(20), +A(21),A(22),A(23),A(24),A(25),A(26),A(27),A(28),A(29),A(30), +A(31),A(32),A(33),A(34),A(35),A(36),A(37),A(38),A(39),A(40), +A(41),A(42),A(43),A(44),A(45),A(46),A(47),A(48),A(49),A(50), +A(51),A(52),A(53),A(54),A(55),A(56),A(57),A(58),A(59),A(60), +A(61),A(62),A(63),A(64),A(65),A(66),A(67),A(68),A(69),A(70), +A(71),A(72),A(73),A(74),A(75),A(76),A(77),A(78),A(79),A(80), +A(81),A(82),A(83),A(84),A(85),A(86),A(87),A(88),A(89),A(90), +A(91),A(92),A(93),A(94),A(95),A(96),A(97),A(98),A(99),A(100), +A(101),A(102),A(103),A(104),A(105),A(106),A(107),A(108),A(109), +A(110),A(111),A(112),A(113),A(114),A(115),A(116),A(117),A(118), +A(119),A(120),A(121),A(122),A(123),A(124),A(125),A(126),A(127), +A(128),A(129),A(130),A(131),A(132),A(133),A(134),A(135),A(136), +A(137),A(138),A(139),A(140),A(141),A(142),A(143),A(144),A(145), +A(146),A(147),A(148),A(149),A(150),A(151),A(152),A(153),A(154), +A(155),A(156),A(157),A(158),A(159),A(160),A(161),A(162),A(163), +A(164),A(165),A(166),A(167),A(168),A(169),A(170),A(171),A(172), +A(173),A(174),A(175),A(176),A(177),A(178),A(179),A(180),A(181), +A(182),A(183),A(184),A(185),A(186),A(187),A(188),A(189),A(190), +A(191),A(192),A(193),A(194),A(195),A(196),A(197),A(198),A(199), +A(200),A(201),A(202),A(203),A(204),A(205),A(206),A(207),A(208), +A(209),A(210),A(211),A(212),A(213),A(214),A(215),A(216),A(217), +A(218),A(219),A(220),A(221),A(222),A(223),A(224),A(225),A(226), +A(227),A(228),A(229),A(230),A(231),A(232),A(233),A(234),A(235), +A(236),A(237),A(238),A(239),A(240),A(241),A(242),A(243),A(244), +A(245),A(246),A(247),A(248),A(249),A(250),A(251),A(252),A(253), +A(254),A(255) +#undef A +}; + +CAMLexport value caml_atom(tag_t tag) { + return Val_hp(&atoms[tag]); +} + +void caml_init_major_heap (asize_t size) { +} + + +/* Verify heap invariants. + + Verification happens just after the heap is cycled during STW, so + everything should be unmarked. If something reachable marked after + cycling the heap, it means that garbage was reachable beforehand. +*/ +struct heap_verify_state { + value* stack; + int stack_len; + int sp; + intnat objs; + struct addrmap seen; +}; + +struct heap_verify_state* caml_verify_begin() +{ + struct heap_verify_state init = {0, 0, 0, 0, ADDRMAP_INIT}; + struct heap_verify_state* st = caml_stat_alloc(sizeof init); + *st = init; + return st; +} + +void verify_push(void* st_v, value v, value* p) +{ + struct heap_verify_state* st = st_v; + if (!Is_block(v)) return; + + if( Is_young(v) ) { + struct domain* domain; + caml_gc_log("minor in heap: %p, hd_val: %lx, p: %p", (value*)v, Hd_val(v), p); + domain = caml_owner_of_young_block(v); + caml_gc_log("owner: %d, young_start: %p, young_end: %p, young_ptr: %p, young_limit: %p", domain->state->id, domain->state->young_start, domain->state->young_end, domain->state->young_ptr, (void *)domain->state->young_limit); + } + + if (st->sp == st->stack_len) { + st->stack_len = st->stack_len * 2 + 100; + st->stack = caml_stat_resize(st->stack, + sizeof(value*) * st->stack_len); + } + st->stack[st->sp++] = v; +} + +void caml_verify_root(void* state, value v, value* p) +{ + verify_push(state, v, p); +} + +static void verify_object(struct heap_verify_state* st, value v) { + intnat* entry; + if (!Is_block(v)) return; + + Assert (!Is_young(v)); + Assert (Hd_val(v)); + + if (Tag_val(v) == Infix_tag) { + v -= Infix_offset_val(v); + Assert(Tag_val(v) == Closure_tag); + } + + entry = caml_addrmap_insert_pos(&st->seen, v); + if (*entry != ADDRMAP_NOT_PRESENT) return; + *entry = 1; + + if (Has_status_hd(Hd_val(v), NOT_MARKABLE)) return; + st->objs++; + + Assert(Has_status_hd(Hd_val(v), global.UNMARKED)); + + if (Tag_val(v) == Cont_tag) { + struct stack_info* stk = Ptr_val(Op_val(v)[0]); + if (stk != NULL) + caml_scan_stack(verify_push, st, stk, 0); + } else if (Tag_val(v) < No_scan_tag) { + int i = 0; + if (Tag_val(v) == Closure_tag) { + i = Start_env_closinfo(Closinfo_val(v)); + } + for (; i < Wosize_val(v); i++) { + value f = Op_val(v)[i]; + if (Is_young(v) && Is_young(f)) { + Assert(caml_owner_of_young_block(v) == + caml_owner_of_young_block(f)); + } + if (Is_block(f)) verify_push(st, f, Op_val(v)+i); + } + } +} + +void caml_verify_heap(struct heap_verify_state* st) { + while (st->sp) verify_object(st, st->stack[--st->sp]); + + caml_addrmap_clear(&st->seen); + caml_stat_free(st->stack); + caml_stat_free(st); +} + + +struct mem_stats { + /* unit is words */ + uintnat alloced; + uintnat live; + uintnat free; + uintnat overhead; + + uintnat live_blocks; +}; + +static void verify_pool(pool* a, sizeclass sz, struct mem_stats* s) { + value* v; + for (v = a->next_obj; v; v = (value*)v[1]) { + Assert(*v == 0); + } + + { + value* p = (value*)((char*)a + POOL_HEADER_SZ); + value* end = (value*)a + POOL_WSIZE; + mlsize_t wh = wsize_sizeclass[sz]; + s->overhead += Wsize_bsize(POOL_HEADER_SZ); + + while (p + wh <= end) { + header_t hd = (header_t)*p; + Assert(hd == 0 || !Has_status_hd(hd, global.GARBAGE)); + if (hd) { + s->live += Whsize_hd(hd); + s->overhead += wh - Whsize_hd(hd); + s->live_blocks++; + } else { + s->free += wh; + } + p += wh; + } + Assert(end - p == wastage_sizeclass[sz]); + s->overhead += end - p; + s->alloced += POOL_WSIZE; + } +} + +static void verify_large(large_alloc* a, struct mem_stats* s) { + for (; a; a = a->next) { + header_t hd = *(header_t*)((char*)a + LARGE_ALLOC_HEADER_SZ); + Assert (!Has_status_hd(hd, global.GARBAGE)); + s->alloced += Wsize_bsize(LARGE_ALLOC_HEADER_SZ) + Whsize_hd(hd); + s->overhead += Wsize_bsize(LARGE_ALLOC_HEADER_SZ); + s->live_blocks++; + } +} + +static void verify_swept (struct caml_heap_state* local) { + int i; + struct mem_stats pool_stats = {}, large_stats = {}; + + /* sweeping should be done by this point */ + Assert(local->next_to_sweep == NUM_SIZECLASSES); + for (i = 0; i < NUM_SIZECLASSES; i++) { + pool* p; + Assert(local->unswept_avail_pools[i] == 0 && + local->unswept_full_pools[i] == 0); + for (p = local->avail_pools[i]; p; p = p->next) + verify_pool(p, i, &pool_stats); + for (p = local->full_pools[i]; p; p = p->next) { + Assert(p->next_obj == 0); + verify_pool(p, i, &pool_stats); + } + } + caml_gc_log("Pooled memory: %lu alloced, %lu free, %lu fragmentation", + pool_stats.alloced, pool_stats.free, pool_stats.overhead); + + verify_large(local->swept_large, &large_stats); + Assert(local->unswept_large == 0); + caml_gc_log("Large memory: %lu alloced, %lu free, %lu fragmentation", + large_stats.alloced, large_stats.free, large_stats.overhead); + + /* Check stats are being computed correctly */ + Assert(local->stats.pool_words == pool_stats.alloced); + Assert(local->stats.pool_live_words == pool_stats.live); + Assert(local->stats.pool_live_blocks == pool_stats.live_blocks); + Assert(local->stats.pool_frag_words == pool_stats.overhead); + Assert(local->stats.pool_words - + (local->stats.pool_live_words + local->stats.pool_frag_words) + == pool_stats.free); + Assert(local->stats.large_words == large_stats.alloced); + Assert(local->stats.large_blocks == large_stats.live_blocks); +} + +void caml_cycle_heap_stw() { + struct global_heap_state oldg = global; + struct global_heap_state newg; + newg.UNMARKED = oldg.MARKED; + newg.GARBAGE = oldg.UNMARKED; + newg.MARKED = oldg.GARBAGE; /* should be empty because garbage was swept */ + global = newg; +} + +void caml_cycle_heap(struct caml_heap_state* local) { + int i, received_p = 0, received_l = 0; + + caml_gc_log("Cycling heap [%02d]", local->owner->state->id); + for (i = 0; i < NUM_SIZECLASSES; i++) { + Assert(local->unswept_avail_pools[i] == 0); + local->unswept_avail_pools[i] = local->avail_pools[i]; + local->avail_pools[i] = 0; + Assert(local->unswept_full_pools[i] == 0); + local->unswept_full_pools[i] = local->full_pools[i]; + local->full_pools[i] = 0; + } + Assert(local->unswept_large == 0); + local->unswept_large = local->swept_large; + local->swept_large = 0; + + caml_plat_lock(&pool_freelist.lock); + for (i = 0; i < NUM_SIZECLASSES; i++) { + received_p += move_all_pools(&pool_freelist.global_avail_pools[i], + &local->unswept_avail_pools[i], + local->owner); + received_p += move_all_pools(&pool_freelist.global_full_pools[i], + &local->unswept_full_pools[i], + local->owner); + } + while (pool_freelist.global_large) { + large_alloc* a = pool_freelist.global_large; + pool_freelist.global_large = a->next; + a->owner = local->owner; + a->next = local->unswept_large; + local->unswept_large = a; + received_l++; + } + if (received_p || received_l) { + caml_accum_heap_stats(&local->stats, &pool_freelist.stats); + memset(&pool_freelist.stats, 0, sizeof(pool_freelist.stats)); + } + caml_plat_unlock(&pool_freelist.lock); + if (received_p || received_l) + caml_gc_log("Received %d new pools, %d new large allocs", received_p, received_l); + + local->next_to_sweep = 0; +} diff --git a/runtime/signals.c b/runtime/signals.c index 57bb3fc712..f119415b5e 100644 --- a/runtime/signals.c +++ b/runtime/signals.c @@ -19,6 +19,7 @@ #include <signal.h> #include <errno.h> +#include <string.h> #include "caml/alloc.h" #include "caml/callback.h" #include "caml/config.h" @@ -28,10 +29,7 @@ #include "caml/mlvalues.h" #include "caml/roots.h" #include "caml/signals.h" -#include "caml/signals_machdep.h" #include "caml/sys.h" -#include "caml/memprof.h" -#include "caml/finalise.h" #if defined(NATIVE_CODE) && defined(WITH_SPACETIME) #include "caml/spacetime.h" @@ -41,177 +39,107 @@ #define NSIG 64 #endif -CAMLexport int volatile caml_something_to_do = 0; - /* The set of pending signals (received but not yet processed) */ -static intnat volatile signals_are_pending = 0; +CAMLexport intnat volatile caml_signals_are_pending = 0; CAMLexport intnat volatile caml_pending_signals[NSIG]; -#ifdef POSIX_SIGNALS -/* This wrapper makes [sigprocmask] compatible with - [pthread_sigmask]. Indeed, the latter returns the error code while - the former sets [errno]. - */ -static int sigprocmask_wrapper(int how, const sigset_t *set, sigset_t *oldset) { - if(sigprocmask(how, set, oldset) != 0) return errno; - else return 0; -} - -CAMLexport int (*caml_sigmask_hook)(int, const sigset_t *, sigset_t *) - = sigprocmask_wrapper; -#endif - /* Execute all pending signals */ -value caml_process_pending_signals_exn(void) +static void caml_execute_signal(int signal_number); +void caml_process_pending_signals(void) { int i; - int really_pending; -#ifdef POSIX_SIGNALS - sigset_t set; -#endif - - if(!signals_are_pending) - return Val_unit; - signals_are_pending = 0; - - /* Check that there is indeed a pending signal before issuing the - syscall in [caml_sigmask_hook]. */ - really_pending = 0; - for (i = 0; i < NSIG; i++) - if (caml_pending_signals[i]) { - really_pending = 1; - break; - } - if(!really_pending) - return Val_unit; - -#ifdef POSIX_SIGNALS - caml_sigmask_hook(/* dummy */ SIG_BLOCK, NULL, &set); -#endif - for (i = 0; i < NSIG; i++) { - if (!caml_pending_signals[i]) - continue; -#ifdef POSIX_SIGNALS - if(sigismember(&set, i)) - continue; -#endif - caml_pending_signals[i] = 0; - { - value exn = caml_execute_signal_exn(i, 0); - if (Is_exception_result(exn)) return exn; + /* this function preserves errno (PR#5982) */ + int saved_errno = errno; + + if (caml_signals_are_pending) { + caml_signals_are_pending = 0; + for (i = 0; i < NSIG; i++) { + if (caml_pending_signals[i]) { + caml_pending_signals[i] = 0; + caml_execute_signal(i); + } } } - return Val_unit; -} - -CAMLno_tsan /* When called from [caml_record_signal], these memory - accesses may not be synchronized. */ -void caml_set_action_pending(void) -{ - caml_something_to_do = 1; - - /* When this function is called without [caml_c_call] (e.g., in - [caml_modify]), this is only moderately effective on ports that cache - [Caml_state->young_limit] in a register, so it may take a while before the - register is reloaded from [Caml_state->young_limit]. */ - Caml_state->young_limit = Caml_state->young_alloc_end; + errno = saved_errno; } /* Record the delivery of a signal, and arrange for it to be processed as soon as possible: - - via caml_something_to_do, processed in - caml_process_pending_actions_exn. - - by playing with the allocation limit, processed in - caml_garbage_collection and caml_alloc_small_dispatch. + - in bytecode: via caml_something_to_do, processed in caml_process_event + - in native-code: by playing with the allocation limit, processed + in caml_garbage_collection */ -CAMLno_tsan void caml_record_signal(int signal_number) +void caml_record_signal(int signal_number) { caml_pending_signals[signal_number] = 1; - signals_are_pending = 1; - caml_set_action_pending(); + caml_signals_are_pending = 1; + caml_interrupt_self(); } -/* Management of blocking sections. */ - -static intnat volatile caml_async_signal_mode = 0; - -static void caml_enter_blocking_section_default(void) -{ - CAMLassert (caml_async_signal_mode == 0); - caml_async_signal_mode = 1; -} - -static void caml_leave_blocking_section_default(void) +int caml_init_signal_stack() { - CAMLassert (caml_async_signal_mode == 1); - caml_async_signal_mode = 0; -} +#ifdef POSIX_SIGNALS + stack_t stk; + stk.ss_flags = 0; + stk.ss_size = SIGSTKSZ; + stk.ss_sp = caml_stat_alloc_noexc(stk.ss_size); + if(stk.ss_sp == NULL) { + return -1; + } + if (sigaltstack(&stk, NULL) < 0) { + caml_stat_free(stk.ss_sp); + return -1; + } -static int caml_try_leave_blocking_section_default(void) -{ - intnat res; - Read_and_clear(res, caml_async_signal_mode); - return res; + /* gprof installs a signal handler for SIGPROF. + Make it run on the alternate signal stack, to prevent segfaults. */ + { + struct sigaction act; + sigaction(SIGPROF, NULL, &act); + if ((act.sa_flags & SA_SIGINFO) || + (act.sa_handler != SIG_IGN && act.sa_handler != SIG_DFL)) { + /* found a handler */ + if ((act.sa_flags & SA_ONSTACK) == 0) { + act.sa_flags |= SA_ONSTACK; + sigaction(SIGPROF, &act, NULL); + } + } + } +#endif + return 0; } -CAMLexport void (*caml_enter_blocking_section_hook)(void) = - caml_enter_blocking_section_default; -CAMLexport void (*caml_leave_blocking_section_hook)(void) = - caml_leave_blocking_section_default; -CAMLexport int (*caml_try_leave_blocking_section_hook)(void) = - caml_try_leave_blocking_section_default; - -CAMLno_tsan /* The read of [caml_something_to_do] is not synchronized. */ -CAMLexport void caml_enter_blocking_section(void) +void caml_free_signal_stack() { - while (1){ - /* Process all pending signals now */ - caml_raise_if_exception(caml_process_pending_signals_exn()); - caml_enter_blocking_section_hook (); - /* Check again for pending signals. - If none, done; otherwise, try again */ - if (! signals_are_pending) break; - caml_leave_blocking_section_hook (); +#ifdef POSIX_SIGNALS + stack_t stk, disable = {0}; + disable.ss_flags = SS_DISABLE; + /* POSIX says ss_size is ignored when SS_DISABLE is set, + but OSX/Darwin fails if the size isn't set. */ + disable.ss_size = SIGSTKSZ; + if (sigaltstack(&disable, &stk) < 0) { + caml_fatal_error_arg("Failed to reset signal stack: %s", strerror(errno)); } + caml_stat_free(stk.ss_sp); +#endif } -CAMLexport void caml_leave_blocking_section(void) -{ - int saved_errno; - /* Save the value of errno (PR#5982). */ - saved_errno = errno; - caml_leave_blocking_section_hook (); - - /* Some other thread may have switched - [signals_are_pending] to 0 even though there are still - pending signals (masked in the other thread). To handle this - case, we force re-examination of all signals by setting it back - to 1. +/* Execute a signal handler immediately */ - Another case where this is necessary (even in a single threaded - setting) is when the blocking section unmasks a pending signal: - If the signal is pending and masked but has already been - examined by [caml_process_pending_signals_exn], then - [signals_are_pending] is 0 but the signal needs to be - handled at this point. */ - signals_are_pending = 1; - caml_raise_if_exception(caml_process_pending_signals_exn()); +static caml_root caml_signal_handlers; - errno = saved_errno; +void caml_init_signal_handling() { + caml_signal_handlers = caml_create_root(caml_alloc_shr(NSIG, 0)); } -/* Execute a signal handler immediately */ - -static value caml_signal_handlers = 0; - -value caml_execute_signal_exn(int signal_number, int in_signal_handler) +static void caml_execute_signal(int signal_number) { - value res; - value handler; -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) + CAMLparam0 (); + CAMLlocal2 (res, handler); +#if 0 && defined(NATIVE_CODE) && defined(WITH_SPACETIME) void* saved_spacetime_trie_node_ptr; #endif #ifdef POSIX_SIGNALS @@ -220,9 +148,9 @@ value caml_execute_signal_exn(int signal_number, int in_signal_handler) the original signal mask */ sigemptyset(&nsigs); sigaddset(&nsigs, signal_number); - caml_sigmask_hook(SIG_BLOCK, &nsigs, &sigs); + sigprocmask(SIG_BLOCK, &nsigs, &sigs); #endif -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) +#if 0 && defined(NATIVE_CODE) && defined(WITH_SPACETIME) /* We record the signal handler's execution separately, in the same trie used for finalisers. */ saved_spacetime_trie_node_ptr @@ -230,128 +158,34 @@ value caml_execute_signal_exn(int signal_number, int in_signal_handler) caml_spacetime_trie_node_ptr = caml_spacetime_finaliser_trie_root; #endif -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) +#if 0 && defined(NATIVE_CODE) && defined(WITH_SPACETIME) /* Handled action may have no associated handler, which we interpret as meaning the signal should be handled by a call to exit. This is used to allow spacetime profiles to be completed on interrupt */ if (caml_signal_handlers == 0) { res = caml_sys_exit(Val_int(2)); } else { - handler = Field(caml_signal_handlers, signal_number); + caml_read_field(caml_read_root(caml_signal_handlers), signal_number, &handler); if (!Is_block(handler)) { res = caml_sys_exit(Val_int(2)); } else { #else - handler = Field(caml_signal_handlers, signal_number); + caml_read_field(caml_read_root(caml_signal_handlers), signal_number, &handler); #endif - res = caml_callback_exn( - handler, - Val_int(caml_rev_convert_signal_number(signal_number))); -#if defined(NATIVE_CODE) && defined(WITH_SPACETIME) + res = caml_callback_exn( + handler, + Val_int(caml_rev_convert_signal_number(signal_number))); +#if 0 && defined(NATIVE_CODE) && defined(WITH_SPACETIME) } } caml_spacetime_trie_node_ptr = saved_spacetime_trie_node_ptr; #endif #ifdef POSIX_SIGNALS - if (! in_signal_handler) { - /* Restore the original signal mask */ - caml_sigmask_hook(SIG_SETMASK, &sigs, NULL); - } else if (Is_exception_result(res)) { - /* Restore the original signal mask and unblock the signal itself */ - sigdelset(&sigs, signal_number); - caml_sigmask_hook(SIG_SETMASK, &sigs, NULL); - } + /* Restore the original signal mask */ + sigprocmask(SIG_SETMASK, &sigs, NULL); #endif - return res; -} - -void caml_update_young_limit (void) -{ - /* The minor heap grows downwards. The first trigger is the largest one. */ - Caml_state->young_limit = - caml_memprof_young_trigger < Caml_state->young_trigger ? - Caml_state->young_trigger : caml_memprof_young_trigger; - - if(caml_something_to_do) - Caml_state->young_limit = Caml_state->young_alloc_end; -} - -/* Arrange for a garbage collection to be performed as soon as possible */ - -void caml_request_major_slice (void) -{ - Caml_state->requested_major_slice = 1; - caml_set_action_pending(); -} - -void caml_request_minor_gc (void) -{ - Caml_state->requested_minor_gc = 1; - caml_set_action_pending(); -} - -value caml_do_pending_actions_exn(void) -{ - value exn; - - caml_something_to_do = 0; - - // Do any pending minor collection or major slice - caml_check_urgent_gc(Val_unit); - - caml_update_young_limit(); - - // Call signal handlers first - exn = caml_process_pending_signals_exn(); - if (Is_exception_result(exn)) goto exception; - - // Call memprof callbacks - exn = caml_memprof_handle_postponed_exn(); - if (Is_exception_result(exn)) goto exception; - - // Call finalisers - exn = caml_final_do_calls_exn(); - if (Is_exception_result(exn)) goto exception; - - return Val_unit; - -exception: - /* If an exception is raised during an asynchronous callback, then - it might be the case that we did not run all the callbacks we - needed. Therefore, we set [caml_something_to_do] again in order - to force reexamination of callbacks. */ - caml_set_action_pending(); - return exn; -} - -CAMLno_tsan /* The access to [caml_something_to_do] is not synchronized. */ -Caml_inline value process_pending_actions_with_root_exn(value extra_root) -{ - if (caml_something_to_do) { - CAMLparam1(extra_root); - value exn = caml_do_pending_actions_exn(); - if (Is_exception_result(exn)) - CAMLreturn(exn); - CAMLdrop; - } - return extra_root; -} - -value caml_process_pending_actions_with_root(value extra_root) -{ - value res = process_pending_actions_with_root_exn(extra_root); - return caml_raise_if_exception(res); -} - -CAMLexport value caml_process_pending_actions_exn(void) -{ - return process_pending_actions_with_root_exn(Val_unit); -} - -CAMLexport void caml_process_pending_actions(void) -{ - value exn = process_pending_actions_with_root_exn(Val_unit); - caml_raise_if_exception(exn); + if (Is_exception_result(res)) caml_raise(Extract_exception(res)); + CAMLreturn0; } /* OS-independent numbering of signals */ @@ -469,7 +303,7 @@ CAMLexport int caml_rev_convert_signal_number(int signo) CAMLprim value caml_install_signal_handler(value signal_number, value action) { CAMLparam2 (signal_number, action); - CAMLlocal1 (res); + CAMLlocal2 (res, handler); int sig, act, oldact; sig = caml_convert_signal_number(Int_val(signal_number)); @@ -495,34 +329,15 @@ CAMLprim value caml_install_signal_handler(value signal_number, value action) res = Val_int(1); break; case 2: /* was Signal_handle */ - #if defined(NATIVE_CODE) && defined(WITH_SPACETIME) - /* Handled action may have no associated handler - which we treat as Signal_default */ - if (caml_signal_handlers == 0) { - res = Val_int(0); - } else { - if (!Is_block(Field(caml_signal_handlers, sig))) { - res = Val_int(0); - } else { - res = caml_alloc_small (1, 0); - Field(res, 0) = Field(caml_signal_handlers, sig); - } - } - #else - res = caml_alloc_small (1, 0); - Field(res, 0) = Field(caml_signal_handlers, sig); - #endif + caml_read_field(caml_read_root(caml_signal_handlers), sig, &handler); + res = caml_alloc_1 (0, handler); break; default: /* error in caml_set_signal_action */ caml_sys_error(NO_ARG); } if (Is_block(action)) { - if (caml_signal_handlers == 0) { - caml_signal_handlers = caml_alloc(NSIG, 0); - caml_register_global_root(&caml_signal_handlers); - } - caml_modify(&Field(caml_signal_handlers, sig), Field(action, 0)); + caml_modify_field(caml_read_root(caml_signal_handlers), sig, Field(action, 0)); } - caml_raise_if_exception(caml_process_pending_signals_exn()); + caml_process_pending_signals(); CAMLreturn (res); } diff --git a/runtime/signals_byt.c b/runtime/signals_byt.c index 040de03c57..103cecf8f8 100644 --- a/runtime/signals_byt.c +++ b/runtime/signals_byt.c @@ -21,11 +21,8 @@ #include <errno.h> #include "caml/config.h" #include "caml/memory.h" -#include "caml/fail.h" -#include "caml/finalise.h" #include "caml/osdeps.h" #include "caml/signals.h" -#include "caml/signals_machdep.h" #ifndef NSIG #define NSIG 64 @@ -37,6 +34,22 @@ extern sighandler caml_win32_signal(int sig, sighandler action); #define signal(sig,act) caml_win32_signal(sig,act) #endif +CAMLexport int volatile caml_something_to_do = 0; +CAMLexport void (* volatile caml_async_action_hook)(void) = NULL; + +void caml_process_event(void) +{ + void (*async_action)(void); + + caml_check_urgent_gc (Val_unit); + caml_process_pending_signals(); + async_action = caml_async_action_hook; + if (async_action != NULL) { + caml_async_action_hook = NULL; + (*async_action)(); + } +} + static void handle_signal(int signal_number) { int saved_errno; @@ -46,12 +59,7 @@ static void handle_signal(int signal_number) signal(signal_number, handle_signal); #endif if (signal_number < 0 || signal_number >= NSIG) return; - if (caml_try_leave_blocking_section_hook()) { - caml_raise_if_exception(caml_execute_signal_exn(signal_number, 1)); - caml_enter_blocking_section_hook(); - }else{ - caml_record_signal(signal_number); - } + caml_record_signal(signal_number); errno = saved_errno; } @@ -71,7 +79,7 @@ int caml_set_signal_action(int signo, int action) #ifdef POSIX_SIGNALS sigact.sa_handler = act; sigemptyset(&sigact.sa_mask); - sigact.sa_flags = 0; + sigact.sa_flags = SA_ONSTACK; if (sigaction(signo, &sigact, &oldsigact) == -1) return -1; oldact = oldsigact.sa_handler; #else @@ -85,5 +93,3 @@ int caml_set_signal_action(int signo, int action) else return 0; } - -void caml_setup_stack_overflow_detection(void) {} diff --git a/runtime/signals_nat.c b/runtime/signals_nat.c index 9ee2b2647f..9ef278e47b 100644 --- a/runtime/signals_nat.c +++ b/runtime/signals_nat.c @@ -27,16 +27,13 @@ #include <errno.h> #include <stdio.h> #include "caml/codefrag.h" +#include "caml/domain.h" #include "caml/fail.h" #include "caml/memory.h" #include "caml/osdeps.h" #include "caml/signals.h" -#include "caml/signals_machdep.h" -#include "signals_osdep.h" #include "caml/stack.h" #include "caml/spacetime.h" -#include "caml/memprof.h" -#include "caml/finalise.h" #ifndef NSIG #define NSIG 64 @@ -47,9 +44,9 @@ typedef void (*signal_handler)(int signo); #ifdef _WIN32 extern signal_handler caml_win32_signal(int sig, signal_handler action); #define signal(sig,act) caml_win32_signal(sig,act) -extern void caml_win32_overflow_detection(); #endif + /* This routine is the common entry point for garbage collection and signal handling. It can trigger a callback to OCaml code. With system threads, this callback can cause a context switch. @@ -59,72 +56,34 @@ extern void caml_win32_overflow_detection(); Only generated assembly code can call [caml_garbage_collection], via the caml_call_gc assembly stubs. */ -void caml_garbage_collection(void) +void caml_garbage_collection() { - frame_descr* d; - intnat allocsz = 0, i, nallocs; - unsigned char* alloc_len; - - { /* Find the frame descriptor for the current allocation */ - uintnat h = Hash_retaddr(Caml_state->last_return_address); - while (1) { - d = caml_frame_descriptors[h]; - if (d->retaddr == Caml_state->last_return_address) break; - h = (h + 1) & caml_frame_descriptors_mask; - } - /* Must be an allocation frame */ - CAMLassert(d && d->frame_size != 0xFFFF && (d->frame_size & 2)); - } + caml_handle_gc_interrupt(); - /* Compute the total allocation size at this point, - including allocations combined by Comballoc */ - alloc_len = (unsigned char*)(&d->live_ofs[d->num_live]); - nallocs = *alloc_len++; - for (i = 0; i < nallocs; i++) { - allocsz += Whsize_wosize(Wosize_encoded_alloc_len(alloc_len[i])); +#ifdef WITH_SPACETIME + if (caml_young_ptr == caml_young_alloc_end) { + caml_spacetime_automatic_snapshot(); } - /* We have computed whsize (including header), but need wosize (without) */ - allocsz -= 1; +#endif - caml_alloc_small_dispatch(allocsz, CAML_DO_TRACK | CAML_FROM_CAML, - nallocs, alloc_len); + caml_process_pending_signals(); } -DECLARE_SIGNAL_HANDLER(handle_signal) +static void handle_signal(int sig, siginfo_t* info, void* context) { int saved_errno; /* Save the value of errno (PR#5982). */ saved_errno = errno; -#if !defined(POSIX_SIGNALS) && !defined(BSD_SIGNALS) - signal(sig, handle_signal); -#endif if (sig < 0 || sig >= NSIG) return; - if (caml_try_leave_blocking_section_hook ()) { - caml_raise_if_exception(caml_execute_signal_exn(sig, 1)); - caml_enter_blocking_section_hook(); - } else { - caml_record_signal(sig); - /* Some ports cache [Caml_state->young_limit] in a register. - Use the signal context to modify that register too, but only if - we are inside OCaml code (not inside C code). */ -#if defined(CONTEXT_PC) && defined(CONTEXT_YOUNG_LIMIT) - if (caml_find_code_fragment_by_pc((char *) CONTEXT_PC) != NULL) - CONTEXT_YOUNG_LIMIT = (context_reg) Caml_state->young_limit; -#endif - } + caml_record_signal(sig); errno = saved_errno; } int caml_set_signal_action(int signo, int action) { signal_handler oldact; -#ifdef POSIX_SIGNALS struct sigaction sigact, oldsigact; -#else - signal_handler act; -#endif -#ifdef POSIX_SIGNALS switch(action) { case 0: sigact.sa_handler = SIG_DFL; @@ -135,21 +94,16 @@ int caml_set_signal_action(int signo, int action) sigact.sa_flags = 0; break; default: - SET_SIGACT(sigact, handle_signal); + sigact.sa_sigaction = handle_signal; + sigact.sa_flags = SA_ONSTACK | SA_SIGINFO; +#if defined(TARGET_amd64) && defined(SYS_macosx) + sigact.sa_flags |= SA_64REGSET; +#endif break; } sigemptyset(&sigact.sa_mask); if (sigaction(signo, &sigact, &oldsigact) == -1) return -1; oldact = oldsigact.sa_handler; -#else - switch(action) { - case 0: act = SIG_DFL; break; - case 1: act = SIG_IGN; break; - default: act = handle_signal; break; - } - oldact = signal(signo, act); - if (oldact == SIG_ERR) return -1; -#endif if (oldact == (signal_handler) handle_signal) return 2; else if (oldact == SIG_IGN) @@ -162,90 +116,12 @@ int caml_set_signal_action(int signo, int action) #if defined(TARGET_power) \ || defined(TARGET_s390x) +#error "Architecture requires a bounds-check trap handler" DECLARE_SIGNAL_HANDLER(trap_handler) { -#if defined(SYS_rhapsody) - /* Unblock SIGTRAP */ - { sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGTRAP); - caml_sigmask_hook(SIG_UNBLOCK, &mask, NULL); - } -#endif - Caml_state->exception_pointer = (char *) CONTEXT_EXCEPTION_POINTER; - Caml_state->young_ptr = (value *) CONTEXT_YOUNG_PTR; - Caml_state->bottom_of_stack = (char *) CONTEXT_SP; - Caml_state->last_return_address = (uintnat) CONTEXT_PC; - caml_array_bound_error(); -} -#endif - -/* Machine- and OS-dependent handling of stack overflow */ - -#ifdef HAS_STACK_OVERFLOW_DETECTION -#ifndef CONTEXT_SP -#error "CONTEXT_SP is required if HAS_STACK_OVERFLOW_DETECTION is defined" -#endif - -static char sig_alt_stack[SIGSTKSZ]; - -/* Code compiled with ocamlopt never accesses more than - EXTRA_STACK bytes below the stack pointer. */ -#define EXTRA_STACK 256 - -#ifdef RETURN_AFTER_STACK_OVERFLOW -extern void caml_stack_overflow(caml_domain_state*); -#endif - -/* Address sanitizer is confused when running the stack overflow - handler in an alternate stack. We deactivate it for all the - functions used by the stack overflow handler. */ -CAMLno_asan -DECLARE_SIGNAL_HANDLER(segv_handler) -{ - struct sigaction act; - char * fault_addr; - - /* Sanity checks: - - faulting address is word-aligned - - faulting address is on the stack, or within EXTRA_STACK of it - - we are in OCaml code */ - fault_addr = CONTEXT_FAULTING_ADDRESS; - if (((uintnat) fault_addr & (sizeof(intnat) - 1)) == 0 - && fault_addr < Caml_state->top_of_stack - && (uintnat)fault_addr >= CONTEXT_SP - EXTRA_STACK -#ifdef CONTEXT_PC - && caml_find_code_fragment_by_pc((char *) CONTEXT_PC) != NULL -#endif - ) { -#ifdef RETURN_AFTER_STACK_OVERFLOW - /* Tweak the PC part of the context so that on return from this - handler, we jump to the asm function [caml_stack_overflow] - (from $ARCH.S). */ -#ifdef CONTEXT_PC - CONTEXT_C_ARG_1 = (context_reg) Caml_state; - CONTEXT_PC = (context_reg) &caml_stack_overflow; -#else -#error "CONTEXT_PC must be defined if RETURN_AFTER_STACK_OVERFLOW is" -#endif -#else - /* Raise a Stack_overflow exception straight from this signal handler */ -#if defined(CONTEXT_YOUNG_PTR) && defined(CONTEXT_EXCEPTION_POINTER) - Caml_state->exception_pointer == (char *) CONTEXT_EXCEPTION_POINTER; - Caml_state->young_ptr = (value *) CONTEXT_YOUNG_PTR; -#endif - caml_raise_stack_overflow(); -#endif - } else { - /* Otherwise, deactivate our exception handler and return, - causing fatal signal to be generated at point of error. */ - act.sa_handler = SIG_DFL; - act.sa_flags = 0; - sigemptyset(&act.sa_mask); - sigaction(SIGSEGV, &act, NULL); - } + /* TODO: raise a real exception here */ + caml_fatal_error ("bounds check failed"); } - #endif /* Initialization of signal stuff */ @@ -257,10 +133,8 @@ void caml_init_signals(void) #if defined(TARGET_power) { struct sigaction act; sigemptyset(&act.sa_mask); - SET_SIGACT(act, trap_handler); -#if !defined(SYS_rhapsody) - act.sa_flags |= SA_NODEFER; -#endif + act.sa_sigaction = trap_handler; + act.sa_flags = SA_ONSTACK | SA_SIGINFO; sigaction(SIGTRAP, &act, NULL); } #endif @@ -268,34 +142,9 @@ void caml_init_signals(void) #if defined(TARGET_s390x) { struct sigaction act; sigemptyset(&act.sa_mask); - SET_SIGACT(act, trap_handler); + act.sa_sigaction = trap_handler; + act.sa_flags = SA_ONSTACK | SA_SIGINFO; sigaction(SIGFPE, &act, NULL); } #endif - -#ifdef HAS_STACK_OVERFLOW_DETECTION - { - stack_t stk; - struct sigaction act; - stk.ss_sp = sig_alt_stack; - stk.ss_size = SIGSTKSZ; - stk.ss_flags = 0; - SET_SIGACT(act, segv_handler); - act.sa_flags |= SA_ONSTACK | SA_NODEFER; - sigemptyset(&act.sa_mask); - if (sigaltstack(&stk, NULL) == 0) { sigaction(SIGSEGV, &act, NULL); } - } -#endif -} - -void caml_setup_stack_overflow_detection(void) -{ -#ifdef HAS_STACK_OVERFLOW_DETECTION - stack_t stk; - stk.ss_sp = malloc(SIGSTKSZ); - stk.ss_size = SIGSTKSZ; - stk.ss_flags = 0; - if (stk.ss_sp) - sigaltstack(&stk, NULL); -#endif } diff --git a/runtime/signals_osdep.h b/runtime/signals_osdep.h deleted file mode 100644 index 6c30232726..0000000000 --- a/runtime/signals_osdep.h +++ /dev/null @@ -1,427 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 2004 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -/* Processor- and OS-dependent signal interface */ - -/****************** AMD64, Linux */ - -#if defined(TARGET_amd64) && defined (SYS_linux) - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, ucontext_t * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \ - sigact.sa_flags = SA_SIGINFO - - typedef greg_t context_reg; - #define CONTEXT_C_ARG_1 (context->uc_mcontext.gregs[REG_RDI]) - #define CONTEXT_PC (context->uc_mcontext.gregs[REG_RIP]) - #define CONTEXT_SP (context->uc_mcontext.gregs[REG_RSP]) - #define CONTEXT_YOUNG_PTR (context->uc_mcontext.gregs[REG_R15]) - #define CONTEXT_FAULTING_ADDRESS ((char *)context->uc_mcontext.gregs[REG_CR2]) - -/****************** AMD64, MacOSX */ - -#elif defined(TARGET_amd64) && defined (SYS_macosx) - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, void * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (name); \ - sigact.sa_flags = SA_SIGINFO | SA_64REGSET - - #include <sys/ucontext.h> - #include <AvailabilityMacros.h> - - #if !defined(MAC_OS_X_VERSION_10_5) \ - || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 - #define CONTEXT_REG(r) r - #else - #define CONTEXT_REG(r) __##r - #endif - - typedef unsigned long long context_reg; - #define CONTEXT_STATE (((ucontext_t *)context)->uc_mcontext->CONTEXT_REG(ss)) - #define CONTEXT_C_ARG_1 (CONTEXT_STATE.CONTEXT_REG(rdi)) - #define CONTEXT_PC (CONTEXT_STATE.CONTEXT_REG(rip)) - #define CONTEXT_YOUNG_PTR (CONTEXT_STATE.CONTEXT_REG(r15)) - #define CONTEXT_SP (CONTEXT_STATE.CONTEXT_REG(rsp)) - #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr) - - #define RETURN_AFTER_STACK_OVERFLOW - -/****************** ARM, Linux */ - -#elif defined(TARGET_arm) && (defined(SYS_linux_eabi) \ - || defined(SYS_linux_eabihf)) - - #include <sys/ucontext.h> - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, ucontext_t * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \ - sigact.sa_flags = SA_SIGINFO - - typedef unsigned long context_reg; - #define CONTEXT_PC (context->uc_mcontext.arm_pc) - #define CONTEXT_SP (context->uc_mcontext.arm_sp) - #define CONTEXT_EXCEPTION_POINTER (context->uc_mcontext.arm_fp) - #define CONTEXT_YOUNG_PTR (context->uc_mcontext.arm_r8) - #define CONTEXT_FAULTING_ADDRESS ((char *) context->uc_mcontext.fault_address) - -/****************** ARM64, Linux */ - -#elif defined(TARGET_arm64) && defined(SYS_linux) - - #include <sys/ucontext.h> - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, ucontext_t * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \ - sigact.sa_flags = SA_SIGINFO - - typedef unsigned long context_reg; - #define CONTEXT_PC (context->uc_mcontext.pc) - #define CONTEXT_SP (context->uc_mcontext.sp) - #define CONTEXT_EXCEPTION_POINTER (context->uc_mcontext.regs[26]) - #define CONTEXT_YOUNG_PTR (context->uc_mcontext.regs[27]) - #define CONTEXT_FAULTING_ADDRESS ((char *) context->uc_mcontext.fault_address) - -/****************** ARM64, FreeBSD */ - -#elif defined(TARGET_arm64) && defined(SYS_freebsd) - - #include <sys/ucontext.h> - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, ucontext_t * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \ - sigact.sa_flags = SA_SIGINFO - - typedef unsigned long context_reg; - #define CONTEXT_PC (context->uc_mcontext.mc_gpregs.gp_elr) - #define CONTEXT_SP (context->uc_mcontext.mc_gpregs.gp_sp) - #define CONTEXT_EXCEPTION_POINTER (context->uc_mcontext.mc_gpregs.gp_x[26]) - #define CONTEXT_YOUNG_PTR (context->uc_mcontext.mc_gpregs.gp_x[27]) - #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr) - - -/****************** AMD64, Solaris x86 */ - -#elif defined(TARGET_amd64) && defined (SYS_solaris) - - #include <ucontext.h> - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, ucontext_t * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \ - sigact.sa_flags = SA_SIGINFO - - typedef greg_t context_reg; - #define CONTEXT_PC (context->uc_mcontext.gregs[REG_RIP]) - #define CONTEXT_C_ARG_1 (context->uc_mcontext.gregs[REG_RDI]) - #define CONTEXT_SP (context->uc_mcontext.gregs[REG_RSP]) - #define CONTEXT_YOUNG_PTR (context->uc_mcontext.gregs[REG_R15]) - #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr) - -/****************** AMD64, OpenBSD */ - -#elif defined(TARGET_amd64) && defined (SYS_openbsd) - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, struct sigcontext * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \ - sigact.sa_flags = SA_SIGINFO - - #define CONTEXT_PC (context->sc_rip) - #define CONTEXT_C_ARG_1 (context->sc_rdi) - #define CONTEXT_SP (context->sc_rsp) - #define CONTEXT_YOUNG_PTR (context->sc_r15) - #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr) - -/****************** AMD64, NetBSD */ - -#elif defined(TARGET_amd64) && defined (SYS_netbsd) - - #include <ucontext.h> - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, ucontext_t * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \ - sigact.sa_flags = SA_SIGINFO - - #define CONTEXT_PC (_UC_MACHINE_PC(context)) - #define CONTEXT_C_ARG_1 (context->uc_mcontext.gregs[REG_RDI]) - #define CONTEXT_SP (_UC_MACHINE_SP(context)) - #define CONTEXT_YOUNG_PTR (context->uc_mcontext.gregs[REG_R15]) - #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr) - -/****************** I386, Linux */ - -#elif defined(TARGET_i386) && defined(SYS_linux_elf) - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, ucontext_t * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \ - sigact.sa_flags = SA_SIGINFO - - typedef greg_t context_reg; - #define CONTEXT_PC (context->uc_mcontext.gregs[REG_EIP]) - #define CONTEXT_SP (context->uc_mcontext.gregs[REG_ESP]) - #define CONTEXT_FAULTING_ADDRESS ((char *)context->uc_mcontext.cr2) - -/****************** I386, BSD_ELF */ - -#elif defined(TARGET_i386) && defined(SYS_bsd_elf) - - #if defined (__NetBSD__) - #include <ucontext.h> - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, ucontext_t * context) - #else - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, struct sigcontext * context) - #endif - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \ - sigact.sa_flags = SA_SIGINFO - - #if defined (__NetBSD__) - #define CONTEXT_PC (_UC_MACHINE_PC(context)) - #define CONTEXT_SP (_UC_MACHINE_SP(context)) - #else - #define CONTEXT_PC (context->sc_eip) - #define CONTEXT_SP (context->sc_esp) - #endif - #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr) - -/****************** I386, BSD */ - -#elif defined(TARGET_i386) && defined(SYS_bsd) - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, void * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (name); \ - sigact.sa_flags = SA_SIGINFO - - #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr) - -/****************** I386, MacOS X */ - -#elif defined(TARGET_i386) && defined(SYS_macosx) - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, void * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (name); \ - sigact.sa_flags = SA_SIGINFO - - #include <sys/ucontext.h> - #include <AvailabilityMacros.h> - - #if !defined(MAC_OS_X_VERSION_10_5) \ - || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 - #define CONTEXT_REG(r) r - #else - #define CONTEXT_REG(r) __##r - #endif - - #define CONTEXT_STATE (((ucontext_t *)context)->uc_mcontext->CONTEXT_REG(ss)) - #define CONTEXT_PC (CONTEXT_STATE.CONTEXT_REG(eip)) - #define CONTEXT_SP (CONTEXT_STATE.CONTEXT_REG(esp)) - #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr) - -/****************** I386, Solaris x86 */ - -#elif defined(TARGET_i386) && defined(SYS_solaris) - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, void * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (name); \ - sigact.sa_flags = SA_SIGINFO - - #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr) - -/****************** PowerPC, MacOS X */ - -#elif defined(TARGET_power) && defined(SYS_rhapsody) - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, void * context) - - #include <sys/ucontext.h> - #include <AvailabilityMacros.h> - - #ifdef __LP64__ - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (name); \ - sigact.sa_flags = SA_SIGINFO | SA_64REGSET - - typedef unsigned long long context_reg; - - #define CONTEXT_MCONTEXT (((ucontext64_t *)context)->uc_mcontext64) - #else - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (name); \ - sigact.sa_flags = SA_SIGINFO - - typedef unsigned long context_reg; - - #define CONTEXT_MCONTEXT (((ucontext_t *)context)->uc_mcontext) - #endif - - #if !defined(MAC_OS_X_VERSION_10_5) \ - || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 - #define CONTEXT_REG(r) r - #else - #define CONTEXT_REG(r) __##r - #endif - - #define CONTEXT_STATE (CONTEXT_MCONTEXT->CONTEXT_REG(ss)) - #define CONTEXT_PC (CONTEXT_STATE.CONTEXT_REG(srr0)) - #define CONTEXT_EXCEPTION_POINTER (CONTEXT_STATE.CONTEXT_REG(r29)) - #define CONTEXT_YOUNG_LIMIT (CONTEXT_STATE.CONTEXT_REG(r30)) - #define CONTEXT_YOUNG_PTR (CONTEXT_STATE.CONTEXT_REG(r31)) - #define CONTEXT_SP (CONTEXT_STATE.CONTEXT_REG(r1)) - #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr) - -/****************** PowerPC 32 bits, ELF (Linux) */ - -#elif defined(TARGET_power) && defined(MODEL_ppc) && defined(SYS_elf) - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, struct sigcontext * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_handler = (void (*)(int)) (name); \ - sigact.sa_flags = 0 - - typedef unsigned long context_reg; - #define CONTEXT_PC (context->regs->nip) - #define CONTEXT_EXCEPTION_POINTER (context->regs->gpr[29]) - #define CONTEXT_YOUNG_LIMIT (context->regs->gpr[30]) - #define CONTEXT_YOUNG_PTR (context->regs->gpr[31]) - #define CONTEXT_SP (context->regs->gpr[1]) - -/****************** PowerPC 64 bits, ELF (Linux) */ - -#elif defined(TARGET_power) && defined(SYS_elf) - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, ucontext_t * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \ - sigact.sa_flags = SA_SIGINFO - - typedef unsigned long context_reg; - #define CONTEXT_PC (context->uc_mcontext.gp_regs[32]) - #define CONTEXT_EXCEPTION_POINTER (context->uc_mcontext.gp_regs[29]) - #define CONTEXT_YOUNG_LIMIT (context->uc_mcontext.gp_regs[30]) - #define CONTEXT_YOUNG_PTR (context->uc_mcontext.gp_regs[31]) - #define CONTEXT_SP (context->uc_mcontext.gp_regs[1]) - #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr) - -/****************** PowerPC, NetBSD */ - -#elif defined(TARGET_power) && defined (SYS_netbsd) - - #include <ucontext.h> - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, ucontext_t * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \ - sigact.sa_flags = SA_SIGINFO - - typedef long context_reg; - #define CONTEXT_PC (_UC_MACHINE_PC(context)) - #define CONTEXT_EXCEPTION_POINTER (context->uc_mcontext.__gregs[_REG_R29]) - #define CONTEXT_YOUNG_LIMIT (context->uc_mcontext.__gregs[_REG_R30]) - #define CONTEXT_YOUNG_PTR (context->uc_mcontext.__gregs[_REG_R31]) - #define CONTEXT_SP (_UC_MACHINE_SP(context)) - #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr) - - -/****************** PowerPC, other BSDs */ - -#elif defined(TARGET_power) && \ - (defined(SYS_bsd) || defined(SYS_bsd_elf)) - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, int code, struct sigcontext * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_handler = (void (*)(int)) (name); \ - sigact.sa_flags = 0 - - typedef unsigned long context_reg; - #define CONTEXT_PC (context->sc_frame.srr0) - #define CONTEXT_EXCEPTION_POINTER (context->sc_frame.fixreg[29]) - #define CONTEXT_YOUNG_LIMIT (context->sc_frame.fixreg[30]) - #define CONTEXT_YOUNG_PTR (context->sc_frame.fixreg[31]) - #define CONTEXT_SP (context->sc_frame.fixreg[1]) - -/****************** s390x, ELF (Linux) */ -#elif defined(TARGET_s390x) && defined(SYS_elf) - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig, siginfo_t * info, ucontext_t * context) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_sigaction = (void (*)(int,siginfo_t *,void *)) (name); \ - sigact.sa_flags = SA_SIGINFO - - typedef unsigned long context_reg; - #define CONTEXT_PC (context->uc_mcontext.psw.addr) - #define CONTEXT_EXCEPTION_POINTER (context->uc_mcontext.gregs[13]) - #define CONTEXT_YOUNG_LIMIT (context->uc_mcontext.gregs[10]) - #define CONTEXT_YOUNG_PTR (context->uc_mcontext.gregs[11]) - #define CONTEXT_SP (context->uc_mcontext.gregs[15]) - #define CONTEXT_FAULTING_ADDRESS ((char *) info->si_addr) - -/******************** Default */ - -#else - - #define DECLARE_SIGNAL_HANDLER(name) \ - static void name(int sig) - - #define SET_SIGACT(sigact,name) \ - sigact.sa_handler = (name); \ - sigact.sa_flags = 0 - -#endif diff --git a/runtime/spacetime_nat.c b/runtime/spacetime_nat.c index 7e85e96e11..68ab5452df 100644 --- a/runtime/spacetime_nat.c +++ b/runtime/spacetime_nat.c @@ -33,7 +33,8 @@ #endif #include "caml/alloc.h" -#include "caml/backtrace_prim.h" +/* XXX KC */ +/* #include "caml/backtrace_prim.h" */ #include "caml/fail.h" #include "caml/gc.h" #include "caml/intext.h" diff --git a/runtime/spacetime_snapshot.c b/runtime/spacetime_snapshot.c index 4ce31ceb0a..ce352434e6 100644 --- a/runtime/spacetime_snapshot.c +++ b/runtime/spacetime_snapshot.c @@ -21,7 +21,7 @@ #include <math.h> #include "caml/alloc.h" -#include "caml/backtrace_prim.h" +/* #include "caml/backtrace_prim.h" */ #include "caml/config.h" #include "caml/custom.h" #include "caml/fail.h" diff --git a/runtime/stacks.c b/runtime/stacks.c deleted file mode 100644 index a1409b2abd..0000000000 --- a/runtime/stacks.c +++ /dev/null @@ -1,114 +0,0 @@ -/**************************************************************************/ -/* */ -/* OCaml */ -/* */ -/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */ -/* */ -/* Copyright 1996 Institut National de Recherche en Informatique et */ -/* en Automatique. */ -/* */ -/* All rights reserved. This file is distributed under the terms of */ -/* the GNU Lesser General Public License version 2.1, with the */ -/* special exception on linking described in the file LICENSE. */ -/* */ -/**************************************************************************/ - -#define CAML_INTERNALS - -/* To initialize and resize the stacks */ - -#include <string.h> -#include "caml/config.h" -#include "caml/fail.h" -#include "caml/misc.h" -#include "caml/mlvalues.h" -#include "caml/stacks.h" - -value caml_global_data = 0; - -uintnat caml_max_stack_size; /* also used in gc_ctrl.c */ - -void caml_init_stack (uintnat initial_max_size) -{ - Caml_state->stack_low = (value *) caml_stat_alloc(Stack_size); - Caml_state->stack_high = Caml_state->stack_low + Stack_size / sizeof (value); - Caml_state->stack_threshold = - Caml_state->stack_low + Stack_threshold / sizeof (value); - Caml_state->extern_sp = Caml_state->stack_high; - Caml_state->trapsp = Caml_state->stack_high; - Caml_state->trap_barrier = Caml_state->stack_high + 1; - caml_max_stack_size = initial_max_size; - caml_gc_message (0x08, "Initial stack limit: %" - ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n", - caml_max_stack_size / 1024 * sizeof (value)); -} - -void caml_realloc_stack(asize_t required_space) -{ - asize_t size; - value * new_low, * new_high, * new_sp; - - CAMLassert(Caml_state->extern_sp >= Caml_state->stack_low); - size = Caml_state->stack_high - Caml_state->stack_low; - do { - if (size >= caml_max_stack_size) caml_raise_stack_overflow(); - size *= 2; - } while (size < Caml_state->stack_high - Caml_state->extern_sp - + required_space); - caml_gc_message (0x08, "Growing stack to %" - ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n", - (uintnat) size * sizeof(value) / 1024); - new_low = (value *) caml_stat_alloc(size * sizeof(value)); - new_high = new_low + size; - -#define shift(ptr) \ - ((char *) new_high - ((char *) Caml_state->stack_high - (char *) (ptr))) - - new_sp = (value *) shift(Caml_state->extern_sp); - memmove((char *) new_sp, - (char *) Caml_state->extern_sp, - (Caml_state->stack_high - Caml_state->extern_sp) * sizeof(value)); - caml_stat_free(Caml_state->stack_low); - Caml_state->trapsp = (value *) shift(Caml_state->trapsp); - Caml_state->trap_barrier = (value *) shift(Caml_state->trap_barrier); - Caml_state->stack_low = new_low; - Caml_state->stack_high = new_high; - Caml_state->stack_threshold = - Caml_state->stack_low + Stack_threshold / sizeof (value); - Caml_state->extern_sp = new_sp; - -#undef shift -} - -CAMLprim value caml_ensure_stack_capacity(value required_space) -{ - asize_t req = Long_val(required_space); - if (Caml_state->extern_sp - req < Caml_state->stack_low) - caml_realloc_stack(req); - return Val_unit; -} - -void caml_change_max_stack_size (uintnat new_max_size) -{ - asize_t size = Caml_state->stack_high - Caml_state->extern_sp - + Stack_threshold / sizeof (value); - - if (new_max_size < size) new_max_size = size; - if (new_max_size != caml_max_stack_size){ - caml_gc_message (0x08, "Changing stack limit to %" - ARCH_INTNAT_PRINTF_FORMAT "uk bytes\n", - new_max_size * sizeof (value) / 1024); - } - caml_max_stack_size = new_max_size; -} - -CAMLexport uintnat (*caml_stack_usage_hook)(void) = NULL; - -uintnat caml_stack_usage(void) -{ - uintnat sz; - sz = Caml_state->stack_high - Caml_state->extern_sp; - if (caml_stack_usage_hook != NULL) - sz += (*caml_stack_usage_hook)(); - return sz; -} diff --git a/runtime/startup_aux.c b/runtime/startup_aux.c index ba15a30bf5..cca360c3ff 100644 --- a/runtime/startup_aux.c +++ b/runtime/startup_aux.c @@ -19,77 +19,58 @@ and native code. */ #include <stdio.h> +#include <string.h> #include "caml/backtrace.h" +#include "caml/dynlink.h" #include "caml/memory.h" #include "caml/callback.h" #include "caml/major_gc.h" +#include "caml/misc.h" #ifndef NATIVE_CODE #include "caml/dynlink.h" #endif #include "caml/osdeps.h" +#include "caml/prims.h" #include "caml/startup_aux.h" -#include "caml/memprof.h" - +#include "caml/version.h" #ifdef _WIN32 extern void caml_win32_unregister_overflow_detection (void); #endif -CAMLexport header_t *caml_atom_table = NULL; +/* Configuration parameters and flags */ + +static struct caml_params params; +const struct caml_params* const caml_params = ¶ms; -/* Initialize the atom table */ -void caml_init_atom_table(void) +static void init_startup_params() { - caml_stat_block b; - int i; - - /* PR#9128: We need to give the atom table its own page to make sure - it does not share a page with a non-value, which would break code - which depend on the correctness of the page table. For example, - if the atom table shares a page with bytecode, then functions in - the runtime may decide to follow a code pointer in a closure, as - if it were a pointer to a value. - - We add 1 padding at the end of the atom table because the atom - pointer actually points to the word *following* the corresponding - entry in the table (the entry is an empty block *header*). - */ - asize_t request = (256 + 1) * sizeof(header_t); - request = (request + Page_size - 1) / Page_size * Page_size; - caml_atom_table = - caml_stat_alloc_aligned_noexc(request, 0, &b); - - for(i = 0; i < 256; i++) { -#ifdef NATIVE_CODE - caml_atom_table[i] = Make_header_allocated_here(0, i, Caml_black); -#else - caml_atom_table[i] = Make_header(0, i, Caml_black); +#ifndef NATIVE_CODE + char_os * cds_file; #endif + + params.init_percent_free = Percent_free_def; + params.init_max_percent_free = Max_percent_free_def; + params.init_minor_heap_wsz = Minor_heap_def; + params.init_heap_chunk_sz = Heap_chunk_def; + params.init_heap_wsz = Init_heap_def; + params.init_custom_major_ratio = Custom_major_ratio_def; + params.init_custom_minor_ratio = Custom_minor_ratio_def; + params.init_custom_minor_max_bsz = Custom_minor_max_bsz_def; + params.init_max_stack_wsz = Max_stack_def; + params.init_fiber_wsz = (Stack_threshold * 2) / sizeof(value); +#ifdef DEBUG + params.verb_gc = 0x3F; +#endif +#ifndef NATIVE_CODE + cds_file = caml_secure_getenv(T("CAML_DEBUG_FILE")); + if (cds_file != NULL) { + params.cds_file = caml_stat_strdup_os(cds_file); } - if (caml_page_table_add(In_static_data, - caml_atom_table, caml_atom_table + 256 + 1) != 0) { - caml_fatal_error("not enough memory for initial page table"); - } +#endif + params.cleanup_on_exit = 0; } - -/* Parse the OCAMLRUNPARAM environment variable. */ - -uintnat caml_init_percent_free = Percent_free_def; -uintnat caml_init_max_percent_free = Max_percent_free_def; -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; -uintnat caml_init_custom_major_ratio = Custom_major_ratio_def; -uintnat caml_init_custom_minor_ratio = Custom_minor_ratio_def; -uintnat caml_init_custom_minor_max_bsz = Custom_minor_max_bsz_def; -extern int caml_parser_trace; -uintnat caml_trace_level = 0; -int caml_cleanup_on_exit = 0; - - static void scanmult (char_os *opt, uintnat *var) { char_os mult = ' '; @@ -107,44 +88,46 @@ static void scanmult (char_os *opt, uintnat *var) void caml_parse_ocamlrunparam(void) { char_os *opt = caml_secure_getenv (T("OCAMLRUNPARAM")); - uintnat p; + + init_startup_params(); if (opt == NULL) opt = caml_secure_getenv (T("CAMLRUNPARAM")); if (opt != NULL){ while (*opt != '\0'){ switch (*opt++){ - case 'a': scanmult (opt, &p); caml_set_allocation_policy ((intnat) p); - break; - case 'b': scanmult (opt, &p); caml_record_backtrace(Val_bool (p)); - break; - case 'c': scanmult (opt, &p); caml_cleanup_on_exit = (p != 0); 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 'M': scanmult (opt, &caml_init_custom_major_ratio); break; - case 'm': scanmult (opt, &caml_init_custom_minor_ratio); break; - case 'n': scanmult (opt, &caml_init_custom_minor_max_bsz); break; - case 'o': scanmult (opt, &caml_init_percent_free); break; - case 'O': scanmult (opt, &caml_init_max_percent_free); break; - case 'p': scanmult (opt, &p); caml_parser_trace = (p != 0); break; + //case 'a': scanmult (opt, &p); caml_set_allocation_policy (p); break; + case 'b': scanmult (opt, ¶ms.backtrace_enabled_init); break; + case 'c': scanmult (opt, ¶ms.cleanup_on_exit); break; + case 'e': scanmult (opt, ¶ms.eventlog_enabled); break; + case 'f': scanmult (opt, ¶ms.init_fiber_wsz); break; + case 'h': scanmult (opt, ¶ms.init_heap_wsz); break; + //case 'H': scanmult (opt, &caml_use_huge_pages); break; + case 'i': scanmult (opt, ¶ms.init_heap_chunk_sz); break; + case 'l': scanmult (opt, ¶ms.init_max_stack_wsz); break; + case 'M': scanmult (opt, ¶ms.init_custom_major_ratio); break; + case 'm': scanmult (opt, ¶ms.init_custom_minor_ratio); break; + case 'n': scanmult (opt, ¶ms.init_custom_minor_max_bsz); break; + case 'o': scanmult (opt, ¶ms.init_percent_free); break; + case 'O': scanmult (opt, ¶ms.init_max_percent_free); break; + case 'p': scanmult (opt, ¶ms.parser_trace); break; case 'R': break; /* see stdlib/hashtbl.mli */ - 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 's': scanmult (opt, ¶ms.init_minor_heap_wsz); break; + case 'S': scanmult (opt, ¶ms.print_stats); break; + case 't': scanmult (opt, ¶ms.trace_level); break; + case 'v': scanmult (opt, ¶ms.verb_gc); break; + case 'V': scanmult (opt, ¶ms.verify_heap); break; + //case 'w': scanmult (opt, &caml_init_major_window); break; case 'W': scanmult (opt, &caml_runtime_warnings); break; case ',': continue; } + --opt; /* to handle patterns like ",b=1" */ while (*opt != '\0'){ if (*opt++ == ',') break; } } } } - - /* The number of outstanding calls to caml_startup */ static int startup_count = 0; @@ -155,7 +138,7 @@ static int shutdown_happened = 0; int caml_startup_aux(int pooling) { if (shutdown_happened == 1) - caml_fatal_error("caml_startup was called after the runtime " + caml_fatal_error("Fatal error: caml_startup was called after the runtime " "was shut down with caml_shutdown"); /* Second and subsequent calls are ignored, @@ -180,7 +163,7 @@ static void call_registered_value(char* name) CAMLexport void caml_shutdown(void) { if (startup_count <= 0) - caml_fatal_error("a call to caml_shutdown has no " + caml_fatal_error("Fatal error: a call to caml_shutdown has no " "corresponding call to caml_startup"); /* Do nothing unless it's the last call remaining */ @@ -202,3 +185,72 @@ CAMLexport void caml_shutdown(void) shutdown_happened = 1; } + +void caml_init_exe_name(const char* exe_name) +{ + params.exe_name = exe_name; +} + +void caml_init_section_table(const char* section_table, + asize_t section_table_size) +{ + params.section_table = section_table; + params.section_table_size = section_table_size; +} + +CAMLprim value caml_maybe_print_stats (value v) +{ + Assert (v == Val_unit); + if (caml_params->print_stats) + caml_print_stats (); + return Val_unit; +} + +#ifndef NATIVE_CODE + +/* Parse options on the command line */ + +int caml_parse_command_line(char_os **argv) +{ + int i, j; + + for(i = 1; argv[i] != NULL && argv[i][0] == '-'; i++) { + switch(argv[i][1]) { + case 't': + params.trace_level++; /* ignored unless DEBUG mode */ + break; + case 'v': + if (!strcmp_os (argv[i], T("-version"))){ + printf ("The OCaml runtime, version " OCAML_VERSION_STRING "\n"); + exit (0); + }else if (!strcmp_os (argv[i], T("-vnum"))){ + printf (OCAML_VERSION_STRING "\n"); + exit (0); + }else{ + params.verb_gc = 0x001+0x004+0x008+0x010+0x020; + } + break; + case 'p': + for (j = 0; caml_names_of_builtin_cprim[j] != NULL; j++) + printf("%s\n", caml_names_of_builtin_cprim[j]); + exit(0); + break; + case 'b': + params.backtrace_enabled_init = 1; + break; + case 'I': + if (argv[i + 1] != NULL) { + caml_ext_table_add(&caml_shared_libs_path, argv[i + 1]); + i++; + } + break; + default: + caml_fatal_error_arg("Unknown option %s.\n", caml_stat_strdup_of_os(argv[i])); + } + } + return i; +} + +#endif /* not NATIVE_CODE */ + + diff --git a/runtime/startup_byt.c b/runtime/startup_byt.c index 1d04a85ad1..84c8386c3b 100644 --- a/runtime/startup_byt.c +++ b/runtime/startup_byt.c @@ -33,13 +33,13 @@ #include "caml/callback.h" #include "caml/custom.h" #include "caml/debugger.h" -#include "caml/domain.h" +#include "caml/domain_state.h" #include "caml/dynlink.h" #include "caml/eventlog.h" #include "caml/exec.h" #include "caml/fail.h" +#include "caml/fiber.h" #include "caml/fix_code.h" -#include "caml/freelist.h" #include "caml/gc_ctrl.h" #include "caml/instrtrace.h" #include "caml/interp.h" @@ -50,14 +50,13 @@ #include "caml/misc.h" #include "caml/mlvalues.h" #include "caml/osdeps.h" +#include "caml/startup_aux.h" #include "caml/prims.h" #include "caml/printexc.h" #include "caml/reverse.h" #include "caml/signals.h" -#include "caml/stacks.h" #include "caml/sys.h" #include "caml/startup.h" -#include "caml/startup_aux.h" #include "caml/version.h" #ifndef O_BINARY @@ -244,81 +243,6 @@ static char_os * read_section_to_os(int fd, struct exec_trailer *trail, #endif -/* Invocation of ocamlrun: 4 cases. - - 1. runtime + bytecode - user types: ocamlrun [options] bytecode args... - arguments: ocamlrun [options] bytecode args... - - 2. bytecode script - user types: bytecode args... - 2a (kernel 1) arguments: ocamlrun ./bytecode args... - 2b (kernel 2) arguments: bytecode bytecode args... - - 3. concatenated runtime and bytecode - user types: composite args... - arguments: composite args... - -Algorithm: - 1- If argument 0 is a valid byte-code file that does not start with #!, - then we are in case 3 and we pass the same command line to the - OCaml program. - 2- In all other cases, we parse the command line as: - (whatever) [options] bytecode args... - and we strip "(whatever) [options]" from the command line. - -*/ - -/* Parse options on the command line */ - -static int parse_command_line(char_os **argv) -{ - int i, j; - - for(i = 1; argv[i] != NULL && argv[i][0] == '-'; i++) { - switch(argv[i][1]) { - case 't': - ++ caml_trace_level; /* ignored unless DEBUG mode */ - break; - case 'v': - if (!strcmp_os (argv[i], T("-version"))){ - printf ("%s\n", "The OCaml runtime, version " OCAML_VERSION_STRING); - exit (0); - }else if (!strcmp_os (argv[i], T("-vnum"))){ - printf ("%s\n", OCAML_VERSION_STRING); - exit (0); - }else{ - caml_verb_gc = 0x001+0x004+0x008+0x010+0x020; - } - break; - case 'p': - for (j = 0; caml_names_of_builtin_cprim[j] != NULL; j++) - printf("%s\n", caml_names_of_builtin_cprim[j]); - exit(0); - break; - case 'b': - caml_record_backtrace(Val_true); - break; - case 'I': - if (argv[i + 1] != NULL) { - caml_ext_table_add(&caml_shared_libs_path, argv[i + 1]); - i++; - } - break; - case 'm': - print_magic = 1; - break; - case 'M': - printf ( "%s\n", EXEC_MAGIC); - exit(0); - break; - default: - error("unknown option %s", caml_stat_strdup_of_os(argv[i])); - } - } - return i; -} - #ifdef _WIN32 extern void caml_signal_thread(void * lpParam); #endif @@ -344,21 +268,17 @@ CAMLexport void caml_main(char_os **argv) char_os * shared_lib_path, * shared_libs; char_os * exe_name, * proc_self_exe; - caml_ensure_spacetime_dot_o_is_included++; + CAML_INIT_DOMAIN_STATE; - /* Initialize the domain */ - caml_init_domain(); + caml_ensure_spacetime_dot_o_is_included++; /* Determine options */ -#ifdef DEBUG - caml_verb_gc = 0x3F; -#endif caml_parse_ocamlrunparam(); CAML_EVENTLOG_INIT(); #ifdef DEBUG caml_gc_message (-1, "### OCaml runtime: debug mode ###\n"); #endif - if (!caml_startup_aux(/* pooling */ caml_cleanup_on_exit)) + if (!caml_startup_aux(/* pooling */ caml_params->cleanup_on_exit)) return; caml_init_locale(); @@ -387,7 +307,7 @@ CAMLexport void caml_main(char_os **argv) } if (fd < 0) { - pos = parse_command_line(argv); + pos = caml_parse_command_line(argv); if (argv[pos] == 0) { error("no bytecode file specified"); } @@ -413,17 +333,13 @@ CAMLexport void caml_main(char_os **argv) break; } } + /* Read the table of contents (section descriptors) */ caml_read_section_descriptors(fd, &trail); /* 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_major_window, - caml_init_custom_major_ratio, caml_init_custom_minor_ratio, - caml_init_custom_minor_max_bsz); - caml_init_stack (caml_init_max_stack_wsz); - caml_init_atom_table(); - caml_init_backtrace(); + caml_init_gc (); + Caml_state->external_raise = NULL; + if (caml_params->backtrace_enabled_init) caml_record_backtrace(Val_int(1)); /* Initialize the interpreter */ caml_interprete(NULL, 0); /* Initialize the debugger, if needed */ @@ -444,14 +360,13 @@ CAMLexport void caml_main(char_os **argv) /* Load the globals */ caml_seek_section(fd, &trail, "DATA"); chan = caml_open_descriptor_in(fd); - caml_global_data = caml_input_val(chan); + caml_modify_root(caml_global_data, caml_input_val(chan)); caml_close_channel(chan); /* this also closes fd */ caml_stat_free(trail.section); - /* Ensure that the globals are in the major heap. */ - caml_oldify_one (caml_global_data, &caml_global_data); - caml_oldify_mopup (); /* Initialize system libraries */ caml_sys_init(exe_name, argv + pos); + /* ensure all globals are in major heap */ + caml_minor_collection(); #ifdef _WIN32 /* Start a thread to handle signals */ if (caml_secure_getenv(T("CAMLSIGPIPE"))) @@ -460,14 +375,15 @@ CAMLexport void caml_main(char_os **argv) /* Execute the program */ caml_debugger(PROGRAM_START, Val_unit); res = caml_interprete(caml_start_code, caml_code_size); + caml_maybe_print_stats(Val_unit); if (Is_exception_result(res)) { - Caml_state->exn_bucket = Extract_exception(res); + value exn = Extract_exception(res); if (caml_debugger_in_use) { - Caml_state->extern_sp = &Caml_state->exn_bucket; /* The debugger needs the - exception value.*/ + Caml_state->current_stack->sp = &exn; /* The debugger needs the + exception value.*/ caml_debugger(UNCAUGHT_EXC, Val_unit); } - caml_fatal_uncaught_exception(Caml_state->exn_bucket); + caml_fatal_uncaught_exception(exn); } } @@ -480,21 +396,17 @@ CAMLexport value caml_startup_code_exn( int pooling, char_os **argv) { - char_os * cds_file; char_os * exe_name; - /* Initialize the domain */ - caml_init_domain(); + CAML_INIT_DOMAIN_STATE; + /* Determine options */ -#ifdef DEBUG - caml_verb_gc = 0x3F; -#endif caml_parse_ocamlrunparam(); CAML_EVENTLOG_INIT(); #ifdef DEBUG caml_gc_message (-1, "### OCaml runtime: debug mode ###\n"); #endif - if (caml_cleanup_on_exit) + if (caml_params->cleanup_on_exit) pooling = 1; if (!caml_startup_aux(pooling)) return Val_unit; @@ -504,21 +416,15 @@ CAMLexport value caml_startup_code_exn( caml_install_invalid_parameter_handler(); #endif caml_init_custom_operations(); - cds_file = caml_secure_getenv(T("CAML_DEBUG_FILE")); - if (cds_file != NULL) { - caml_cds_file = caml_stat_strdup_os(cds_file); - } + + /* Initialize the abstract machine */ + caml_init_gc (); exe_name = caml_executable_name(); if (exe_name == NULL) exe_name = caml_search_exe_in_path(argv[0]); - /* 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_major_window, - caml_init_custom_major_ratio, caml_init_custom_minor_ratio, - caml_init_custom_minor_max_bsz); - caml_init_stack (caml_init_max_stack_wsz); - caml_init_atom_table(); - caml_init_backtrace(); + Caml_state->external_raise = NULL; + caml_sys_init(exe_name, argv); + if (caml_params->backtrace_enabled_init) caml_record_backtrace(Val_int(1)); + Caml_state->external_raise = NULL; /* Initialize the interpreter */ caml_interprete(NULL, 0); /* Initialize the debugger, if needed */ @@ -534,15 +440,10 @@ CAMLexport value caml_startup_code_exn( /* Use the builtin table of primitives */ caml_build_primitive_table_builtin(); /* Load the globals */ - caml_global_data = caml_input_value_from_block(data, data_size); - /* Ensure that the globals are in the major heap. */ - caml_oldify_one (caml_global_data, &caml_global_data); - caml_oldify_mopup (); + caml_modify_root(caml_global_data, caml_input_value_from_block(data, data_size)); + caml_minor_collection(); /* ensure all globals are in major heap */ /* Record the sections (for caml_get_section_table in meta.c) */ - caml_section_table = section_table; - caml_section_table_size = section_table_size; - /* Initialize system libraries */ - caml_sys_init(exe_name, argv); + caml_init_section_table(section_table, section_table_size); /* Execute the program */ caml_debugger(PROGRAM_START, Val_unit); return caml_interprete(caml_start_code, caml_code_size); @@ -561,12 +462,12 @@ CAMLexport void caml_startup_code( section_table, section_table_size, pooling, argv); if (Is_exception_result(res)) { - Caml_state->exn_bucket = Extract_exception(res); + value exn = Extract_exception(res); if (caml_debugger_in_use) { - Caml_state->extern_sp = &Caml_state->exn_bucket; /* The debugger needs the - exception value.*/ + Caml_state->current_stack->sp = &exn; /* The debugger needs the + exception value.*/ caml_debugger(UNCAUGHT_EXC, Val_unit); } - caml_fatal_uncaught_exception(Caml_state->exn_bucket); + caml_fatal_uncaught_exception(exn); } } diff --git a/runtime/startup_nat.c b/runtime/startup_nat.c index 4e5926499e..16335f23e9 100644 --- a/runtime/startup_nat.c +++ b/runtime/startup_nat.c @@ -19,15 +19,14 @@ #include <stdio.h> #include <stdlib.h> -#include "caml/callback.h" #include "caml/backtrace.h" +#include "caml/callback.h" #include "caml/custom.h" #include "caml/codefrag.h" #include "caml/debugger.h" -#include "caml/domain.h" #include "caml/eventlog.h" +#include "caml/fiber.h" #include "caml/fail.h" -#include "caml/freelist.h" #include "caml/gc.h" #include "caml/gc_ctrl.h" #include "caml/intext.h" @@ -37,8 +36,8 @@ #include "caml/osdeps.h" #include "caml/printexc.h" #include "caml/stack.h" -#include "caml/startup_aux.h" #include "caml/sys.h" +#include "caml/startup_aux.h" #ifdef WITH_SPACETIME #include "caml/spacetime.h" #endif @@ -50,26 +49,15 @@ extern int caml_parser_trace; char * caml_code_area_start, * caml_code_area_end; extern char caml_system__code_begin, caml_system__code_end; -/* Initialize the atom table and the static data and code area limits. */ +/* Initialize the static data and code area limits. */ struct segment { char * begin; char * end; }; -static void init_static(void) +static void init_segments(void) { - extern struct segment caml_data_segments[], caml_code_segments[]; + extern struct segment caml_code_segments[]; int i; - caml_init_atom_table (); - - for (i = 0; caml_data_segments[i].begin != 0; i++) { - /* PR#5509: we must include the zero word at end of data segment, - because pointers equal to caml_data_segments[i].end are static data. */ - if (caml_page_table_add(In_static_data, - caml_data_segments[i].begin, - caml_data_segments[i].end + sizeof(value)) != 0) - caml_fatal_error("not enough memory for initial page table"); - } - caml_code_area_start = caml_code_segments[0].begin; caml_code_area_end = caml_code_segments[0].end; for (i = 1; caml_code_segments[i].begin != 0; i++) { @@ -94,9 +82,6 @@ void (*caml_termination_hook)(void *) = NULL; extern value caml_start_program (caml_domain_state*); extern void caml_init_signals (void); -#ifdef _WIN32 -extern void caml_win32_overflow_detection (void); -#endif #if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L @@ -108,20 +93,16 @@ extern void caml_install_invalid_parameter_handler(); value caml_startup_common(char_os **argv, int pooling) { char_os * exe_name, * proc_self_exe; - char tos; - /* Initialize the domain */ - caml_init_domain(); + CAML_INIT_DOMAIN_STATE; + /* Determine options */ -#ifdef DEBUG - caml_verb_gc = 0x3F; -#endif caml_parse_ocamlrunparam(); CAML_EVENTLOG_INIT(); #ifdef DEBUG caml_gc_message (-1, "### OCaml runtime: debug mode ###\n"); #endif - if (caml_cleanup_on_exit) + if (caml_params->cleanup_on_exit) pooling = 1; if (!caml_startup_aux(pooling)) return Val_unit; @@ -129,24 +110,18 @@ value caml_startup_common(char_os **argv, int pooling) #ifdef WITH_SPACETIME caml_spacetime_initialize(); #endif - caml_init_frame_descriptors(); caml_init_locale(); #if defined(_MSC_VER) && __STDC_SECURE_LIB__ >= 200411L caml_install_invalid_parameter_handler(); #endif caml_init_custom_operations(); - Caml_state->top_of_stack = &tos; - 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_major_window, - caml_init_custom_major_ratio, caml_init_custom_minor_ratio, - caml_init_custom_minor_max_bsz); - init_static(); + caml_init_gc (); + + if (caml_params->backtrace_enabled_init) + caml_record_backtrace(Val_int(1)); + + init_segments(); caml_init_signals(); -#ifdef _WIN32 - caml_win32_overflow_detection(); -#endif - caml_init_backtrace(); caml_debugger_init (); /* force debugger.o stub to be linked */ exe_name = argv[0]; if (exe_name == NULL) exe_name = T(""); @@ -160,6 +135,7 @@ value caml_startup_common(char_os **argv, int pooling) if (caml_termination_hook != NULL) caml_termination_hook(NULL); return Val_unit; } + caml_maybe_expand_stack(); return caml_start_program(Caml_state); } @@ -168,16 +144,17 @@ value caml_startup_exn(char_os **argv) return caml_startup_common(argv, /* pooling */ 0); } -void caml_startup(char_os **argv) +void caml_main(char_os **argv) { value res = caml_startup_exn(argv); + caml_maybe_print_stats(Val_unit); if (Is_exception_result(res)) caml_fatal_uncaught_exception(Extract_exception(res)); } -void caml_main(char_os **argv) +void caml_startup(char_os **argv) { - caml_startup(argv); + caml_main(argv); } value caml_startup_pooled_exn(char_os **argv) diff --git a/runtime/sys.c b/runtime/sys.c index 6b67c7a8b5..af616bd987 100644 --- a/runtime/sys.c +++ b/runtime/sys.c @@ -50,15 +50,17 @@ #include "caml/fail.h" #include "caml/gc_ctrl.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/fiber.h" #include "caml/sys.h" +#include "caml/startup.h" #include "caml/version.h" #include "caml/callback.h" #include "caml/startup_aux.h" +#include "caml/major_gc.h" +#include "caml/shared_heap.h" static char * error_message(void) { @@ -114,48 +116,58 @@ static void caml_sys_check_path(value name) CAMLprim value caml_sys_exit(value retcode_v) { + caml_domain_state* domain_state = Caml_state; int retcode = Int_val(retcode_v); - - if ((caml_verb_gc & 0x400) != 0) { - /* cf caml_gc_counters */ - double minwords = Caml_state->stat_minor_words - + (double) (Caml_state->young_end - Caml_state->young_ptr); - double prowords = Caml_state->stat_promoted_words; - double majwords = - Caml_state->stat_major_words + (double) caml_allocated_words; - double allocated_words = minwords + majwords - prowords; - intnat mincoll = Caml_state->stat_minor_collections; - intnat majcoll = Caml_state->stat_major_collections; - intnat heap_words = Caml_state->stat_heap_wsz; - intnat heap_chunks = Caml_state->stat_heap_chunks; - intnat top_heap_words = Caml_state->stat_top_heap_wsz; - intnat cpct = Caml_state->stat_compactions; - intnat forcmajcoll = Caml_state->stat_forced_major_collections; - caml_gc_message(0x400, "allocated_words: %.0f\n", allocated_words); - caml_gc_message(0x400, "minor_words: %.0f\n", minwords); - caml_gc_message(0x400, "promoted_words: %.0f\n", prowords); - caml_gc_message(0x400, "major_words: %.0f\n", majwords); - caml_gc_message(0x400, "minor_collections: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", - mincoll); - caml_gc_message(0x400, "major_collections: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", - majcoll); - caml_gc_message(0x400, "heap_words: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", - heap_words); - caml_gc_message(0x400, "heap_chunks: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", - heap_chunks); - caml_gc_message(0x400, "top_heap_words: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", - top_heap_words); - caml_gc_message(0x400, "compactions: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", - cpct); - caml_gc_message(0x400, - "forced_major_collections: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", - forcmajcoll); + struct gc_stats s; + + if ((caml_params->verb_gc & 0x400) != 0) { + caml_sample_gc_stats(&s); + { + /* cf caml_gc_counters */ + double minwords = s.minor_words + + (double) (domain_state->young_end - domain_state->young_ptr); + double majwords = s.major_words + (double) domain_state->allocated_words; + double allocated_words = minwords + majwords - s.promoted_words; + intnat heap_words = + s.major_heap.pool_words + s.major_heap.large_words; + intnat top_heap_words = + s.major_heap.pool_max_words + s.major_heap.large_max_words; + + if (heap_words == 0) { + heap_words = Wsize_bsize(caml_heap_size(Caml_state->shared_heap)); + } + + if (top_heap_words == 0) { + top_heap_words = caml_top_heap_words(Caml_state->shared_heap); + } + + caml_gc_message(0x400, "allocated_words: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + (intnat)allocated_words); + caml_gc_message(0x400, "minor_words: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + (intnat) minwords); + caml_gc_message(0x400, "promoted_words: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + (intnat) s.promoted_words); + caml_gc_message(0x400, "major_words: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + (intnat) majwords); + caml_gc_message(0x400, "minor_collections: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + (intnat) s.minor_collections); + caml_gc_message(0x400, "major_collections: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + domain_state->stat_major_collections); + caml_gc_message(0x400, + "forced_major_collections: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + (intnat)s.forced_major_collections); + caml_gc_message(0x400, "heap_words: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + heap_words); + caml_gc_message(0x400, "top_heap_words: %"ARCH_INTNAT_PRINTF_FORMAT"d\n", + top_heap_words); + caml_gc_message(0x400, "mean_space_overhead: %lf\n", caml_mean_space_overhead()); + } } #ifndef NATIVE_CODE caml_debugger(PROGRAM_EXIT, Val_unit); #endif - if (caml_cleanup_on_exit) + if (caml_params->cleanup_on_exit) caml_shutdown(); #ifdef _WIN32 caml_restore_win32_terminal(); @@ -177,7 +189,7 @@ CAMLprim value caml_sys_exit(value retcode_v) #endif #endif -static int sys_open_flags[] = { +const static int sys_open_flags[] = { O_RDONLY, O_WRONLY, O_APPEND | O_WRONLY, O_CREAT, O_TRUNC, O_EXCL, O_BINARY, O_TEXT, O_NONBLOCK }; @@ -374,38 +386,38 @@ CAMLprim value caml_sys_getenv(value var) return val; } -char_os * caml_exe_name; -static value main_argv; +static caml_root main_argv; CAMLprim value caml_sys_get_argv(value unit) { CAMLparam0 (); /* unit is unused */ CAMLlocal2 (exe_name, res); - exe_name = caml_copy_string_of_os(caml_exe_name); + exe_name = caml_copy_string_of_os(caml_params->exe_name); res = caml_alloc_small(2, 0); - Field(res, 0) = exe_name; - Field(res, 1) = main_argv; + caml_initialize_field(res, 0, exe_name); + caml_initialize_field(res, 1, caml_read_root(main_argv)); CAMLreturn(res); } CAMLprim value caml_sys_argv(value unit) { - return main_argv; + return caml_read_root(main_argv); } CAMLprim value caml_sys_modify_argv(value new_argv) { - caml_modify_generational_global_root(&main_argv, new_argv); + caml_modify_root(main_argv, new_argv); return Val_unit; } CAMLprim value caml_sys_executable_name(value unit) { - return caml_copy_string_of_os(caml_exe_name); + return caml_copy_string_of_os(caml_params->exe_name); } void caml_sys_init(char_os * exe_name, char_os **argv) { + value v; #ifdef _WIN32 /* Initialises the caml_win32_* globals on Windows with the version of Windows which is running */ @@ -414,10 +426,10 @@ void caml_sys_init(char_os * exe_name, char_os **argv) caml_setup_win32_terminal(); #endif #endif - caml_exe_name = exe_name; - main_argv = caml_alloc_array((void *)caml_copy_string_of_os, - (char const **) argv); - caml_register_generational_global_root(&main_argv); + caml_init_exe_name(exe_name); + v = caml_alloc_array((void *)caml_copy_string_of_os, + (char const **) argv); + main_argv = caml_create_root(v); } #ifdef _WIN32 diff --git a/runtime/unix.c b/runtime/unix.c index c0ddbaaaf8..2f53b7f8f4 100644 --- a/runtime/unix.c +++ b/runtime/unix.c @@ -26,9 +26,12 @@ #include <string.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/time.h> #include <errno.h> #include <sys/ioctl.h> #include <fcntl.h> +#include <time.h> +#include <errno.h> #include "caml/config.h" #ifdef SUPPORT_DYNAMIC_LINKING #ifdef __CYGWIN__ @@ -427,6 +430,25 @@ char *caml_secure_getenv (char const *var) #endif } +int64_t caml_time_counter(void) +{ +#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK != (-1) + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + return + (int64_t)t.tv_sec * (int64_t)1000000000 + + (int64_t)t.tv_nsec; +#elif defined(HAS_GETTIMEOFDAY) + struct timeval t; + gettimeofday(&t, 0); + return + (int64_t)t.tv_sec * (int64_t)1000000000 + + (int64_t)t.tv_usec * (int64_t)1000; +#else +# error "No timesource available" +#endif +} + int caml_num_rows_fd(int fd) { #ifdef TIOCGWINSZ diff --git a/runtime/weak.c b/runtime/weak.c index da509637ff..a3a1e734f2 100644 --- a/runtime/weak.c +++ b/runtime/weak.c @@ -20,94 +20,49 @@ #include <string.h> #include "caml/alloc.h" +#include "caml/domain.h" #include "caml/fail.h" #include "caml/major_gc.h" #include "caml/memory.h" #include "caml/mlvalues.h" +#include "caml/shared_heap.h" #include "caml/weak.h" -#include "caml/minor_gc.h" -#include "caml/signals.h" -#include "caml/eventlog.h" - -value caml_ephe_list_head = 0; - -static value ephe_dummy = 0; -value caml_ephe_none = (value) &ephe_dummy; - -#define CAMLassert_valid_ephemeron(eph) do{ \ - CAMLassert (Is_in_heap (eph)); \ - CAMLassert (Tag_val(eph) == Abstract_tag); \ - CAMLassert (CAML_EPHE_FIRST_KEY <= Wosize_val (eph)); \ -}while(0) - -#define CAMLassert_valid_offset(eph, offset) do{ \ - CAMLassert_valid_ephemeron(eph); \ - CAMLassert (0 <= offset); \ - CAMLassert (offset < Wosize_val (eph) - CAML_EPHE_FIRST_KEY); \ -}while(0) - -#define CAMLassert_not_dead_value(v) do{ \ - CAMLassert ( caml_gc_phase != Phase_clean \ - || !Is_block(v) \ - || !Is_in_heap (v) \ - || !Is_white_val(v) ); \ -}while(0) - -CAMLexport mlsize_t caml_ephemeron_num_keys(value eph) -{ - CAMLassert_valid_ephemeron(eph); - return Wosize_val (eph) - CAML_EPHE_FIRST_KEY; -} -/** The minor heap is considered alive. */ +value caml_dummy[] = + {(value)Make_header(0,Abstract_tag, NOT_MARKABLE), + Val_unit}; +value caml_ephe_none = (value)&caml_dummy[1]; -/** Outside minor and major heap, x must be black. */ -Caml_inline int Is_Dead_during_clean(value x) -{ - CAMLassert (x != caml_ephe_none); - CAMLassert (caml_gc_phase == Phase_clean); -#ifdef NO_NAKED_POINTERS - return Is_block (x) && !Is_young (x) && Is_white_val(x); -#else - return Is_block (x) && Is_in_heap (x) && Is_white_val(x); -#endif -} -/** The minor heap doesn't have to be marked, outside they should - already be black -*/ -Caml_inline int Must_be_Marked_during_mark(value x) +#define None_val (Val_int(0)) +#define Some_tag 0 + +struct caml_ephe_info* caml_alloc_ephe_info () { - CAMLassert (x != caml_ephe_none); - CAMLassert (caml_gc_phase == Phase_mark); -#ifdef NO_NAKED_POINTERS - return Is_block (x) && !Is_young (x); -#else - return Is_block (x) && Is_in_heap (x); -#endif + struct caml_ephe_info* e = + caml_stat_alloc_noexc (sizeof(struct caml_ephe_info)); + if(e != NULL) + memset (e, 0, sizeof(struct caml_ephe_info)); + return e; } -/* [len] is a number of words (fields) */ -CAMLexport value caml_ephemeron_create (mlsize_t len) +/* [len] is a value that represents a number of words (fields) */ +CAMLprim value caml_ephe_create (value len) { mlsize_t size, i; value res; + caml_domain_state* domain_state = Caml_state; - CAMLassert(len <= CAML_EPHE_MAX_WOSIZE); - size = len + CAML_EPHE_FIRST_KEY; - if (size < CAML_EPHE_FIRST_KEY || size > Max_wosize) - caml_invalid_argument ("Weak.create"); + size = Long_val (len) + + 1 /* weak_list */ + + 1 /* the value */; + if (size < CAML_EPHE_FIRST_KEY || size > Max_wosize) caml_invalid_argument ("Weak.create"); res = caml_alloc_shr (size, Abstract_tag); - for (i = 1; i < size; i++) Field (res, i) = caml_ephe_none; - Field (res, CAML_EPHE_LINK_OFFSET) = caml_ephe_list_head; - caml_ephe_list_head = res; - return res; -} -CAMLprim value caml_ephe_create (value len) -{ - value res = caml_ephemeron_create(Long_val(len)); - // run memprof callbacks - return caml_process_pending_actions_with_root(res); + Ephe_link(res) = domain_state->ephe_info->live; + domain_state->ephe_info->live = res; + for (i = CAML_EPHE_DATA_OFFSET; i < size; i++) + Op_val(res)[i] = caml_ephe_none; + return res; } CAMLprim value caml_weak_create (value len) @@ -145,178 +100,166 @@ CAMLprim value caml_weak_create (value len) */ -#define None_val (Val_int(0)) -#define Some_tag 0 - -/* If we are in Phase_clean we need to check if the key +/* If we are in Phase_sweep_ephe we need to check if the key that is going to disappear is dead and so should trigger a cleaning */ -static void do_check_key_clean(value ar, mlsize_t offset) +static void do_check_key_clean(value e, mlsize_t offset) { + value elt; CAMLassert (offset >= CAML_EPHE_FIRST_KEY); - if (caml_gc_phase == Phase_clean){ - value elt = Field (ar, offset); - if (elt != caml_ephe_none && Is_Dead_during_clean(elt)){ - Field(ar, offset) = caml_ephe_none; - Field(ar, CAML_EPHE_DATA_OFFSET) = caml_ephe_none; - }; - }; -} -/* If we are in Phase_clean we need to do as if the key is empty when - it will be cleaned during this phase */ -Caml_inline int is_ephe_key_none(value ar, mlsize_t offset) -{ - value elt = Field (ar, offset); - if (elt == caml_ephe_none){ - return 1; - }else if (caml_gc_phase == Phase_clean && Is_Dead_during_clean(elt)){ - Field(ar, offset) = caml_ephe_none; - Field(ar, CAML_EPHE_DATA_OFFSET) = caml_ephe_none; - return 1; - } else { - return 0; + if (caml_gc_phase != Phase_sweep_ephe) return; + + elt = Op_val(e)[offset]; + if (elt != caml_ephe_none && Is_block (elt) && + !Is_young (elt) && is_unmarked(elt)) { + Op_val(e)[offset] = caml_ephe_none; + Op_val(e)[CAML_EPHE_DATA_OFFSET] = caml_ephe_none; } } -static void do_set (value ar, mlsize_t offset, value v) -{ - if (Is_block (v) && Is_young (v)){ - /* modified version of caml_modify */ - value old = Field (ar, offset); - Field (ar, offset) = v; - if (!(Is_block (old) && Is_young (old))){ - add_to_ephe_ref_table (Caml_state->ephe_ref_table, ar, offset); +void caml_ephe_clean (value v) { + value child; + int release_data = 0; + mlsize_t size, i; + header_t hd; + + if (caml_gc_phase != Phase_sweep_ephe) return; + + hd = Hd_val(v); + size = Wosize_hd (hd); + for (i = CAML_EPHE_FIRST_KEY; i < size; i++) { + child = Op_val(v)[i]; + ephemeron_again: + if (child != caml_ephe_none && Is_block(child)) { + if (Tag_val (child) == Forward_tag) { + value f = Forward_val (child); + if (Is_block(f)) { + if (Tag_val(f) == Forward_tag || Tag_val(f) == Lazy_tag || + Tag_val(f) == Double_tag) { + /* Do not short-circuit the pointer */ + } else { + Op_val(v)[i] = child = f; + if (Is_block (f) && Is_young (f)) + add_to_ephe_ref_table(&Caml_state->minor_tables->ephe_ref, v, i); + goto ephemeron_again; + } + } + } + + // FIXME: Is_young -> Is_young here is probably not what we want, fix this. + if (!Is_young (child) && is_unmarked(child)) { + release_data = 1; + Op_val(v)[i] = caml_ephe_none; + } + } + } + + child = Op_val(v)[CAML_EPHE_DATA_OFFSET]; + if (child != caml_ephe_none) { + if (release_data) { + Op_val(v)[CAML_EPHE_DATA_OFFSET] = caml_ephe_none; + } else { + CAMLassert (!Is_block(child) || !is_unmarked(child)); } - }else{ - Field (ar, offset) = v; } } -CAMLexport void caml_ephemeron_set_key(value ar, mlsize_t offset, value k) +static void clean_field (value e, mlsize_t offset) { - CAMLassert_valid_offset(ar, offset); - CAMLassert (Is_in_heap (ar)); - - offset += CAML_EPHE_FIRST_KEY; - do_check_key_clean(ar, offset); - do_set (ar, offset, k); + if (offset == CAML_EPHE_DATA_OFFSET) + caml_ephe_clean(e); + else + do_check_key_clean(e, offset); } -CAMLprim value caml_ephe_set_key (value ar, value n, value el) +static void do_set (value e, mlsize_t offset, value v) { - caml_ephemeron_set_key(ar, Long_val(n), el); - return Val_unit; + if (Is_block(v) && Is_young(v)) { + value old = Op_val(e)[offset]; + Op_val(e)[offset] = v; + if (!(Is_block(old) && Is_young(old))) + add_to_ephe_ref_table (&Caml_state->minor_tables->ephe_ref, + e, offset); + } else { + Op_val(e)[offset] = v; + } } -CAMLexport void caml_ephemeron_unset_key(value ar, mlsize_t offset) +static value ephe_set_field (value e, mlsize_t offset, value el) { - CAMLassert_valid_offset(ar, offset); - CAMLassert (Is_in_heap (ar)); - - offset += CAML_EPHE_FIRST_KEY; + CAMLparam2(e,el); - do_check_key_clean(ar, offset); - Field (ar, offset) = caml_ephe_none; + clean_field(e, offset); + do_set(e, offset, el); + CAMLreturn(Val_unit); } -CAMLprim value caml_ephe_unset_key (value ar, value n) +CAMLprim value caml_ephe_set_key (value e, value n, value el) { - caml_ephemeron_unset_key(ar, Long_val(n)); - return Val_unit; -} + mlsize_t offset = Long_val (n) + CAML_EPHE_FIRST_KEY; -/* deprecated (03/2016) */ -value caml_ephe_set_key_option (value ar, value n, value el) -{ - if (Is_block (el)){ - CAMLassert (Wosize_val (el) == 1); - caml_ephe_set_key(ar, n, Field (el, 0)); - }else{ - CAMLassert (el == None_val); - caml_ephe_unset_key(ar, n); + if (offset < CAML_EPHE_FIRST_KEY || offset >= Wosize_val (e)){ + caml_invalid_argument ("Weak.set"); } - return Val_unit; -} - -/* deprecated (03/2016) */ -CAMLprim value caml_weak_set (value ar, value n, value el) -{ - return caml_ephe_set_key_option(ar, n, el); + return ephe_set_field (e, offset, el); } -CAMLexport void caml_ephemeron_set_data (value ar, value el) +CAMLprim value caml_ephe_unset_key (value e, value n) { - CAMLassert_valid_ephemeron(ar); - - if (caml_gc_phase == Phase_clean){ - /* During this phase since we don't know which ephemerons have been - cleaned we always need to check it. */ - caml_ephe_clean(ar); - }; - do_set (ar, CAML_EPHE_DATA_OFFSET, el); + return caml_ephe_set_key (e, n, caml_ephe_none); } -CAMLprim value caml_ephe_set_data (value ar, value el) +value caml_ephe_set_key_option (value e, value n, value el) { - caml_ephemeron_set_data (ar, el); - return Val_unit; + if (el != None_val && Is_block (el)) { + return caml_ephe_set_key (e, n, Op_val(el)[0]); + } else { + return caml_ephe_unset_key (e, n); + } } -CAMLexport void caml_ephemeron_unset_data (value ar) +CAMLprim value caml_weak_set (value ar, value n, value el) { - CAMLassert_valid_ephemeron(ar); - - Field (ar, CAML_EPHE_DATA_OFFSET) = caml_ephe_none; + return caml_ephe_set_key_option(ar,n,el); } -CAMLprim value caml_ephe_unset_data (value ar) +CAMLprim value caml_ephe_set_data (value e, value el) { - caml_ephemeron_unset_data (ar); - return Val_unit; + return ephe_set_field (e, CAML_EPHE_DATA_OFFSET, el); } -static value optionalize(int status, value *x) +CAMLprim value caml_ephe_unset_data (value e) { - CAMLparam0(); - CAMLlocal2(res, v); - if(status) { - v = *x; - res = caml_alloc_small (1, Some_tag); - Field (res, 0) = v; - } else { - res = None_val; - } - // run memprof callbacks both for the option we are allocating here - // and the calling function. - caml_process_pending_actions(); - CAMLreturn(res); + return caml_ephe_set_data(e, caml_ephe_none); } -CAMLexport int caml_ephemeron_get_key (value ar, mlsize_t offset, value *key) +static value ephe_get_field (value e, mlsize_t offset) { - value elt; - CAMLassert_valid_offset(ar, offset); + CAMLparam1(e); + CAMLlocal2 (res, elt); - offset += CAML_EPHE_FIRST_KEY; + clean_field(e, offset); + elt = Op_val(e)[offset]; - if (is_ephe_key_none(ar, offset)){ - return 0; - }else{ - elt = Field (ar, offset); - if (caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(elt)){ - caml_darken (elt, NULL); - } - *key = elt; - CAMLassert_not_dead_value(elt); - return 1; + if (elt == caml_ephe_none) { + res = None_val; + } else { + elt = Op_val(e)[offset]; + caml_darken (0, elt, 0); + res = caml_alloc_shr (1, Some_tag); + caml_initialize_field(res, 0, elt); } + CAMLreturn (res); } -CAMLprim value caml_ephe_get_key (value ar, value n) +CAMLprim value caml_ephe_get_key (value e, value n) { - value data; - return optionalize(caml_ephemeron_get_key(ar, Long_val(n), &data), &data); + mlsize_t offset = Long_val (n) + CAML_EPHE_FIRST_KEY; + if (offset < CAML_EPHE_FIRST_KEY || offset >= Wosize_val (e)){ + caml_invalid_argument ("Weak.get"); + } + return ephe_get_field (e, offset); } CAMLprim value caml_weak_get (value ar, value n) @@ -324,254 +267,145 @@ CAMLprim value caml_weak_get (value ar, value n) return caml_ephe_get_key(ar, n); } -CAMLexport int caml_ephemeron_get_data (value ar, value *data) +static value ephe_get_field_copy (value e, mlsize_t offset) { - value elt; - CAMLassert_valid_ephemeron(ar); - - if(caml_gc_phase == Phase_clean) caml_ephe_clean(ar); - elt = Field (ar, CAML_EPHE_DATA_OFFSET); - if (elt == caml_ephe_none){ - return 0; - }else{ - if (caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(elt)){ - caml_darken (elt, NULL); - } - *data = elt; - CAMLassert_not_dead_value(elt); - return 1; - } -} + CAMLparam1 (e); + CAMLlocal2 (res, elt); + mlsize_t i; + value v; /* Caution: this is NOT a local root. */ + value f; -CAMLprim value caml_ephe_get_data (value ar) -{ - value data; - return optionalize(caml_ephemeron_get_data(ar, &data), &data); -} + clean_field(e, offset); + v = Op_val(e)[offset]; + if (v == caml_ephe_none) CAMLreturn (None_val); + /** Don't copy custom_block #7279 */ + if (Is_block(v) && //XXX KC: trunk includes Is_in_heap_or_young(v) && + Tag_val(v) != Custom_tag) { + elt = caml_alloc_shr (Wosize_val(v), Tag_val(v)); + clean_field(e, offset); + v = Op_val(e)[offset]; + if (v == caml_ephe_none) CAMLreturn (None_val); -Caml_inline void copy_value(value src, value dst) -{ - if (Tag_val (src) < No_scan_tag){ - mlsize_t i; - for (i = 0; i < Wosize_val (src); i++){ - value f = Field (src, i); - if (caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(f)){ - caml_darken (f, NULL); + if (Tag_val(v) < No_scan_tag) { + for (i = 0; i < Wosize_val(v); i++) { + f = Op_val(v)[i]; + caml_darken (0, f, 0); + Store_field(elt, i, f); } - caml_modify (&Field (dst, i), f); + } else { + memmove (Bp_val(elt), Bp_val(v), Bosize_val(v)); } - }else{ - memmove (Bp_val (dst), Bp_val (src), Bosize_val (src)); + } else { + Op_val(e)[offset] = elt = v; } + res = caml_alloc_shr (1, Some_tag); + caml_initialize_field(res, 0, elt); + CAMLreturn(res); } -CAMLexport int caml_ephemeron_get_key_copy(value ar, mlsize_t offset, - value *key) +CAMLprim value caml_ephe_get_key_copy (value e, value n) { - mlsize_t loop = 0; - CAMLparam1(ar); - value elt = Val_unit, v; /* Caution: they are NOT local roots. */ - CAMLassert_valid_offset(ar, offset); - - offset += CAML_EPHE_FIRST_KEY; - - while(1) { - if(is_ephe_key_none(ar, offset)) CAMLreturn(0); - v = Field (ar, offset); - /** Don't copy custom_block #7279 */ - if(!(Is_block (v) && Is_in_value_area(v) && Tag_val(v) != Custom_tag)) { - if ( caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(v) ){ - caml_darken (v, NULL); - }; - *key = v; - CAMLreturn(1); - } - if (elt != Val_unit && - Wosize_val(v) == Wosize_val(elt) && Tag_val(v) == Tag_val(elt)) { - /* The allocation may trigger a finaliser that change the tag - and size of the block. Therefore, in addition to checking - that the pointer is still alive, we have to check that it - still has the same tag and size. - */ - CAMLassert_not_dead_value(v); - copy_value(v, elt); - *key = elt; - CAMLreturn(1); - } - - CAMLassert(loop < 10); - if(8 == loop){ /** One minor gc must be enough */ - elt = Val_unit; - CAML_EV_COUNTER (EV_C_FORCE_MINOR_WEAK, 1); - caml_minor_collection (); - } else { - /* cases where loop is between 0 to 7 and where loop is equal to 9 */ - elt = caml_alloc (Wosize_val (v), Tag_val (v)); - /* The GC may erase, move or even change v during this call to - caml_alloc. */ - } - ++loop; + mlsize_t offset = Long_val (n) + CAML_EPHE_FIRST_KEY; + if (offset < CAML_EPHE_FIRST_KEY || offset >= Wosize_val (e)){ + caml_invalid_argument ("Weak.get"); } + return ephe_get_field_copy(e, offset); } -CAMLprim value caml_ephe_get_key_copy (value ar, value n) -{ - value key; - int status = caml_ephemeron_get_key_copy(ar, Long_val(n), &key); - return optionalize(status, &key); +CAMLprim value caml_weak_get_copy (value e, value n){ + return caml_ephe_get_key_copy(e,n); } -CAMLprim value caml_weak_get_copy (value ar, value n) +CAMLprim value caml_ephe_get_data (value e) { - return caml_ephe_get_key_copy(ar, n); + return ephe_get_field (e, CAML_EPHE_DATA_OFFSET); } -CAMLexport int caml_ephemeron_get_data_copy (value ar, value *data) +CAMLprim value caml_ephe_get_data_copy (value e) { - mlsize_t loop = 0; - CAMLparam1 (ar); - value elt = Val_unit, v; /* Caution: they are NOT local roots. */ - CAMLassert_valid_ephemeron(ar); - - while(1) { - if (caml_gc_phase == Phase_clean) caml_ephe_clean(ar); - v = Field (ar, CAML_EPHE_DATA_OFFSET); - if (v == caml_ephe_none) CAMLreturn(0); - /** Don't copy custom_block #7279 */ - if (!(Is_block (v) && Is_in_value_area(v) && Tag_val(v) != Custom_tag)) { - if ( caml_gc_phase == Phase_mark && Must_be_Marked_during_mark(v) ){ - caml_darken (v, NULL); - }; - *data = v; - CAMLreturn(1); - } - if (elt != Val_unit && - Wosize_val(v) == Wosize_val(elt) && Tag_val(v) == Tag_val(elt)) { - /** cf caml_ephemeron_get_key_copy */ - CAMLassert_not_dead_value(v); - copy_value(v, elt); - *data = elt; - CAMLreturn(1); - } - - CAMLassert(loop < 10); - if(8 == loop){ /** One minor gc must be enough */ - elt = Val_unit; - CAML_EV_COUNTER (EV_C_FORCE_MINOR_WEAK, 1); - caml_minor_collection (); - } else { - /* cases where loop is between 0 to 7 and where loop is equal to 9 */ - elt = caml_alloc (Wosize_val (v), Tag_val (v)); - /** cf caml_ephemeron_get_key_copy */ - } - ++loop; - } + return ephe_get_field_copy (e, CAML_EPHE_DATA_OFFSET); } - -CAMLprim value caml_ephe_get_data_copy (value ar) +static value ephe_check_field (value e, mlsize_t offset) { - value data; - int status = caml_ephemeron_get_data_copy(ar, &data); - return optionalize(status, &data); + CAMLparam1(e); + CAMLlocal1(v); + + clean_field(e, offset); + v = Op_val(e)[offset]; + CAMLreturn(Val_bool(v != caml_ephe_none)); } -CAMLexport int caml_ephemeron_key_is_set(value ar, mlsize_t offset) +CAMLprim value caml_ephe_check_key (value e, value n) { - CAMLassert_valid_offset(ar, offset); - - offset += CAML_EPHE_FIRST_KEY; - return !is_ephe_key_none(ar, offset); + mlsize_t offset = Long_val (n) + CAML_EPHE_FIRST_KEY; + if (offset < CAML_EPHE_FIRST_KEY || offset >= Wosize_val (e)){ + caml_invalid_argument ("Weak.check"); + } + return ephe_check_field (e, offset); } -CAMLprim value caml_ephe_check_key (value ar, value n) +CAMLprim value caml_weak_check (value e, value n) { - return Val_bool (caml_ephemeron_key_is_set(ar, Long_val(n))); + return caml_ephe_check_key(e,n); } -CAMLprim value caml_weak_check (value ar, value n) +CAMLprim value caml_ephe_check_data (value e) { - return caml_ephe_check_key(ar, n); + return ephe_check_field (e, CAML_EPHE_DATA_OFFSET); } -CAMLexport int caml_ephemeron_data_is_set (value ar) +static value ephe_blit_field (value es, mlsize_t offset_s, + value ed, mlsize_t offset_d, mlsize_t length) { - CAMLassert_valid_ephemeron(ar); + CAMLparam2(es,ed); + CAMLlocal1(ar); + long i; - if(caml_gc_phase == Phase_clean) caml_ephe_clean(ar); - return Field (ar, CAML_EPHE_DATA_OFFSET) != caml_ephe_none; -} + if (length == 0) CAMLreturn(Val_unit); -CAMLprim value caml_ephe_check_data (value ar) -{ - return Val_bool (caml_ephemeron_data_is_set(ar)); -} + caml_ephe_clean(es); + caml_ephe_clean(ed); -CAMLexport void caml_ephemeron_blit_key(value ars, mlsize_t offset_s, - value ard, mlsize_t offset_d, - mlsize_t length) -{ - intnat i; /** intnat because the second for-loop stops with i == -1 */ - if (length == 0) return; - CAMLassert_valid_offset(ars, offset_s); - CAMLassert_valid_offset(ard, offset_d); - CAMLassert(length <= Wosize_val(ars) - CAML_EPHE_FIRST_KEY); - CAMLassert(length <= Wosize_val(ard) - CAML_EPHE_FIRST_KEY); - CAMLassert(offset_s <= Wosize_val(ars) - CAML_EPHE_FIRST_KEY - length); - CAMLassert(offset_d <= Wosize_val(ard) - CAML_EPHE_FIRST_KEY - length); - - offset_s += CAML_EPHE_FIRST_KEY; - offset_d += CAML_EPHE_FIRST_KEY; - - if (caml_gc_phase == Phase_clean){ - caml_ephe_clean_partial(ars, offset_s, offset_s + length); - /* We don't need to clean the keys that are about to be overwritten, - except where cleaning them could result in releasing the data, - which can't happen if data is already released. */ - if (Field (ard, CAML_EPHE_DATA_OFFSET) != caml_ephe_none) - caml_ephe_clean_partial(ard, offset_d, offset_d + length); - } - if (offset_d < offset_s){ - for (i = 0; i < length; i++){ - do_set (ard, offset_d + i, Field (ars, offset_s + i)); + if (offset_d < offset_s) { + for (i = 0; i < length; i++) { + caml_darken(0, Op_val(es)[offset_s + i], 0); + do_set(ed, offset_d + i, Op_val(es)[offset_s + i]); } - }else{ - for (i = length - 1; i >= 0; i--){ - do_set (ard, offset_d + i, Field (ars, offset_s + i)); + } else { + for (i = length - 1; i >= 0; i--) { + caml_darken(0, Op_val(es)[offset_s + i], 0); + do_set(ed, offset_d + i, Op_val(es)[offset_s + i]); } } + CAMLreturn(Val_unit); } -CAMLprim value caml_ephe_blit_key (value ars, value ofs, - value ard, value ofd, value len) +CAMLprim value caml_ephe_blit_key (value es, value ofs, + value ed, value ofd, value len) { - if (Long_val(len) == 0) return Val_unit; + mlsize_t offset_s = Long_val (ofs) + CAML_EPHE_FIRST_KEY; + mlsize_t offset_d = Long_val (ofd) + CAML_EPHE_FIRST_KEY; + mlsize_t length = Long_val (len); - caml_ephemeron_blit_key(ars,Long_val(ofs),ard,Long_val(ofd),Long_val(len)); - return Val_unit; -} - -CAMLprim value caml_weak_blit (value ars, value ofs, - value ard, value ofd, value len) -{ - return caml_ephe_blit_key (ars, ofs, ard, ofd, len); + if (offset_s < CAML_EPHE_FIRST_KEY || offset_s + length > Wosize_val (es)){ + caml_invalid_argument ("Weak.blit"); + } + if (offset_d < CAML_EPHE_FIRST_KEY || offset_d + length > Wosize_val (ed)){ + caml_invalid_argument ("Weak.blit"); + } + return ephe_blit_field (es, offset_s, ed, offset_d, length); } -CAMLexport void caml_ephemeron_blit_data (value ars, value ard) +CAMLprim value caml_ephe_blit_data (value es, value ed) { - CAMLassert_valid_ephemeron(ars); - CAMLassert_valid_ephemeron(ard); - - if(caml_gc_phase == Phase_clean) { - caml_ephe_clean(ars); - caml_ephe_clean(ard); - }; - do_set (ard, CAML_EPHE_DATA_OFFSET, Field (ars, CAML_EPHE_DATA_OFFSET)); + return ephe_blit_field (es, CAML_EPHE_DATA_OFFSET, + ed, CAML_EPHE_DATA_OFFSET, 1); } -CAMLprim value caml_ephe_blit_data (value ars, value ard) +CAMLprim value caml_weak_blit (value es, value ofs, + value ed, value ofd, value len) { - caml_ephemeron_blit_data(ars, ard); - return Val_unit; + return caml_ephe_blit_key (es, ofs, ed, ofd, len); } diff --git a/runtime/win32.c b/runtime/win32.c index 948d03c3da..458f0312e4 100644 --- a/runtime/win32.c +++ b/runtime/win32.c @@ -230,7 +230,7 @@ void * caml_dlopen(wchar_t * libname, int for_execution, int global) int flags = (global ? FLEXDLL_RTLD_GLOBAL : 0); if (!for_execution) flags |= FLEXDLL_RTLD_NOEXEC; handle = flexdll_wdlopen(libname, flags); - if ((handle != NULL) && ((caml_verb_gc & 0x100) != 0)) { + if ((handle != NULL) && ((caml_params->verb_gc & 0x100) != 0)) { flexdll_dump_exports(handle); fflush(stdout); } diff --git a/stdlib/.depend b/stdlib/.depend index ffaa61937c..e3ca373eb2 100644 --- a/stdlib/.depend +++ b/stdlib/.depend @@ -148,6 +148,7 @@ camlinternalMod.cmo : \ stdlib__obj.cmi \ stdlib__nativeint.cmi \ camlinternalOO.cmi \ + camlinternalLazy.cmi \ stdlib__array.cmi \ camlinternalMod.cmi camlinternalMod.cmx : \ @@ -155,6 +156,7 @@ camlinternalMod.cmx : \ stdlib__obj.cmx \ stdlib__nativeint.cmx \ camlinternalOO.cmx \ + camlinternalLazy.cmx \ stdlib__array.cmx \ camlinternalMod.cmi camlinternalMod.cmi : \ @@ -200,6 +202,17 @@ stdlib__digest.cmx : \ stdlib__bytes.cmx \ stdlib__digest.cmi stdlib__digest.cmi : +stdlib__domain.cmo : \ + stdlib__obj.cmi \ + stdlib__int64.cmi \ + stdlib__atomic.cmi \ + stdlib__domain.cmi +stdlib__domain.cmx : \ + stdlib__obj.cmx \ + stdlib__int64.cmx \ + stdlib__atomic.cmx \ + stdlib__domain.cmi +stdlib__domain.cmi : stdlib__ephemeron.cmo : \ stdlib__sys.cmi \ stdlib__seq.cmi \ @@ -290,16 +303,13 @@ stdlib__gc.cmo : \ stdlib__sys.cmi \ stdlib__string.cmi \ stdlib__printf.cmi \ - stdlib__printexc.cmi \ stdlib__gc.cmi stdlib__gc.cmx : \ stdlib__sys.cmx \ stdlib__string.cmx \ stdlib__printf.cmx \ - stdlib__printexc.cmx \ stdlib__gc.cmi -stdlib__gc.cmi : \ - stdlib__printexc.cmi +stdlib__gc.cmi : stdlib__genlex.cmo : \ stdlib__string.cmi \ stdlib__stream.cmi \ diff --git a/stdlib/StdlibModules b/stdlib/StdlibModules index d21befe9d1..4cf9c0a9a8 100644 --- a/stdlib/StdlibModules +++ b/stdlib/StdlibModules @@ -38,7 +38,7 @@ STDLIB_MODS=\ printexc fun gc digest random hashtbl weak \ format scanf callback camlinternalOO oo camlinternalMod genlex ephemeron \ filename complex arrayLabels listLabels bytesLabels stringLabels moreLabels \ - stdLabels spacetime bigarray + stdLabels spacetime bigarray domain STDLIB_MODULES=\ $(foreach module, $(STDLIB_MODS), $(call add_stdlib_prefix,$(module))) diff --git a/stdlib/atomic.mli b/stdlib/atomic.mli index b66d576f01..08f3f8a219 100644 --- a/stdlib/atomic.mli +++ b/stdlib/atomic.mli @@ -27,7 +27,7 @@ import additional compatibility layers. *) (** An atomic (mutable) reference to a value of type ['a]. *) -type !'a t +type 'a t (** Create an atomic reference. *) val make : 'a -> 'a t diff --git a/stdlib/camlinternalAtomic.ml b/stdlib/camlinternalAtomic.ml index c738453301..50a786df99 100644 --- a/stdlib/camlinternalAtomic.ml +++ b/stdlib/camlinternalAtomic.ml @@ -1,49 +1,16 @@ -(**************************************************************************) -(* *) -(* OCaml *) -(* *) -(* Gabriel Scherer, projet Partout, INRIA Paris-Saclay *) -(* *) -(* Copyright 2020 Institut National de Recherche en Informatique et *) -(* en Automatique. *) -(* *) -(* All rights reserved. This file is distributed under the terms of *) -(* the GNU Lesser General Public License version 2.1, with the *) -(* special exception on linking described in the file LICENSE. *) -(* *) -(**************************************************************************) - (* CamlinternalAtomic is a dependency of Stdlib, so it is compiled with -nopervasives. *) -external ( == ) : 'a -> 'a -> bool = "%eq" -external ( + ) : int -> int -> int = "%addint" -external ignore : 'a -> unit = "%ignore" - -(* We are not reusing ('a ref) directly to make it easier to reason - about atomicity if we wish to: even in a sequential implementation, - signals and other asynchronous callbacks might break atomicity. *) -type 'a t = {mutable v: 'a} - -let make v = {v} -let get r = r.v -let set r v = r.v <- v +type 'a t -let exchange r v = - let cur = r.v in - r.v <- v; - cur - -let compare_and_set r seen v = - let cur = r.v in - if cur == seen then - (r.v <- v; true) - else - false - -let fetch_and_add r n = - let cur = r.v in - r.v <- (cur + n); - cur +(* Atomic is a dependency of Stdlib, so it is compiled with + -nopervasives. *) +external make : 'a -> 'a t = "%makemutable" +external get : 'a t -> 'a = "%atomic_load" +external exchange : 'a t -> 'a -> 'a = "%atomic_exchange" +external compare_and_set : 'a t -> 'a -> 'a -> bool = "%atomic_cas" +external fetch_and_add : int t -> int -> int = "%atomic_fetch_add" +external ignore : 'a -> unit = "%ignore" +let set r x = ignore (exchange r x) let incr r = ignore (fetch_and_add r 1) -let decr r = ignore (fetch_and_add r (-1)) +let decr r = ignore (fetch_and_add r (-1))
\ No newline at end of file diff --git a/stdlib/camlinternalAtomic.mli b/stdlib/camlinternalAtomic.mli index 3b9aab3c6f..f5eb36c42d 100644 --- a/stdlib/camlinternalAtomic.mli +++ b/stdlib/camlinternalAtomic.mli @@ -19,7 +19,7 @@ modules_before_stdlib used in stdlib/dune does not support the Stdlib__ prefix trick. *) -type !'a t +type 'a t val make : 'a -> 'a t val get : 'a t -> 'a val set : 'a t -> 'a -> unit diff --git a/stdlib/camlinternalLazy.ml b/stdlib/camlinternalLazy.ml index 8226ffda2e..441aed0ce9 100644 --- a/stdlib/camlinternalLazy.ml +++ b/stdlib/camlinternalLazy.ml @@ -19,47 +19,89 @@ type 'a t = 'a lazy_t exception Undefined -let raise_undefined = Obj.repr (fun () -> raise Undefined) +(* [update_tag blk old new] updates the tag [blk] from [old] to [new] using a + * CAS loop (in order to handle concurrent conflicts with the GC marking). + * Returns [true] if the update is successful. Return [false] if the tag of + * [blk] is not [old]. *) + +external update_tag : Obj.t -> int -> int -> bool = "caml_obj_update_tag" external make_forward : Obj.t -> Obj.t -> unit = "caml_obj_make_forward" -(* Assume [blk] is a block with tag lazy *) -let force_lazy_block (blk : 'arg lazy_t) = - let closure = (Obj.obj (Obj.field (Obj.repr blk) 0) : unit -> 'arg) in - Obj.set_field (Obj.repr blk) 0 raise_undefined; +external domain_self : unit -> int = "caml_ml_domain_id" + +(* Assumes [blk] is a block with tag forcing *) +let do_force_block blk = + let b = Obj.repr blk in + let closure = (Obj.obj (Obj.field b 0) : unit -> 'arg) in + Obj.set_field b 0 (Obj.repr (domain_self ())); try let result = closure () in - make_forward (Obj.repr blk) (Obj.repr result); + make_forward b (Obj.repr result); result with e -> - Obj.set_field (Obj.repr blk) 0 (Obj.repr (fun () -> raise e)); + Obj.set_field b 0 (Obj.repr (fun () -> raise e)); + assert (update_tag b Obj.forcing_tag Obj.lazy_tag); raise e - -(* Assume [blk] is a block with tag lazy *) -let force_val_lazy_block (blk : 'arg lazy_t) = - let closure = (Obj.obj (Obj.field (Obj.repr blk) 0) : unit -> 'arg) in - Obj.set_field (Obj.repr blk) 0 raise_undefined; +(* Assumes [blk] is a block with tag forcing *) +let do_force_val_block blk = + let b = Obj.repr blk in + let closure = (Obj.obj (Obj.field b 0) : unit -> 'arg) in + Obj.set_field b 0 (Obj.repr (domain_self ())); let result = closure () in - make_forward (Obj.repr blk) (Obj.repr result); + make_forward b (Obj.repr result); result +type status = Racy | Forcing + +(* Assumes [blk] is a block with tag lazy *) +let update_tag_forcing (blk : 'arg lazy_t) = + let b = Obj.repr blk in + if not (update_tag b Obj.lazy_tag Obj.forcing_tag) then + (* blk has tag either + + Obj.forcing_tag -- currently being forced by this domain or + another concurrent domain (or) + + Obj.forward_tag -- was being forced by another domain which has since + completed the evaluation and updated the lazy. *) + let forcing_domain_id : int = Obj.obj (Obj.field b 0) in + let my_domain_id = domain_self () in + (* XXX KC: Need a fence here to prevent the tag read from being reordered + * before reading the first field of [b] *) + if Obj.tag b = Obj.forcing_tag && forcing_domain_id = my_domain_id then + raise Undefined + else Racy + else Forcing -(* [force] is not used, since [Lazy.force] is declared as a primitive - whose code inlines the tag tests of its argument. This function is - here for the sake of completeness, and for debugging purpose. *) +let force_gen_lazy_block ~only_val blk = + match update_tag_forcing blk with + | Racy -> raise Undefined + | Forcing when only_val -> do_force_val_block blk + | Forcing -> do_force_block blk -let force (lzv : 'arg lazy_t) = +(* used in the %lazy_force primitive *) +let force_lazy_block blk = force_gen_lazy_block ~only_val:false blk + +let try_force_gen_lazy_block ~only_val blk = + match update_tag_forcing blk with + | Racy -> None + | Forcing when only_val -> Some (do_force_val_block blk) + | Forcing -> Some (do_force_block blk) + +(* [force_gen ~only_val:false] is not used, since [Lazy.force] is + declared as a primitive whose code inlines the tag tests of its + argument. This function is here for the sake of completeness, and + for debugging purpose. *) +let force_gen ~only_val (lzv : 'arg lazy_t) = let x = Obj.repr lzv in let t = Obj.tag x in if t = Obj.forward_tag then (Obj.obj (Obj.field x 0) : 'arg) else - if t <> Obj.lazy_tag then (Obj.obj x : 'arg) - else force_lazy_block lzv + if t <> Obj.lazy_tag && t <> Obj.forcing_tag then (Obj.obj x : 'arg) + else force_gen_lazy_block ~only_val lzv - -let force_val (lzv : 'arg lazy_t) = +let try_force_gen ~only_val (lzv : 'arg lazy_t) = let x = Obj.repr lzv in let t = Obj.tag x in - if t = Obj.forward_tag then (Obj.obj (Obj.field x 0) : 'arg) else - if t <> Obj.lazy_tag then (Obj.obj x : 'arg) - else force_val_lazy_block lzv + if t = Obj.forward_tag then Some (Obj.obj (Obj.field x 0) : 'arg) else + if t <> Obj.lazy_tag && t <> Obj.forcing_tag then Some (Obj.obj x : 'arg) + else try_force_gen_lazy_block ~only_val lzv diff --git a/stdlib/camlinternalLazy.mli b/stdlib/camlinternalLazy.mli index 7d04087f44..901d53683f 100644 --- a/stdlib/camlinternalLazy.mli +++ b/stdlib/camlinternalLazy.mli @@ -17,13 +17,12 @@ All functions in this module are for system use only, not for the casual user. *) -exception Undefined - type 'a t = 'a lazy_t +exception Undefined + val force_lazy_block : 'a lazy_t -> 'a -val force_val_lazy_block : 'a lazy_t -> 'a +val force_gen : only_val:bool -> 'a lazy_t -> 'a -val force : 'a lazy_t -> 'a -val force_val : 'a lazy_t -> 'a +val try_force_gen : only_val:bool -> 'a lazy_t -> 'a option diff --git a/stdlib/camlinternalMod.ml b/stdlib/camlinternalMod.ml index eb66d22607..05b2c22b45 100644 --- a/stdlib/camlinternalMod.ml +++ b/stdlib/camlinternalMod.ml @@ -72,7 +72,8 @@ let rec init_mod loc shape = overwrite_closure closure template; closure | Lazy -> - Obj.repr (lazy (raise (Undefined_recursive_module loc))) + Obj.repr (lazy (raise (Undefined_recursive_module loc)) + : _ CamlinternalLazy.t) | Class -> Obj.repr (CamlinternalOO.dummy_class loc) | Module comps -> diff --git a/stdlib/domain.ml b/stdlib/domain.ml new file mode 100644 index 0000000000..116cfa0af1 --- /dev/null +++ b/stdlib/domain.ml @@ -0,0 +1,163 @@ +module Raw = struct + (* Low-level primitives provided by the runtime *) + type t = private int + external critical_adjust : int -> unit + = "caml_ml_domain_critical_section" + external interrupt : t -> unit + = "caml_ml_domain_interrupt" + external wait : unit -> unit + = "caml_ml_domain_yield" + type timeout_or_notified = Timeout | Notified + external wait_until : int64 -> timeout_or_notified + = "caml_ml_domain_yield_until" + external spawn : (unit -> unit) -> t + = "caml_domain_spawn" + external self : unit -> t + = "caml_ml_domain_id" + external cpu_relax : unit -> unit + = "caml_ml_domain_cpu_relax" +end + +type nanoseconds = int64 +external timer_ticks : unit -> (int64 [@unboxed]) = + "caml_ml_domain_ticks" "caml_ml_domain_ticks_unboxed" [@@noalloc] + +module Sync = struct + exception Retry + let rec critical_section f = + Raw.critical_adjust (+1); + match f () with + | x -> Raw.critical_adjust (-1); x + | exception Retry -> Raw.critical_adjust (-1); Raw.cpu_relax (); critical_section f + | exception ex -> Raw.critical_adjust (-1); raise ex + + let notify d = Raw.interrupt d + let wait () = Raw.wait () + type timeout_or_notified = + Raw.timeout_or_notified = + Timeout | Notified + let wait_until t = Raw.wait_until t + let wait_for dt = Raw.wait_until (Int64.add (timer_ticks ()) dt) + let cpu_relax () = Raw.cpu_relax () + external poll : unit -> unit = "%poll" +end + +type id = Raw.t + +type 'a state = +| Running +| Joining of ('a, exn) result option ref * id +| Finished of ('a, exn) result +| Joined + +type 'a t = + { domain : Raw.t; state : 'a state Atomic.t } + +exception Retry +let rec spin f = + try f () with Retry -> + (* fixme: spin more gently *) + spin f + +let cas r vold vnew = + if not (Atomic.compare_and_set r vold vnew) then raise Retry + +let spawn f = + let state = Atomic.make Running in + let body () = + let result = match f () with + | x -> Ok x + | exception ex -> Error ex in + (* Begin a critical section that is ended by domain + termination *) + Raw.critical_adjust (+1); + spin (fun () -> + match Atomic.get state with + | Running -> + cas state Running (Finished result) + | Joining (r, d) as old -> + cas state old Joined; + r := Some result; + Raw.interrupt d + | Joined | Finished _ -> + failwith "internal error: I'm already finished?") in + { domain = Raw.spawn body; state } + +let join { domain ; state } = + let res = spin (fun () -> + match Atomic.get state with + | Running -> + let res = ref None in + cas state Running (Joining (res, Raw.self ())); + spin (fun () -> + Sync.critical_section (fun () -> + match !res with + | None -> Sync.wait (); raise Retry + | Some r -> r)) + | Finished res as old -> + cas state old Joined; + res + | Joining _ | Joined -> + raise (Invalid_argument "This domain has already been joined")) in + (* Wait until the domain has terminated. + The domain is in a critical section which will be + ended by the runtime when it terminates *) + Sync.notify domain; + match res with + | Ok x -> x + | Error ex -> raise ex + + +let get_id { domain; _ } = domain + +let self () = Raw.self () + +module DLS = struct + + type 'a key = int ref * (unit -> 'a) + + type entry = {key_id: int ref; mutable slot: Obj.t} + + external get_dls_list : unit -> entry list + = "caml_domain_dls_get" [@@noalloc] + + external set_dls_list : entry list -> unit + = "caml_domain_dls_set" [@@noalloc] + + let new_key f = (ref 0, f) + + let set k x = + let cs = Obj.repr x in + let vals = get_dls_list () in + let rec add_or_update_entry k v l = + match l with + | [] -> Some {key_id = k; slot = v} + | hd::tl -> + if (hd.key_id == k) then begin + hd.slot <- v; + None + end + else add_or_update_entry k v tl + in + let (key, _) = k in + match add_or_update_entry key cs vals with + | None -> () + | Some e -> set_dls_list (e::vals) + + let get k = + let rec search key_id init dls_list l = + match l with + | [] -> + begin + let slot = Obj.repr (init ()) in + set_dls_list ({key_id; slot}::dls_list); + slot + end + | hd::tl -> + if hd.key_id == key_id then hd.slot else search key_id init dls_list tl + in + let dls_list = get_dls_list () in + let (key_id, init) = k in + Obj.obj @@ search key_id init dls_list dls_list + +end diff --git a/stdlib/domain.mli b/stdlib/domain.mli new file mode 100644 index 0000000000..e8392580c4 --- /dev/null +++ b/stdlib/domain.mli @@ -0,0 +1,136 @@ +type 'a t +(** A domain of type ['a t] runs independently, eventually producing a + result of type 'a, or an exception *) + +val spawn : (unit -> 'a) -> 'a t +(** [spawn f] creates a new domain that runs in parallel with the + current domain. *) + +val join : 'a t -> 'a +(** [join d] blocks until domain [d] runs to completion. + If [d] results in a value, then that is returned by [join d]. + If [d] raises an uncaught exception, then that is thrown by [join d]. + Domains may only be joined once: subsequent uses of [join d] + raise Invalid_argument. *) + +type id = private int +(** Domains have unique integer identifiers *) + +val get_id : 'a t -> id + +val self : unit -> id +(** [self ()] is the identifier of the currently running domain *) + +type nanoseconds = int64 +val timer_ticks : unit -> nanoseconds +(** Returns the number of nanoseconds elapsed since the OCaml + runtime started. *) + +module Sync : sig + (** Low-level synchronisation primitives. + + The general usage pattern for these primitives is to test a + predicate of atomic variables in a critical section and call + [wait] if the predicate does not hold. The domain that causes + the predicate to become true must then call [notify]. + + For example, here one domain waits for another to complete work: + + let done = Atomic.make false + + let rec await_completion () = + let success = + critical_section (fun () -> + if Atomic.get done then true else (wait (); false)) in + if success then () else await_completion () + + let signal_completion waiting_domain = + Atomic.set success true; + notify waiting_domain + + Semantically, the primitives are similar to having a single + monitor (or mutex + condition variable) per domain. That is, + [critical_section f] acquires the current domain's mutex and + runs [f], [wait ()] waits on the current domain's condition + variable (releasing the mutex during the wait), and [notify d] + acquires domain [d]'s mutex and signals its condition variable. + The only difference from standard monitors is that [notify d] + waits for any in-progress critical section to complete. + + However, the actual implementation is somewhat different. In + particular, [critical_section f] is cheaper than acquiring a mutex, + and performs no more atomic operations than [f] does. *) + + exception Retry + + val critical_section : (unit -> 'a) -> 'a + (** [critical_section f] runs [f], but blocks notifications until + [f] returns. See [notify] below. + If [f] raises [Retry], then the critical section is restarted. *) + + val notify : id -> unit + (** If the domain [d] is within a critical section (i.e. is evaluating + [critical_section f]), then [notify d] marks this critical section + as "notified" (causing any call to [wait] to return, see below), + and waits for the critical section to complete before returning. + If [d] is not in a critical section, then [notify d] does nothing. *) + + + val wait : unit -> unit + (** [wait] must be called from within a critical section, and returns + only when that critical section is notified by a call to [notify]. + It does not matter whether [notify] is called before or after + [wait] begins: it is the critical section that is being notified, + not the call to wait. If wait is called and finds that the current + critical has already been notified, it returns immediately. + + Calling [wait ()] twice within the same critical section is not + useful: the first call to [wait ()] returns when the critical + section is notified, so the second call to [wait] will always + return immediately, as the critical section is already notified. *) + + type timeout_or_notified = Timeout | Notified + + val wait_for : nanoseconds -> timeout_or_notified + (** As with [wait], must be called from within a critical section. + Same as [wait], but returns once the specified number of + nanoseconds has elapsed, regardless of whether [notify] + is called *) + + val wait_until : nanoseconds -> timeout_or_notified + (** As with [wait] and [wait_for], must be called from within a critical section. + [wait_until t] is the same as [wait ()], but returns once + [timer_ticks () > t], regardless of whether [notify] is + called *) + + val cpu_relax : unit -> unit + (** If busy-waiting, calling cpu_relax () between iterations + will improve performance on some CPU architectures *) + + external poll : unit -> unit = "%poll" + (** poll for interrupts *) +end + +module DLS : sig +(** Domain-local Storage *) + + type 'a key + (** Type of a DLS key *) + + val new_key : (unit -> 'a) -> 'a key + (** [new_key f] returns a new key bound to initialiser [f] for accessing + domain-local variable. *) + + val set : 'a key -> 'a -> unit + (** [set k v] updates the calling domain's domain-local state to associate + the key [k] with value [v]. It overwrites any previous values associated + to [k], which cannot be restored later. [set] is an [O(n)] operation + where [n] is the number of keys set on the calling domain. *) + + val get : 'a key -> 'a + (** [get k] returns [v] if a value [v] is associated to the key [k] on + the calling domain's domain-local state. Sets [k]'s value with its + initialiser and returns it otherwise. [get] is an [O(n)] operation + where [n] is the number of keys set on the calling domain *) + + end diff --git a/stdlib/gc.ml b/stdlib/gc.ml index 75c13a3785..496cd24207 100644 --- a/stdlib/gc.ml +++ b/stdlib/gc.ml @@ -5,8 +5,8 @@ (* Damien Doligez, projet Para, INRIA Rocquencourt *) (* Jacques-Henri Jourdan, projet Gallium, INRIA Paris *) (* *) -(* Copyright 1996-2016 Institut National de Recherche en Informatique *) -(* et en Automatique. *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) (* *) (* All rights reserved. This file is distributed under the terms of *) (* the GNU Lesser General Public License version 2.1, with the *) @@ -60,10 +60,10 @@ 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" -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" +(* external get_minor_free : unit -> int = "caml_get_minor_free" *) +(* 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" *) external eventlog_pause : unit -> unit = "caml_eventlog_pause" external eventlog_resume : unit -> unit = "caml_eventlog_resume" @@ -98,12 +98,12 @@ let allocated_bytes () = let (mi, pro, ma) = counters () in (mi +. ma -. pro) *. float_of_int (Sys.word_size / 8) - external finalise : ('a -> unit) -> 'a -> unit = "caml_final_register" external finalise_last : (unit -> unit) -> 'a -> unit = "caml_final_register_called_without_value" external finalise_release : unit -> unit = "caml_final_release" +external promote_to : 'a -> 'b -> 'a = "caml_obj_promote_to" type alarm = bool ref type alarm_rec = {active : alarm; f : unit -> unit} @@ -122,40 +122,3 @@ let create_alarm f = let delete_alarm a = a := false - -module Memprof = - struct - type allocation = - { n_samples : int; - size : int; - unmarshalled : bool; - callstack : Printexc.raw_backtrace } - - type ('minor, 'major) tracker = { - alloc_minor: allocation -> 'minor option; - alloc_major: allocation -> 'major option; - promote: 'minor -> 'major option; - dealloc_minor: 'minor -> unit; - dealloc_major: 'major -> unit; - } - - let null_tracker = { - alloc_minor = (fun _ -> None); - alloc_major = (fun _ -> None); - promote = (fun _ -> None); - dealloc_minor = (fun _ -> ()); - dealloc_major = (fun _ -> ()); - } - - external c_start : - float -> int -> ('minor, 'major) tracker -> unit - = "caml_memprof_start" - - let start - ~sampling_rate - ?(callstack_size = max_int) - tracker = - c_start sampling_rate callstack_size tracker - - external stop : unit -> unit = "caml_memprof_stop" - end diff --git a/stdlib/gc.mli b/stdlib/gc.mli index 63f46cd95d..e5de4b04e9 100644 --- a/stdlib/gc.mli +++ b/stdlib/gc.mli @@ -5,8 +5,8 @@ (* Damien Doligez, projet Para, INRIA Rocquencourt *) (* Jacques-Henri Jourdan, projet Gallium, INRIA Paris *) (* *) -(* Copyright 1996-2016 Institut National de Recherche en Informatique *) -(* et en Automatique. *) +(* Copyright 1996 Institut National de Recherche en Informatique et *) +(* en Automatique. *) (* *) (* All rights reserved. This file is distributed under the terms of *) (* the GNU Lesser General Public License version 2.1, with the *) @@ -259,6 +259,8 @@ external minor_words : unit -> (float [@unboxed]) In native code this function does not allocate. + XXX KC: Only for the current domain. + @since 4.04 *) external get : unit -> control = "caml_gc_get" @@ -300,12 +302,13 @@ 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" +(* external get_minor_free : unit -> int = "caml_get_minor_free" *) + (** Return the current size of the free space inside the minor heap. @since 4.03.0 *) -external get_bucket : int -> int = "caml_get_major_bucket" [@@noalloc] +(* 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 @@ -313,14 +316,14 @@ external get_bucket : int -> int = "caml_get_major_bucket" [@@noalloc] @since 4.03.0 *) -external get_credit : unit -> int = "caml_get_major_credit" [@@noalloc] +(* 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. @since 4.03.0 *) -external huge_fallback_count : unit -> int = "caml_gc_huge_fallback_count" +(* 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 *) @@ -411,6 +414,12 @@ val finalise_release : unit -> unit GC that it can launch the next finalisation function without waiting for the current one to return. *) +external promote_to : 'a -> 'b -> 'a = "caml_obj_promote_to" +(** [promote_to a b] will promote [a] to become at least as shared as [b]. + This can improve performance: doing [promote_to msg queue] before + adding [msg] to the shared queue [queue] will ensure that no fault + occurs if another domain accesses [msg] via [queue] *) + type alarm (** An alarm is a piece of data that calls a user function at the end of each major GC cycle. The following functions are provided to create @@ -442,106 +451,3 @@ external eventlog_resume : unit -> unit = "caml_eventlog_resume" This call can be used after calling [eventlog_pause], or if the program was started with OCAML_EVENTLOG_ENABLED=p. (which pauses the collection of traces before the first event.) *) - - -(** [Memprof] is a sampling engine for allocated memory words. Every - allocated word has a probability of being sampled equal to a - configurable sampling rate. Once a block is sampled, it becomes - tracked. A tracked block triggers a user-defined callback as soon - as it is allocated, promoted or deallocated. - - Since blocks are composed of several words, a block can potentially - be sampled several times. If a block is sampled several times, then - each of the callback is called once for each event of this block: - the multiplicity is given in the [n_samples] field of the - [allocation] structure. - - This engine makes it possible to implement a low-overhead memory - profiler as an OCaml library. - - Note: this API is EXPERIMENTAL. It may change without prior - notice. *) -module Memprof : - sig - type allocation = private - { n_samples : int; - (** The number of samples in this block (>= 1). *) - - size : int; - (** The size of the block, in words, excluding the header. *) - - unmarshalled : bool; - (** Whether the block comes from unmarshalling. *) - - callstack : Printexc.raw_backtrace - (** The callstack for the allocation. *) - } - (** The type of metadata associated with allocations. This is the - type of records passed to the callback triggered by the - sampling of an allocation. *) - - type ('minor, 'major) tracker = { - alloc_minor: allocation -> 'minor option; - alloc_major: allocation -> 'major option; - promote: 'minor -> 'major option; - dealloc_minor: 'minor -> unit; - dealloc_major: 'major -> unit; - } - (** - A [('minor, 'major) tracker] describes how memprof should track - sampled blocks over their lifetime, keeping a user-defined piece - of metadata for each of them: ['minor] is the type of metadata - to keep for minor blocks, and ['major] the type of metadata - for major blocks. - - If an allocation-tracking or promotion-tracking function returns [None], - memprof stops tracking the corresponding value. - *) - - val null_tracker: ('minor, 'major) tracker - (** Default callbacks simply return [None] or [()] *) - - val start : - sampling_rate:float -> - ?callstack_size:int -> - ('minor, 'major) tracker -> - unit - (** Start the sampling with the given parameters. Fails if - sampling is already active. - - The parameter [sampling_rate] is the sampling rate in samples - per word (including headers). Usually, with cheap callbacks, a - rate of 1e-4 has no visible effect on performance, and 1e-3 - causes the program to run a few percent slower - - The parameter [callstack_size] is the length of the callstack - recorded at every sample. Its default is [max_int]. - - The parameter [tracker] determines how to track sampled blocks - over their lifetime in the minor and major heap. - - Sampling is temporarily disabled when calling a callback - for the current thread. So they do not need to be reentrant if - the program is single-threaded. However, if threads are used, - it is possible that a context switch occurs during a callback, - in this case the callback functions must be reentrant. - - Note that the callback can be postponed slightly after the - actual event. The callstack passed to the callback is always - accurate, but the program state may have evolved. - - Calling [Thread.exit] in a callback is currently unsafe and can - result in undefined behavior. *) - - val stop : unit -> unit - (** Stop the sampling. Fails if sampling is not active. - - This function does not allocate memory, but tries to run the - postponed callbacks for already allocated memory blocks (of - course, these callbacks may allocate). - - All the already tracked blocks are discarded. - - Calling [stop] when a callback is running can lead to - callbacks not being called even though some events happened. *) -end diff --git a/stdlib/lazy.ml b/stdlib/lazy.ml index 317f925cb0..c7adf7b7b0 100644 --- a/stdlib/lazy.ml +++ b/stdlib/lazy.ml @@ -55,9 +55,13 @@ external make_forward : 'a -> 'a lazy_t = "caml_lazy_make_forward" external force : 'a t -> 'a = "%lazy_force" -(* let force = force *) +(* let force l = CamlinternalLazy.force_gen ~only_val:false l *) -let force_val = CamlinternalLazy.force_val +let force_val l = CamlinternalLazy.force_gen ~only_val:true l + +let try_force l = CamlinternalLazy.try_force_gen ~only_val:false l + +let try_force_val l = CamlinternalLazy.try_force_gen ~only_val:true l let from_fun (f : unit -> 'arg) = let x = Obj.new_block Obj.lazy_tag 1 in diff --git a/stdlib/lazy.mli b/stdlib/lazy.mli index b71e21bb19..d331d31f19 100644 --- a/stdlib/lazy.mli +++ b/stdlib/lazy.mli @@ -42,8 +42,11 @@ type 'a t = 'a CamlinternalLazy.t for the [lazy] keyword. You should not use it directly. Always use [Lazy.t] instead. - Note: [Lazy.force] is not thread-safe. If you use this module in - a multi-threaded program, you will need to add some locks. + Note: [Lazy.force] (and therefore the [lazy] pattern-matching) are + thread-safe, but will raise the [Undefined] exception if forced + concurrently. If you need to share a lazy between threads, then you + need to use [Lazy.try_force] and implement your own synchronisation. + (@since XXX) Note: if the program is compiled with the [-rectypes] option, ill-founded recursive definitions of the form [let rec x = lazy x] @@ -64,19 +67,27 @@ external force : 'a t -> 'a = "%lazy_force" same value again without recomputing it. If it raised an exception, the same exception is raised again. @raise Undefined if the forcing of [x] tries to force [x] itself - recursively. + recursively, or if [x] is concurrently forced by another domain. *) +val try_force : 'a t -> 'a option +(** [try_force x] behaves similarly to [Some (force x)], except that + it returns immediately with [None] if [x] is already being forced + concurrently by another domain. *) + val force_val : 'a t -> 'a (** [force_val x] forces the suspension [x] and returns its result. If [x] has already been forced, [force_val x] returns the same value again without recomputing it. - - If the computation of [x] raises an exception, it is unspecified - whether [force_val x] raises the same exception or {!Undefined}. @raise Undefined if the forcing of [x] tries to force [x] itself - recursively. -*) + recursively, or if [x] is concurrently forced by another domain. + If the computation of [x] raises an exception, it is unspecified + whether [force_val x] raises the same exception or {!Undefined}. *) + +val try_force_val : 'a t -> 'a option +(** [try_force_val x] behaves similarly to [Some (force_val x)], + except that it returns immediately with [None] if [x] is already + being forced concurrently by another domain. *) val from_fun : (unit -> 'a) -> 'a t (** [from_fun f] is the same as [lazy (f ())] but slightly more efficient. diff --git a/stdlib/obj.ml b/stdlib/obj.ml index 926b33c832..f7ef1d32c3 100644 --- a/stdlib/obj.ml +++ b/stdlib/obj.ml @@ -30,6 +30,9 @@ external size : t -> int = "%obj_size" external reachable_words : t -> int = "caml_obj_reachable_words" external field : t -> int -> t = "%obj_field" external set_field : t -> int -> t -> unit = "%obj_set_field" +external compare_and_swap_field : t -> int -> t -> t -> bool + = "caml_obj_compare_and_swap" +external is_shared : t -> bool = "caml_obj_is_shared" external floatarray_get : floatarray -> int -> float = "caml_floatarray_get" external floatarray_set : floatarray -> int -> float -> unit = "caml_floatarray_set" @@ -52,8 +55,10 @@ let unmarshal str pos = (Marshal.from_bytes str pos, pos + Marshal.total_size str pos) let first_non_constant_constructor_tag = 0 -let last_non_constant_constructor_tag = 245 +let last_non_constant_constructor_tag = 243 +let forcing_tag = 244 +let cont_tag = 245 let lazy_tag = 246 let closure_tag = 247 let object_tag = 248 @@ -74,6 +79,9 @@ let int_tag = 1000 let out_of_heap_tag = 1001 let unaligned_tag = 1002 +external clone_continuation : ('a,'b) continuation -> ('a,'b) continuation = + "caml_clone_continuation" + module Closure = struct type info = { arity: int; diff --git a/stdlib/obj.mli b/stdlib/obj.mli index bf56b012df..7b58aa62dc 100644 --- a/stdlib/obj.mli +++ b/stdlib/obj.mli @@ -57,6 +57,9 @@ external field : t -> int -> t = "%obj_field" be propagated. *) external set_field : t -> int -> t -> unit = "%obj_set_field" +external compare_and_swap_field : t -> int -> t -> t -> bool + = "caml_obj_compare_and_swap" +external is_shared : t -> bool = "caml_obj_is_shared" external set_tag : t -> int -> unit = "caml_obj_set_tag" [@@ocaml.deprecated "Use with_tag instead."] @@ -82,6 +85,8 @@ external with_tag : int -> t -> t = "caml_obj_with_tag" val first_non_constant_constructor_tag : int val last_non_constant_constructor_tag : int +val forcing_tag : int +val cont_tag : int val lazy_tag : int val closure_tag : int val object_tag : int @@ -130,6 +135,9 @@ val marshal : t -> bytes val unmarshal : bytes -> int -> t * int [@@ocaml.deprecated "Use Marshal.from_bytes and Marshal.total_size instead."] +external clone_continuation : ('a,'b) continuation -> ('a,'b) continuation = + "caml_clone_continuation" + module Ephemeron: sig (** Ephemeron with arbitrary arity and untyped *) diff --git a/stdlib/printexc.ml b/stdlib/printexc.ml index 2b19b8cd55..3394df406e 100644 --- a/stdlib/printexc.ml +++ b/stdlib/printexc.ml @@ -273,6 +273,8 @@ let rec register_printer fn = external get_callstack: int -> raw_backtrace = "caml_get_current_callstack" +external get_continuation_callstack: ('a,'b) continuation -> int -> raw_backtrace = "caml_get_continuation_callstack" + let exn_slot x = let x = Obj.repr x in if Obj.tag x = 0 then Obj.field x 0 else x diff --git a/stdlib/printexc.mli b/stdlib/printexc.mli index cfedc097a9..2ddbcabe4b 100644 --- a/stdlib/printexc.mli +++ b/stdlib/printexc.mli @@ -190,6 +190,15 @@ external get_callstack: int -> raw_backtrace = "caml_get_current_callstack" @since 4.01.0 *) +(** {6 Continuations} *) + +val get_continuation_callstack: ('a,'b) continuation -> int -> raw_backtrace +(** [Printexc.get_continuation_callstack c n] returns a description of the top + of the call stack on the continuation [c], with at most [n] entries. (Note: + this function is not related to exceptions at all, despite being part of + the [Printexc] module.) +*) + (** {1 Uncaught exceptions} *) val default_uncaught_exception_handler: exn -> raw_backtrace -> unit diff --git a/stdlib/stdlib.ml b/stdlib/stdlib.ml index a3c58a080a..b85431724c 100644 --- a/stdlib/stdlib.ml +++ b/stdlib/stdlib.ml @@ -43,6 +43,24 @@ exception Division_by_zero = Division_by_zero exception Sys_blocked_io = Sys_blocked_io exception Undefined_recursive_module = Undefined_recursive_module +(* Effects *) + +type ('a, 'b) stack +external take_cont_noexc : ('a, 'b) continuation -> ('a, 'b) stack = "caml_continuation_use_noexc" [@@noalloc] +external resume : ('a, 'b) stack -> ('c -> 'a) -> 'c -> 'b = "%resume" + +let continue k v = + resume (take_cont_noexc k) (fun x -> x) v +let discontinue k e = + resume (take_cont_noexc k) (fun e -> raise e) e + +external perform : 'a eff -> 'a = "%perform" + +let reperform e k = + match perform e with + | v -> continue k v + | exception e -> discontinue k e + (* Composition operators *) external ( |> ) : 'a -> ('a -> 'b) -> 'b = "%revapply" @@ -542,6 +560,7 @@ let ( ^^ ) (Format (fmt1, str1)) (Format (fmt2, str2)) = (* Miscellaneous *) external sys_exit : int -> 'a = "caml_sys_exit" +external maybe_print_stats : unit -> unit = "caml_maybe_print_stats" let exit_function = CamlinternalAtomic.make flush_all @@ -559,8 +578,11 @@ let rec at_exit f = let do_at_exit () = (CamlinternalAtomic.get exit_function) () +external nop : unit -> unit = "%nop" + let exit retcode = do_at_exit (); + maybe_print_stats (); sys_exit retcode let _ = register_named_value "Pervasives.do_at_exit" do_at_exit @@ -579,6 +601,7 @@ module Callback = Callback module Char = Char module Complex = Complex module Digest = Digest +module Domain = Domain module Ephemeron = Ephemeron module Filename = Filename module Float = Float diff --git a/stdlib/stdlib.mli b/stdlib/stdlib.mli index efd5e9a974..1fab897d37 100644 --- a/stdlib/stdlib.mli +++ b/stdlib/stdlib.mli @@ -45,6 +45,39 @@ exception Exit (** The [Exit] exception is not raised by any library function. It is provided for use in your programs. *) +(** {6 Effects} *) + +(** [perform e] performs an effect [e]. + + @raises Unhandled if there is no active handler. *) +external perform : 'a eff -> 'a = "%perform" + +(** [continue k x] resumes the continuation [k] by passing [x] to [k]. + + @raise Invalid_argument if the continuation has already been + resumed. *) +val continue: ('a, 'b) continuation -> 'a -> 'b + +(** [discontinue k e] resumes the continuation [k] by raising the + exception [e] in [k]. + + @raise Invalid_argument if the continuation has already been + resumed. *) +val discontinue: ('a, 'b) continuation -> exn -> 'b + +(** [reperform e k] is semantically equivalent to: + + {[ + match perform e with + | v -> continue k v + | exception e -> discontinue k e + ]} + + but it can be implemented directly more efficiently and is a + very common case: it is what you should do with effects that + you don't handle. *) +val reperform: 'a eff -> ('a, 'b) continuation -> 'b + exception Match_failure of (string * int * int) [@ocaml.warn_on_literal_pattern] (** Exception raised when none of the cases of a pattern-matching @@ -1329,6 +1362,8 @@ val unsafe_really_input : in_channel -> bytes -> int -> int -> unit val do_at_exit : unit -> unit +external nop : unit -> unit = "%nop" + (**/**) (** {1:modules Standard library modules } *) @@ -1347,6 +1382,7 @@ module Callback = Callback module Char = Char module Complex = Complex module Digest = Digest +module Domain = Domain module Ephemeron = Ephemeron module Filename = Filename module Float = Float diff --git a/stdlib/weak.ml b/stdlib/weak.ml index 7816ffd46f..dd438d5170 100644 --- a/stdlib/weak.ml +++ b/stdlib/weak.ml @@ -19,13 +19,16 @@ type !'a t external create : int -> 'a t = "caml_weak_create" +(** number of additional values in a weak pointer + * - Link + * - Data *) +let additional_values = 2 (* CAML_EPHE_FIRST_KEY in weak.h *) + let create l = if not (0 <= l && l <= Obj.Ephemeron.max_ephe_length) then invalid_arg("Weak.create"); create l -(** number of additional values in a weak pointer *) -let additional_values = 2 let length x = Obj.size(Obj.repr x) - additional_values diff --git a/testsuite/Makefile b/testsuite/Makefile index 5cd2d6dfa9..b8ecc83568 100644 --- a/testsuite/Makefile +++ b/testsuite/Makefile @@ -92,6 +92,7 @@ default: @echo "Available targets:" @echo " all launch all tests" @echo " all-foo launch all tests beginning with foo" + @echo " all-enabled launch all enabled tests" @echo " parallel launch all tests using GNU parallel" @echo " parallel-foo launch all tests beginning with foo using \ GNU parallel" @@ -133,6 +134,16 @@ check-failstamp: exit 1; \ fi +.PHONY: all-enabled +all-enabled: lib tools + @sed -n 's/#.*//; /\//d; /./p' disabled > disabled-dirs + @ls tests | fgrep -v -f disabled-dirs | \ + while read LINE; do \ + $(MAKE) $(NO_PRINT) exec-one DIR=tests/$$LINE; \ + done 2>&1 | tee _log + @rm disabled-dirs + @$(MAKE) report + .PHONY: all-% all-%: lib tools @for dir in tests/$**; do \ @@ -277,6 +288,7 @@ tools: clean: @$(MAKE) -C lib clean @cd tools && $(MAKE) BASEDIR=$(BASEDIR) clean + @rm -f disabled-dirs $(FIND) . -name '*_ocamltest*' | xargs rm -rf rm -f $(failstamp) diff --git a/testsuite/disabled b/testsuite/disabled new file mode 100644 index 0000000000..aae04ff5d6 --- /dev/null +++ b/testsuite/disabled @@ -0,0 +1,66 @@ +# This file lists tests that are disabled. +# Disabled tests must have comments linking to a Github issue number. +# See https://github.com/ocamllabs/ocaml-multicore/issues/NNN + +# Either an entire directory or a specific file can be disabled here. +# If an entire directory is listed, those tests won't even be run. + +# These depend on marshalling of closures or Custom_tag objects (#75) +lib-marshal +tests/typing-objects/'Tests.ml' with 1 (expect) +tests/lib-dynlink-bytecode/'main.ml' with 1.1.1.1.1.1.1.1.1.1 (check-program-output) +tests/lib-dynlink-native/'main.ml' with 1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.2.1.1.1.1.1.1.1.1.1.1.1 (check-program-output) +tests/runtime-objects/'Tests.ml' with 1 (native) +tests/runtime-objects/'Tests.ml' with 2 (bytecode) + +# TODO: dynlink isn't 100% working in multicore +# (this test below fails on Linux with travis but we can not recreate locally) +tests/lib-dynlink-private/'test.ml' with 1.2.1.2.8.19.1 (run) + +# Obj.truncate is incompatible with multicore (ocaml/ocaml#1725) +tests/weak-ephe-final/'weaktest.ml' with 1 (native) +tests/weak-ephe-final/'weaktest.ml' with 2 (bytecode) + +# TODO: port the new Ephemeron C-api to multicore +# https://github.com/ocaml/ocaml/pull/676 +ephe-c-api + +# TODO: port stat-mem-prof +# https://github.com/ocaml/ocaml/pull/8634 +statmemprof + +# TODO: alloc async changes +# https://github.com/ocaml/ocaml/pull/8897 +tests/c-api/'alloc_async.ml' with 2 (bytecode) +tests/c-api/'alloc_async.ml' with 1 (native) + +# TODO: signal alloc changes +# https://github.com/ocaml/ocaml/pull/9027 +tests/callback/'signals_alloc.ml' with 1.1 (bytecode) +tests/callback/'signals_alloc.ml' with 1.2 (native) + +# TODO: not clear compatibility is sensible for multicore +compatibility + +# TODO: signal handling and tick thread missing from systhreads +lib-systhreads-todo + +# TODO: finaliser issue (#385) +tests/backtrace/'callstack.ml' with 1.1.2 (bytecode) +tests/backtrace/'callstack.ml' with 1.1.1 (native) + +# TODO: off-by-one error on MacOS+Clang (#408) +tests/lib-threads/'beat.ml' with 1.2 (native) +tests/lib-threads/'beat.ml' with 1.1 (bytecode) + +# ocamldebug is broken (#34) +tool-debugger + +# Uses obj.reachable_words whose definition in multicore isn't clear (think racy programs) +lib-obj + +# Uses caml_page_table_lookup() (<- Is_in_static_data ()) which is not available on multicore +tests/asmcomp/'is_static.ml' with 1.1 (native) + +# since promotion is based on minor heap size now, this test can no longer be correct +tests/promotion/bigrecmod.ml diff --git a/testsuite/summarize.awk b/testsuite/summarize.awk index 0b4a8c18f6..28e6eb865f 100644 --- a/testsuite/summarize.awk +++ b/testsuite/summarize.awk @@ -13,6 +13,15 @@ #* * #************************************************************************** +BEGIN { + while ((getline line < "disabled") > 0) { + gsub(/#.*/, "", line); + if (line) { + is_disabled[line] = 1; + } + } +} + function check() { if (!in_test){ printf("error at line %d: found test result without test start\n", NR); @@ -55,7 +64,13 @@ function record_fail() { check(); if (!(key in RESULTS) || RESULTS[key] == "s"){ if (!(key in RESULTS)) ++nresults; - RESULTS[key] = "f"; + testcase = sprintf ("%s/%s", curdir, curfile); + gsub(/[ \t]+$/, "", testcase); + if (is_disabled[testcase]) { + RESULTS[key] = "d"; + } else { + RESULTS[key] = "f"; + } } delete SKIPPED[curdir]; clear(); @@ -64,7 +79,13 @@ function record_fail() { function record_unexp() { if (!(key in RESULTS) || RESULTS[key] == "s"){ if (!(key in RESULTS)) ++nresults; - RESULTS[key] = "e"; + testcase = sprintf ("%s/%s", curdir, curfile); + gsub(/[ \t]+$/, "", testcase); + if (is_disabled[testcase]) { + RESULTS[key] = "d"; + } else { + RESULTS[key] = "e"; + } } delete SKIPPED[curdir]; clear(); @@ -162,6 +183,8 @@ END { }else if (r == "e"){ ++ unexped; unexp[unexpidx++] = key; + }else if (r == "d"){ + ++ ndisabled; }else if (r == "s"){ ++ skipped; curdir = DIRS[key]; @@ -177,6 +200,7 @@ END { ++ ignored; } } + printf("\n"); if (skipped != 0){ printf("\nList of skipped tests:\n"); @@ -199,11 +223,12 @@ END { printf(" %3d tests passed\n", passed); printf(" %3d tests skipped\n", skipped); printf(" %3d tests failed\n", failed); + printf(" %3d tests disabled\n", ndisabled); printf(" %3d tests not started (parent test skipped or failed)\n", ignored); printf(" %3d unexpected errors\n", unexped); printf(" %3d tests considered", nresults); - if (nresults != passed + skipped + ignored + failed + unexped){ + if (nresults != passed + skipped + ignored + failed + ndisabled + unexped){ printf (" (totals don't add up??)"); } printf ("\n"); diff --git a/testsuite/tests/asmcomp/run.ml b/testsuite/tests/asmcomp/run.ml new file mode 100644 index 0000000000..30f07dc55c --- /dev/null +++ b/testsuite/tests/asmcomp/run.ml @@ -0,0 +1,10 @@ +external run_prog : int -> int -> int -> unit = "run_prog" + +let arg n = + if n < Array.length Sys.argv then + int_of_string Sys.argv.(n) + else + 0 + +let () = run_prog (arg 1) (arg 2) (arg 3) + diff --git a/testsuite/tests/asmgen/catch-float.cmm b/testsuite/tests/asmgen/catch-float.cmm index 9d1d1683fe..0cf240ecf6 100644 --- a/testsuite/tests/asmgen/catch-float.cmm +++ b/testsuite/tests/asmgen/catch-float.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DFLOAT_CATCH -DFUN=catch_float main.c" +arguments = "-ccopt -DFLOAT_CATCH -ccopt -DFUN=catch_float main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/catch-multiple.cmm b/testsuite/tests/asmgen/catch-multiple.cmm index 1510fcea08..158704d813 100644 --- a/testsuite/tests/asmgen/catch-multiple.cmm +++ b/testsuite/tests/asmgen/catch-multiple.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DINT_INT -DFUN=catch_multiple main.c" +arguments = "-ccopt -DINT_INT -ccopt -DFUN=catch_multiple main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/catch-rec-deadhandler.cmm b/testsuite/tests/asmgen/catch-rec-deadhandler.cmm index 34dc8a26c5..39f63d48ba 100644 --- a/testsuite/tests/asmgen/catch-rec-deadhandler.cmm +++ b/testsuite/tests/asmgen/catch-rec-deadhandler.cmm @@ -1,7 +1,7 @@ (* TEST flags = "-dlive" files = "main.c" -arguments = "-DUNIT_INT -DFUN=catch_rec_deadhandler main.c" +arguments = "-ccopt -DUNIT_INT -ccopt -DFUN=catch_rec_deadhandler main.c" * asmgen ** run *** check-program-output diff --git a/testsuite/tests/asmgen/catch-rec.cmm b/testsuite/tests/asmgen/catch-rec.cmm index 17f9884a76..beb6542c51 100644 --- a/testsuite/tests/asmgen/catch-rec.cmm +++ b/testsuite/tests/asmgen/catch-rec.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DINT_INT -DFUN=catch_fact main.c" +arguments = "-ccopt -DINT_INT -ccopt -DFUN=catch_fact main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/catch-try-float.cmm b/testsuite/tests/asmgen/catch-try-float.cmm index 23287298ad..09bbcc3351 100644 --- a/testsuite/tests/asmgen/catch-try-float.cmm +++ b/testsuite/tests/asmgen/catch-try-float.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DFLOAT_CATCH -DFUN=catch_try_float main.c" +arguments = "-ccopt -DFLOAT_CATCH -ccopt -DFUN=catch_try_float main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/catch-try.cmm b/testsuite/tests/asmgen/catch-try.cmm index 7537c6564a..45ff2ccca9 100644 --- a/testsuite/tests/asmgen/catch-try.cmm +++ b/testsuite/tests/asmgen/catch-try.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DINT_INT -DFUN=catch_exit main.c" +arguments = "-ccopt -DINT_INT -ccopt -DFUN=catch_exit main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/checkbound.cmm b/testsuite/tests/asmgen/checkbound.cmm index 0b864d5b8c..5b248c1679 100644 --- a/testsuite/tests/asmgen/checkbound.cmm +++ b/testsuite/tests/asmgen/checkbound.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DCHECKBOUND main.c" +arguments = "-ccopt -DCHECKBOUND main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/even-odd-spill-float.cmm b/testsuite/tests/asmgen/even-odd-spill-float.cmm index 1603aa807d..f04d505ae9 100644 --- a/testsuite/tests/asmgen/even-odd-spill-float.cmm +++ b/testsuite/tests/asmgen/even-odd-spill-float.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DINT_FLOAT -DFUN=is_even main.c" +arguments = "-ccopt -DINT_FLOAT -ccopt -DFUN=is_even main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/even-odd-spill.cmm b/testsuite/tests/asmgen/even-odd-spill.cmm index f0b9a70faa..7bc813e75e 100644 --- a/testsuite/tests/asmgen/even-odd-spill.cmm +++ b/testsuite/tests/asmgen/even-odd-spill.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DINT_INT -DFUN=is_even main.c" +arguments = "-ccopt -DINT_INT -ccopt -DFUN=is_even main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/even-odd.cmm b/testsuite/tests/asmgen/even-odd.cmm index adf0d0b828..793b65a507 100644 --- a/testsuite/tests/asmgen/even-odd.cmm +++ b/testsuite/tests/asmgen/even-odd.cmm @@ -1,6 +1,6 @@ (* TEST files= "main.c" -arguments = "-DINT_INT -DFUN=is_even main.c" +arguments = "-ccopt -DINT_INT -ccopt -DFUN=is_even main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/fib.cmm b/testsuite/tests/asmgen/fib.cmm index c1a82de268..778edf7e58 100644 --- a/testsuite/tests/asmgen/fib.cmm +++ b/testsuite/tests/asmgen/fib.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DINT_INT -DFUN=fib main.c" +arguments = "-ccopt -DINT_INT -ccopt -DFUN=fib main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/integr.cmm b/testsuite/tests/asmgen/integr.cmm index 84a3895c24..891e5a6138 100644 --- a/testsuite/tests/asmgen/integr.cmm +++ b/testsuite/tests/asmgen/integr.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DINT_FLOAT -DFUN=test main.c" +arguments = "-ccopt -DINT_FLOAT -ccopt -DFUN=test main.c" * skip reason = "This test is currently broken" ** asmgen diff --git a/testsuite/tests/asmgen/main.c b/testsuite/tests/asmgen/main.c index 103e022baf..93f23e053f 100644 --- a/testsuite/tests/asmgen/main.c +++ b/testsuite/tests/asmgen/main.c @@ -17,12 +17,7 @@ #include <stdio.h> #include <stdlib.h> #include <time.h> - -void caml_ml_array_bound_error(void) -{ - fprintf(stderr, "Fatal error: out-of-bound access in array or string\n"); - exit(2); -} +#include <caml/mlvalues.h> void print_string(char * s) { @@ -57,28 +52,28 @@ int cmpint(const void * i, const void * j) #endif -int main(int argc, char **argv) +CAMLprim value run_prog(value varg1, value varg2, value varg3) { + long arg1 = Long_val(varg1); + long arg2 = Long_val(varg2); + long arg3 = Long_val(varg3); + if (arg1+arg2+arg3) {}; /* squash unused var warnings */ #ifdef UNIT_INT { extern long FUN(void); extern long call_gen_code(long (*)(void)); printf("%ld\n", call_gen_code(FUN)); } #else - if (argc < 2) { - fprintf(stderr, "Usage: %s [int arg]\n", argv[0]); - exit(2); - } #ifdef INT_INT { extern long FUN(long); extern long call_gen_code(long (*)(long), long); - printf("%ld\n", call_gen_code(FUN, atoi(argv[1]))); + printf("%ld\n", call_gen_code(FUN, arg1)); } #endif #ifdef INT_FLOAT { extern double FUN(long); extern double call_gen_code(double (*)(long), long); - printf("%f\n", call_gen_code(FUN, atoi(argv[1]))); + printf("%f\n", call_gen_code(FUN, arg1)); } #endif #ifdef FLOAT_CATCH @@ -96,8 +91,8 @@ int main(int argc, char **argv) long * a, * b; long i; - srand(argc >= 3 ? atoi(argv[2]) : time((time_t *) 0)); - n = atoi(argv[1]); + srand(arg2 ? arg2 : time(0)); + n = arg1; a = (long *) malloc(n * sizeof(long)); for (i = 0 ; i < n; i++) a[i] = rand() & 0xFFF; #ifdef DEBUG @@ -121,9 +116,9 @@ int main(int argc, char **argv) { extern void checkbound1(long), checkbound2(long, long); extern void call_gen_code(void *, ...); long x, y; - x = atoi(argv[1]); - if (argc >= 3) { - y = atoi(argv[2]); + x = arg1; + if (arg2) { + y = arg2; if ((unsigned long) x < (unsigned long) y) printf("Should not trap\n"); else @@ -139,5 +134,5 @@ int main(int argc, char **argv) printf("OK\n"); } #endif - return 0; + return Val_unit; } diff --git a/testsuite/tests/asmgen/pgcd.cmm b/testsuite/tests/asmgen/pgcd.cmm index 3bd067c8bc..cd91e79880 100644 --- a/testsuite/tests/asmgen/pgcd.cmm +++ b/testsuite/tests/asmgen/pgcd.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DINT_INT -DFUN=pgcd_30030 main.c" +arguments = "-ccopt -DINT_INT -ccopt -DFUN=pgcd_30030 main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/quicksort.cmm b/testsuite/tests/asmgen/quicksort.cmm index 5ac97a4128..717330f1f9 100644 --- a/testsuite/tests/asmgen/quicksort.cmm +++ b/testsuite/tests/asmgen/quicksort.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DSORT -DFUN=quicksort main.c" +arguments = "-ccopt -DSORT -ccopt -DFUN=quicksort main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/quicksort2.cmm b/testsuite/tests/asmgen/quicksort2.cmm index b5822eca34..e672484b3d 100644 --- a/testsuite/tests/asmgen/quicksort2.cmm +++ b/testsuite/tests/asmgen/quicksort2.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DSORT -DFUN=quicksort main.c" +arguments = "-ccopt -DSORT -ccopt -DFUN=quicksort main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/soli.cmm b/testsuite/tests/asmgen/soli.cmm index e80381f0cd..d41de3cecf 100644 --- a/testsuite/tests/asmgen/soli.cmm +++ b/testsuite/tests/asmgen/soli.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DUNIT_INT -DFUN=solitaire main.c" +arguments = "-ccopt -DUNIT_INT -ccopt -DFUN=solitaire main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/tagged-fib.cmm b/testsuite/tests/asmgen/tagged-fib.cmm index b9b96152de..270e46a88f 100644 --- a/testsuite/tests/asmgen/tagged-fib.cmm +++ b/testsuite/tests/asmgen/tagged-fib.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DINT_INT -DFUN=fib main.c" +arguments = "-ccopt -DINT_INT -ccopt -DFUN=fib main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/tagged-integr.cmm b/testsuite/tests/asmgen/tagged-integr.cmm index 8903405f6a..4f782f1681 100644 --- a/testsuite/tests/asmgen/tagged-integr.cmm +++ b/testsuite/tests/asmgen/tagged-integr.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DINT_FLOAT -DFUN=test main.c" +arguments = "-ccopt -DINT_FLOAT -ccopt -DFUN=test main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/tagged-quicksort.cmm b/testsuite/tests/asmgen/tagged-quicksort.cmm index 631dd6aa1a..f0cdfba888 100644 --- a/testsuite/tests/asmgen/tagged-quicksort.cmm +++ b/testsuite/tests/asmgen/tagged-quicksort.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DSORT -DFUN=quicksort main.c" +arguments = "-ccopt -DSORT -ccopt -DFUN=quicksort main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/tagged-tak.cmm b/testsuite/tests/asmgen/tagged-tak.cmm index 3ff6ea4f2e..cbec4ca5e8 100644 --- a/testsuite/tests/asmgen/tagged-tak.cmm +++ b/testsuite/tests/asmgen/tagged-tak.cmm @@ -1,6 +1,6 @@ (* TEST files = "main.c" -arguments = "-DUNIT_INT -DFUN=takmain main.c" +arguments = "-ccopt -DUNIT_INT -ccopt -DFUN=takmain main.c" * asmgen *) diff --git a/testsuite/tests/asmgen/tak.cmm b/testsuite/tests/asmgen/tak.cmm index 1835ef66a5..66125c8a2a 100644 --- a/testsuite/tests/asmgen/tak.cmm +++ b/testsuite/tests/asmgen/tak.cmm @@ -1,8 +1,7 @@ (* TEST files = "main.c" -arguments = "-DUNIT_INT -DFUN=takmain main.c" -* asmgen -*) +arguments = "-ccopt -DUNIT_INT -ccopt -DFUN=takmain main.c" +* asmgen*) (**************************************************************************) (* *) diff --git a/testsuite/tests/backtrace/backtrace2.ml b/testsuite/tests/backtrace/backtrace2.ml index 747969a48f..f779119766 100644 --- a/testsuite/tests/backtrace/backtrace2.ml +++ b/testsuite/tests/backtrace/backtrace2.ml @@ -1,6 +1,7 @@ (* TEST flags = "-g" ocamlrunparam += ",b=1" + compare_programs = "false" *) (* A test for stack backtraces *) diff --git a/testsuite/tests/backtrace/backtrace2.reference b/testsuite/tests/backtrace/backtrace2.reference index 8f9c77dc83..f5f3ebecf8 100644 --- a/testsuite/tests/backtrace/backtrace2.reference +++ b/testsuite/tests/backtrace/backtrace2.reference @@ -2,57 +2,57 @@ a No exception b Uncaught exception Backtrace2.Error("b") -Raised at Backtrace2.test_Error.f in file "backtrace2.ml", line 12, characters 18-34 -Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 12, characters 44-55 -Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 12, characters 44-55 -Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 12, characters 44-55 -Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 12, characters 44-55 -Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 12, characters 44-55 -Called from Backtrace2.test_Error in file "backtrace2.ml", line 17, characters 4-11 -Re-raised at Backtrace2.test_Error in file "backtrace2.ml", line 19, characters 62-71 -Called from Backtrace2.run in file "backtrace2.ml", line 62, characters 11-23 +Raised at Backtrace2.test_Error.f in file "backtrace2.ml", line 13, characters 18-34 +Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 13, characters 44-55 +Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 13, characters 44-55 +Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 13, characters 44-55 +Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 13, characters 44-55 +Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 13, characters 44-55 +Called from Backtrace2.test_Error in file "backtrace2.ml", line 18, characters 4-11 +Re-raised at Backtrace2.test_Error in file "backtrace2.ml", line 20, characters 62-71 +Called from Backtrace2.run in file "backtrace2.ml", line 63, characters 11-23 Uncaught exception Backtrace2.Error("c") -Raised at Backtrace2.test_Error in file "backtrace2.ml", line 20, characters 20-37 -Called from Backtrace2.run in file "backtrace2.ml", line 62, characters 11-23 +Raised at Backtrace2.test_Error in file "backtrace2.ml", line 21, characters 20-37 +Called from Backtrace2.run in file "backtrace2.ml", line 63, characters 11-23 Uncaught exception Backtrace2.Error("d") -Raised at Backtrace2.test_Error.f in file "backtrace2.ml", line 12, characters 18-34 -Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 12, characters 44-55 -Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 12, characters 44-55 -Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 12, characters 44-55 -Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 12, characters 44-55 -Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 12, characters 44-55 -Called from Backtrace2.test_Error in file "backtrace2.ml", line 17, characters 4-11 -Called from Backtrace2.run in file "backtrace2.ml", line 62, characters 11-23 +Raised at Backtrace2.test_Error.f in file "backtrace2.ml", line 13, characters 18-34 +Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 13, characters 44-55 +Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 13, characters 44-55 +Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 13, characters 44-55 +Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 13, characters 44-55 +Called from Backtrace2.test_Error.f in file "backtrace2.ml", line 13, characters 44-55 +Called from Backtrace2.test_Error in file "backtrace2.ml", line 18, characters 4-11 +Called from Backtrace2.run in file "backtrace2.ml", line 63, characters 11-23 e Uncaught exception Backtrace2.Error("e") -Raised at Backtrace2.test_Error in file "backtrace2.ml", line 26, characters 50-59 -Called from Backtrace2.run in file "backtrace2.ml", line 62, characters 11-23 +Raised at Backtrace2.test_Error in file "backtrace2.ml", line 27, characters 50-59 +Called from Backtrace2.run in file "backtrace2.ml", line 63, characters 11-23 f Uncaught exception Backtrace2.Error("f") -Raised at Backtrace2.test_Error in file "backtrace2.ml", line 32, characters 62-71 -Called from Backtrace2.run in file "backtrace2.ml", line 62, characters 11-23 +Raised at Backtrace2.test_Error in file "backtrace2.ml", line 33, characters 62-71 +Called from Backtrace2.run in file "backtrace2.ml", line 63, characters 11-23 Uncaught exception Invalid_argument("index out of bounds") -Raised by primitive operation at Backtrace2.run in file "backtrace2.ml", line 62, characters 14-22 +Raised by primitive operation at Backtrace2.run in file "backtrace2.ml", line 63, characters 14-22 test_Not_found Uncaught exception Not_found Raised at Stdlib__hashtbl.find in file "hashtbl.ml", line 538, characters 13-28 -Called from Backtrace2.test_Not_found in file "backtrace2.ml", line 43, characters 9-42 -Re-raised at Backtrace2.test_Not_found in file "backtrace2.ml", line 43, characters 61-70 -Called from Backtrace2.run in file "backtrace2.ml", line 62, characters 11-23 +Called from Backtrace2.test_Not_found in file "backtrace2.ml", line 44, characters 9-42 +Re-raised at Backtrace2.test_Not_found in file "backtrace2.ml", line 44, characters 61-70 +Called from Backtrace2.run in file "backtrace2.ml", line 63, characters 11-23 Uncaught exception Not_found -Raised at Backtrace2.test_lazy.aux in file "backtrace2.ml", line 47, characters 18-33 -Called from Backtrace2.test_lazy.aux in file "backtrace2.ml", line 47, characters 43-52 -Called from Backtrace2.test_lazy.aux in file "backtrace2.ml", line 47, characters 43-52 -Called from Backtrace2.test_lazy.aux in file "backtrace2.ml", line 47, characters 43-52 -Called from Backtrace2.test_lazy.aux in file "backtrace2.ml", line 47, characters 43-52 -Called from Backtrace2.test_lazy.aux in file "backtrace2.ml", line 47, characters 43-52 -Called from CamlinternalLazy.force_lazy_block in file "camlinternalLazy.ml", line 31, characters 17-27 -Re-raised at CamlinternalLazy.force_lazy_block in file "camlinternalLazy.ml", line 36, characters 4-11 -Called from Backtrace2.run in file "backtrace2.ml", line 62, characters 11-23 +Raised at Backtrace2.test_lazy.aux in file "backtrace2.ml", line 48, characters 18-33 +Called from Backtrace2.test_lazy.aux in file "backtrace2.ml", line 48, characters 43-52 +Called from Backtrace2.test_lazy.aux in file "backtrace2.ml", line 48, characters 43-52 +Called from Backtrace2.test_lazy.aux in file "backtrace2.ml", line 48, characters 43-52 +Called from Backtrace2.test_lazy.aux in file "backtrace2.ml", line 48, characters 43-52 +Called from Backtrace2.test_lazy.aux in file "backtrace2.ml", line 48, characters 43-52 +Called from CamlinternalLazy.do_force_block in file "camlinternalLazy.ml", line 39, characters 17-27 +Re-raised at CamlinternalLazy.do_force_block in file "camlinternalLazy.ml", line 45, characters 4-11 +Called from Backtrace2.run in file "backtrace2.ml", line 63, characters 11-23 Uncaught exception Not_found Raised at Stdlib__hashtbl.find in file "hashtbl.ml", line 538, characters 13-28 -Called from Backtrace2.test_lazy.exception_raised_internally in file "backtrace2.ml", line 50, characters 8-41 -Re-raised at CamlinternalLazy.force_lazy_block.(fun) in file "camlinternalLazy.ml", line 35, characters 56-63 -Called from CamlinternalLazy.force_lazy_block in file "camlinternalLazy.ml", line 31, characters 17-27 -Re-raised at CamlinternalLazy.force_lazy_block in file "camlinternalLazy.ml", line 36, characters 4-11 -Called from Backtrace2.run in file "backtrace2.ml", line 62, characters 11-23 +Called from Backtrace2.test_lazy.exception_raised_internally in file "backtrace2.ml", line 51, characters 8-41 +Re-raised at CamlinternalLazy.do_force_block.(fun) in file "camlinternalLazy.ml", line 43, characters 43-50 +Called from CamlinternalLazy.do_force_block in file "camlinternalLazy.ml", line 39, characters 17-27 +Re-raised at CamlinternalLazy.do_force_block in file "camlinternalLazy.ml", line 45, characters 4-11 +Called from Backtrace2.run in file "backtrace2.ml", line 63, characters 11-23 diff --git a/testsuite/tests/backtrace/backtrace_effects.byte.reference b/testsuite/tests/backtrace/backtrace_effects.byte.reference new file mode 100644 index 0000000000..c59bd5d723 --- /dev/null +++ b/testsuite/tests/backtrace/backtrace_effects.byte.reference @@ -0,0 +1,11 @@ +(** get_callstack **) +Raised by primitive operation at file "backtrace_effects.ml", line 9, characters 13-39 +Called from file "backtrace_effects.ml", line 16, characters 12-17 +Called from file "backtrace_effects.ml", line 28, characters 8-14 +(** get_continuation_callstack **) +Raised by primitive operation at file "backtrace_effects.ml", line 11, characters 4-13 +Called from file "backtrace_effects.ml", line 16, characters 12-17 +(** raise **) +Fatal error: exception Pervasives.Exit +Raised at file "backtrace_effects.ml", line 6, characters 10-14 +Called from file "backtrace_effects.ml", line 28, characters 8-14 diff --git a/testsuite/tests/backtrace/backtrace_effects.ml b/testsuite/tests/backtrace/backtrace_effects.ml new file mode 100644 index 0000000000..8d09c8fb5c --- /dev/null +++ b/testsuite/tests/backtrace/backtrace_effects.ml @@ -0,0 +1,28 @@ +effect E : unit + +let bar i = + if i < 0 then begin + print_endline "(** raise **)"; + raise Exit + end else begin + print_endline "(** get_callstack **)"; + let bt = Printexc.get_callstack 100 in + print_string @@ Printexc.raw_backtrace_to_string bt; + perform E; + 20 + end + +let foo i = + ignore @@ bar i; + bar (-1) + +let baz () = + match foo 10 with + | x -> () + | effect E k -> + print_endline "(** get_continuation_callstack **)"; + let bt = Printexc.get_continuation_callstack k 100 in + print_string @@ Printexc.raw_backtrace_to_string bt; + continue k () + +let _ = baz () diff --git a/testsuite/tests/backtrace/backtrace_effects.native.reference b/testsuite/tests/backtrace/backtrace_effects.native.reference new file mode 100644 index 0000000000..71e9203217 --- /dev/null +++ b/testsuite/tests/backtrace/backtrace_effects.native.reference @@ -0,0 +1,11 @@ +(** get_callstack **) +Raised by primitive operation at file "backtrace_effects.ml", line 9, characters 13-39 +Called from file "backtrace_effects.ml", line 16, characters 12-17 +Called from file "backtrace_effects.ml", line 28, characters 8-14 +(** get_continuation_callstack **) +Raised by primitive operation at file "backtrace_effects.ml", line 11, characters 4-13 +Called from file "backtrace_effects.ml", line 16, characters 12-17 +(** raise **) +Fatal error: exception Pervasives.Exit +Raised at file "backtrace_effects.ml", line 6, characters 4-14 +Called from file "backtrace_effects.ml", line 28, characters 8-14 diff --git a/testsuite/tests/backtrace/backtrace_effects.reference b/testsuite/tests/backtrace/backtrace_effects.reference new file mode 100644 index 0000000000..70382de5fc --- /dev/null +++ b/testsuite/tests/backtrace/backtrace_effects.reference @@ -0,0 +1,11 @@ +(** get_callstack **) +Raised by primitive operation at file "backtrace_effects.ml", line 9, characters 13-39 +Called from file "backtrace_effects.ml", line 16, characters 12-17 +Called from file "backtrace_effects.ml", line 28, characters 8-14 +(** get_continuation_callstack **) +Raised by primitive operation at file "backtrace_effects.ml", line 11, characters 12-13 +Called from file "backtrace_effects.ml", line 16, characters 12-17 +(** raise **) +Fatal error: exception Pervasives.Exit +Raised at file "backtrace_effects.ml", line 6, characters 10-14 +Called from file "backtrace_effects.ml", line 28, characters 8-14 diff --git a/testsuite/tests/backtrace/backtrace_effects_nested.byte.reference b/testsuite/tests/backtrace/backtrace_effects_nested.byte.reference new file mode 100644 index 0000000000..ff66bf82ef --- /dev/null +++ b/testsuite/tests/backtrace/backtrace_effects_nested.byte.reference @@ -0,0 +1,3 @@ +Raised by primitive operation at file "backtrace_effects_nested.ml", line 6, characters 2-11 +Called from file "backtrace_effects_nested.ml", line 15, characters 26-39 +43 diff --git a/testsuite/tests/backtrace/backtrace_effects_nested.ml b/testsuite/tests/backtrace/backtrace_effects_nested.ml new file mode 100644 index 0000000000..e92b827714 --- /dev/null +++ b/testsuite/tests/backtrace/backtrace_effects_nested.ml @@ -0,0 +1,24 @@ +effect E : unit +effect Inc : unit + +let blorp () = + perform Inc; + perform E; + 42 + + +let baz () = + match + blorp () + with + | x -> x + | effect Inc k -> 1 + continue k () + +let f () = + match baz () with + | x -> Printf.printf "%d\n" x + | effect E k -> + Printexc.(get_continuation_callstack k 100 |> raw_backtrace_to_string |> print_string); + continue k () + +let () = f () diff --git a/testsuite/tests/backtrace/backtrace_effects_nested.native.reference b/testsuite/tests/backtrace/backtrace_effects_nested.native.reference new file mode 100644 index 0000000000..ff66bf82ef --- /dev/null +++ b/testsuite/tests/backtrace/backtrace_effects_nested.native.reference @@ -0,0 +1,3 @@ +Raised by primitive operation at file "backtrace_effects_nested.ml", line 6, characters 2-11 +Called from file "backtrace_effects_nested.ml", line 15, characters 26-39 +43 diff --git a/testsuite/tests/backtrace/backtrace_effects_nested.reference b/testsuite/tests/backtrace/backtrace_effects_nested.reference new file mode 100644 index 0000000000..ff66bf82ef --- /dev/null +++ b/testsuite/tests/backtrace/backtrace_effects_nested.reference @@ -0,0 +1,3 @@ +Raised by primitive operation at file "backtrace_effects_nested.ml", line 6, characters 2-11 +Called from file "backtrace_effects_nested.ml", line 15, characters 26-39 +43 diff --git a/testsuite/tests/backtrace/callstack.ml b/testsuite/tests/backtrace/callstack.ml index 5c33816e06..f27e35638b 100644 --- a/testsuite/tests/backtrace/callstack.ml +++ b/testsuite/tests/backtrace/callstack.ml @@ -18,7 +18,8 @@ let () = f3 () let () = Printf.printf "from finalizer:\n" let () = - Gc.finalise (fun _ -> f0 ()) [|1|]; + Gc.finalise (fun _ -> ( (* f0 *) ())) [|1|]; + (* TODO: finalizer issue to fix, see Multicore issue #385 *) Gc.full_major (); () diff --git a/testsuite/tests/backtrace/lazy.ml b/testsuite/tests/backtrace/lazy.ml index 44dbb04363..99c0735d73 100644 --- a/testsuite/tests/backtrace/lazy.ml +++ b/testsuite/tests/backtrace/lazy.ml @@ -1,5 +1,6 @@ (* TEST flags = "-g" + compare_programs = "false" * native *) diff --git a/testsuite/tests/backtrace/lazy.reference b/testsuite/tests/backtrace/lazy.reference index ccb2a21e6c..25a7aac0d6 100644 --- a/testsuite/tests/backtrace/lazy.reference +++ b/testsuite/tests/backtrace/lazy.reference @@ -1,12 +1,14 @@ Uncaught exception Not_found -Raised at Lazy.l1 in file "lazy.ml", line 7, characters 28-45 -Called from CamlinternalLazy.force_lazy_block in file "camlinternalLazy.ml", line 31, characters 17-27 -Re-raised at CamlinternalLazy.force_lazy_block in file "camlinternalLazy.ml", line 36, characters 4-11 -Called from Lazy.test1 in file "lazy.ml", line 10, characters 11-24 -Called from Lazy.run in file "lazy.ml", line 19, characters 4-11 +Raised at Lazy.l1 in file "lazy.ml", line 8, characters 28-45 +Called from CamlinternalLazy.do_force_block in file "camlinternalLazy.ml", line 39, characters 17-27 +Re-raised at CamlinternalLazy.do_force_block in file "camlinternalLazy.ml", line 45, characters 4-11 +Called from CamlinternalLazy.force_lazy_block in file "camlinternalLazy.ml" (inlined), line 83, characters 27-67 +Called from Lazy.test1 in file "lazy.ml", line 11, characters 11-24 +Called from Lazy.run in file "lazy.ml", line 20, characters 4-11 Uncaught exception Not_found -Raised at Lazy.l2 in file "lazy.ml", line 12, characters 28-45 -Called from CamlinternalLazy.force_lazy_block in file "camlinternalLazy.ml", line 31, characters 17-27 -Re-raised at CamlinternalLazy.force_lazy_block in file "camlinternalLazy.ml", line 36, characters 4-11 -Called from Lazy.test2 in file "lazy.ml", line 15, characters 6-15 -Called from Lazy.run in file "lazy.ml", line 19, characters 4-11 +Raised at Lazy.l2 in file "lazy.ml", line 13, characters 28-45 +Called from CamlinternalLazy.do_force_block in file "camlinternalLazy.ml", line 39, characters 17-27 +Re-raised at CamlinternalLazy.do_force_block in file "camlinternalLazy.ml", line 45, characters 4-11 +Called from CamlinternalLazy.force_lazy_block in file "camlinternalLazy.ml" (inlined), line 83, characters 27-67 +Called from Lazy.test2 in file "lazy.ml", line 16, characters 6-15 +Called from Lazy.run in file "lazy.ml", line 20, characters 4-11 diff --git a/testsuite/tests/basic-modules/anonymous.ocamlc.reference b/testsuite/tests/basic-modules/anonymous.ocamlc.reference index dd27f037c9..a50daeb848 100644 --- a/testsuite/tests/basic-modules/anonymous.ocamlc.reference +++ b/testsuite/tests/basic-modules/anonymous.ocamlc.reference @@ -2,15 +2,15 @@ (seq (ignore (let (x = [0: 13 37]) (makeblock 0 x))) (let (A = - (apply (field 0 (global CamlinternalMod!)) [0: "anonymous.ml" 25 6] - [0: [0]]) + (apply (field_imm 0 (global CamlinternalMod!)) + [0: "anonymous.ml" 25 6] [0: [0]]) B = - (apply (field 0 (global CamlinternalMod!)) [0: "anonymous.ml" 35 6] - [0: [0]])) + (apply (field_imm 0 (global CamlinternalMod!)) + [0: "anonymous.ml" 35 6] [0: [0]])) (seq (ignore (let (x = [0: 4 2]) (makeblock 0 x))) - (apply (field 1 (global CamlinternalMod!)) [0: [0]] A + (apply (field_imm 1 (global CamlinternalMod!)) [0: [0]] A (module-defn(A) Anonymous anonymous.ml(23):567-608 A)) - (apply (field 1 (global CamlinternalMod!)) [0: [0]] B + (apply (field_imm 1 (global CamlinternalMod!)) [0: [0]] B (module-defn(B) Anonymous anonymous.ml(33):703-773 (let (x = [0: "foo" "bar"]) (makeblock 0)))) (let (f = (function param 0) s = (makemutable 0 "")) @@ -19,5 +19,6 @@ (let (*match* = (setfield_ptr 0 s "Hello World!")) (makeblock 0))) (let - (drop = (function param 0) *match* = (apply drop (field 0 s))) + (drop = (function param 0) + *match* = (apply drop (field_mut 0 s))) (makeblock 0 A B f s drop)))))))) diff --git a/testsuite/tests/basic-modules/anonymous.ocamlopt.flambda.reference b/testsuite/tests/basic-modules/anonymous.ocamlopt.flambda.reference index 16b747f109..c68b4b6bf2 100644 --- a/testsuite/tests/basic-modules/anonymous.ocamlopt.flambda.reference +++ b/testsuite/tests/basic-modules/anonymous.ocamlopt.flambda.reference @@ -1,16 +1,16 @@ (seq (ignore (let (x = [0: 13 37]) (makeblock 0 x))) (let (A = - (apply (field 0 (global CamlinternalMod!)) [0: "anonymous.ml" 25 6] - [0: [0]]) + (apply (field_imm 0 (global CamlinternalMod!)) + [0: "anonymous.ml" 25 6] [0: [0]]) B = - (apply (field 0 (global CamlinternalMod!)) [0: "anonymous.ml" 35 6] - [0: [0]])) + (apply (field_imm 0 (global CamlinternalMod!)) + [0: "anonymous.ml" 35 6] [0: [0]])) (seq (ignore (let (x = [0: 4 2]) (makeblock 0 x))) - (apply (field 1 (global CamlinternalMod!)) [0: [0]] A - (module-defn(A) Anonymous anonymous.ml(23):567-608 A)) - (apply (field 1 (global CamlinternalMod!)) [0: [0]] B - (module-defn(B) Anonymous anonymous.ml(33):703-773 + (apply (field_imm 1 (global CamlinternalMod!)) [0: [0]] A + (module-defn(A) anonymous.ml(23):567-608 A)) + (apply (field_imm 1 (global CamlinternalMod!)) [0: [0]] B + (module-defn(B) anonymous.ml(33):703-773 (let (x = [0: "foo" "bar"]) (makeblock 0)))) (let (f = (function param 0) s = (makemutable 0 "")) (seq diff --git a/testsuite/tests/basic-modules/anonymous.ocamlopt.reference b/testsuite/tests/basic-modules/anonymous.ocamlopt.reference index c0ed05ccf0..2bb3dc4a13 100644 --- a/testsuite/tests/basic-modules/anonymous.ocamlopt.reference +++ b/testsuite/tests/basic-modules/anonymous.ocamlopt.reference @@ -1,14 +1,14 @@ (seq (ignore (let (x = [0: 13 37]) (makeblock 0 x))) (let (A = - (apply (field 0 (global CamlinternalMod!)) [0: "anonymous.ml" 25 6] - [0: [0]]) + (apply (field_imm 0 (global CamlinternalMod!)) + [0: "anonymous.ml" 25 6] [0: [0]]) B = - (apply (field 0 (global CamlinternalMod!)) [0: "anonymous.ml" 35 6] - [0: [0]])) + (apply (field_imm 0 (global CamlinternalMod!)) + [0: "anonymous.ml" 35 6] [0: [0]])) (seq (ignore (let (x = [0: 4 2]) (makeblock 0 x))) - (apply (field 1 (global CamlinternalMod!)) [0: [0]] A A) - (apply (field 1 (global CamlinternalMod!)) [0: [0]] B + (apply (field_imm 1 (global CamlinternalMod!)) [0: [0]] A A) + (apply (field_imm 1 (global CamlinternalMod!)) [0: [0]] B (let (x = [0: "foo" "bar"]) (makeblock 0))) (setfield_ptr(root-init) 0 (global Anonymous!) A) (setfield_ptr(root-init) 1 (global Anonymous!) B) @@ -19,13 +19,14 @@ (ignore (let (*match* = - (setfield_ptr 0 (field 3 (global Anonymous!)) "Hello World!")) + (setfield_ptr 0 (field_imm 3 (global Anonymous!)) + "Hello World!")) (makeblock 0))) (let (drop = (function param 0)) (setfield_ptr(root-init) 4 (global Anonymous!) drop)) (let (*match* = - (apply (field 4 (global Anonymous!)) - (field 0 (field 3 (global Anonymous!))))) + (apply (field_imm 4 (global Anonymous!)) + (field_mut 0 (field_imm 3 (global Anonymous!))))) 0) 0))) diff --git a/testsuite/tests/basic/arrays.ml b/testsuite/tests/basic/arrays.ml index 83cc796cae..a094f155dd 100644 --- a/testsuite/tests/basic/arrays.ml +++ b/testsuite/tests/basic/arrays.ml @@ -127,6 +127,12 @@ let test8 () = ignore (Array.sub [|3;4|] (-1) 1); print_string "Test 8.4: failed\n" with Invalid_argument _ -> ()) +let test9 () = + try + (* test exception raised from C (caml_array_bound_error) to OCaml *) + ignore ([| |].(0)); print_string "Test 9: failed\n" + with Invalid_argument _ -> () + let _ = test1(); test2(); @@ -136,4 +142,5 @@ let _ = test6(); test7(); test8(); + test9(); exit 0 diff --git a/testsuite/tests/basic/constprop.ml.c b/testsuite/tests/basic/constprop.ml.c index ee23d48992..0926edf848 100644 --- a/testsuite/tests/basic/constprop.ml.c +++ b/testsuite/tests/basic/constprop.ml.c @@ -4,6 +4,7 @@ * bytecode compare_programs = "false" * native + compare_programs = "false" *) (* This file has extension .ml.c because it needs to be preprocessed diff --git a/testsuite/tests/basic/patmatch_for_multiple.ml b/testsuite/tests/basic/patmatch_for_multiple.ml index d3146823ae..9d6713f598 100644 --- a/testsuite/tests/basic/patmatch_for_multiple.ml +++ b/testsuite/tests/basic/patmatch_for_multiple.ml @@ -12,16 +12,16 @@ match (3, 2, 1) with ;; [%%expect{| (let - (*match*/88 = 3 - *match*/89 = 2 - *match*/90 = 1 - *match*/91 = *match*/88 + (*match*/89 = 3 + *match*/90 = 2 + *match*/91 = 1 *match*/92 = *match*/89 - *match*/93 = *match*/90) + *match*/93 = *match*/90 + *match*/94 = *match*/91) (catch (catch - (catch (if (!= *match*/92 3) (exit 3) (exit 1)) with (3) - (if (!= *match*/91 1) (exit 2) (exit 1))) + (catch (if (!= *match*/93 3) (exit 3) (exit 1)) with (3) + (if (!= *match*/92 1) (exit 2) (exit 1))) with (2) 0) with (1) 1)) - : bool = false @@ -36,24 +36,25 @@ match (3, 2, 1) with ;; [%%expect{| (let - (*match*/96 = 3 - *match*/97 = 2 - *match*/98 = 1 - *match*/99 = (makeblock 0 *match*/96 *match*/97 *match*/98)) + (*match*/97 = 3 + *match*/98 = 2 + *match*/99 = 1 + *match*/100 = (makeblock 0 *match*/97 *match*/98 *match*/99)) (catch (catch - (let (*match*/100 =a (field 0 *match*/99)) + (let (*match*/101 =a (field_imm 0 *match*/100)) (catch - (let (*match*/101 =a (field 1 *match*/99)) - (if (!= *match*/101 3) (exit 7) - (let (*match*/102 =a (field 2 *match*/99)) (exit 5 *match*/99)))) + (let (*match*/102 =a (field_imm 1 *match*/100)) + (if (!= *match*/102 3) (exit 7) + (let (*match*/103 =a (field_imm 2 *match*/100)) + (exit 5 *match*/100)))) with (7) - (if (!= *match*/100 1) (exit 6) + (if (!= *match*/101 1) (exit 6) (let - (*match*/104 =a (field 2 *match*/99) - *match*/103 =a (field 1 *match*/99)) - (exit 5 *match*/99))))) + (*match*/105 =a (field_imm 2 *match*/100) + *match*/104 =a (field_imm 1 *match*/100)) + (exit 5 *match*/100))))) with (6) 0) - with (5 x/94) (seq (ignore x/94) 1))) + with (5 x/95) (seq (ignore x/95) 1))) - : bool = false |}];; diff --git a/testsuite/tests/basic/patmatch_split_no_or.ml b/testsuite/tests/basic/patmatch_split_no_or.ml index 86a689fb4b..9e8e6e4d30 100644 --- a/testsuite/tests/basic/patmatch_split_no_or.ml +++ b/testsuite/tests/basic/patmatch_split_no_or.ml @@ -18,10 +18,10 @@ let last_is_anys = function (last_is_anys/10 = (function param/12 : int (catch - (if (field 0 param/12) (if (field 1 param/12) (exit 1) 1) - (if (field 1 param/12) (exit 1) 2)) + (if (field_imm 0 param/12) (if (field_imm 1 param/12) (exit 1) 1) + (if (field_imm 1 param/12) (exit 1) 2)) with (1) 3))) - (apply (field 1 (global Toploop!)) "last_is_anys" last_is_anys/10)) + (apply (field_mut 1 (global Toploop!)) "last_is_anys" last_is_anys/10)) val last_is_anys : bool * bool -> int = <fun> |}] @@ -35,10 +35,10 @@ let last_is_vars = function (last_is_vars/17 = (function param/21 : int (catch - (if (field 0 param/21) (if (field 1 param/21) (exit 3) 1) - (if (field 1 param/21) (exit 3) 2)) + (if (field_imm 0 param/21) (if (field_imm 1 param/21) (exit 3) 1) + (if (field_imm 1 param/21) (exit 3) 2)) with (3) 3))) - (apply (field 1 (global Toploop!)) "last_is_vars" last_is_vars/17)) + (apply (field_mut 1 (global Toploop!)) "last_is_vars" last_is_vars/17)) val last_is_vars : bool * bool -> int = <fun> |}] @@ -55,9 +55,9 @@ type t = .. (A/25 = (makeblock 248 "A" (caml_fresh_oo_id 0)) B/26 = (makeblock 248 "B" (caml_fresh_oo_id 0)) C/27 = (makeblock 248 "C" (caml_fresh_oo_id 0))) - (seq (apply (field 1 (global Toploop!)) "A/25" A/25) - (apply (field 1 (global Toploop!)) "B/26" B/26) - (apply (field 1 (global Toploop!)) "C/27" C/27))) + (seq (apply (field_mut 1 (global Toploop!)) "A/25" A/25) + (apply (field_mut 1 (global Toploop!)) "B/26" B/26) + (apply (field_mut 1 (global Toploop!)) "C/27" C/27))) type t += A | B of unit | C of bool * int |}] @@ -71,20 +71,20 @@ let f = function ;; [%%expect{| (let - (C/27 = (apply (field 0 (global Toploop!)) "C/27") - B/26 = (apply (field 0 (global Toploop!)) "B/26") - A/25 = (apply (field 0 (global Toploop!)) "A/25") + (C/27 = (apply (field_mut 0 (global Toploop!)) "C/27") + B/26 = (apply (field_mut 0 (global Toploop!)) "B/26") + A/25 = (apply (field_mut 0 (global Toploop!)) "A/25") f/28 = (function param/30 : int - (let (*match*/31 =a (field 0 param/30)) + (let (*match*/31 =a (field_imm 0 param/30)) (catch - (if (== *match*/31 A/25) (if (field 1 param/30) 1 (exit 8)) + (if (== *match*/31 A/25) (if (field_imm 1 param/30) 1 (exit 8)) (exit 8)) with (8) - (if (field 1 param/30) - (if (== (field 0 *match*/31) B/26) 2 - (if (== (field 0 *match*/31) C/27) 3 4)) - (if (field 2 param/30) 12 11)))))) - (apply (field 1 (global Toploop!)) "f" f/28)) + (if (field_imm 1 param/30) + (if (== (field_imm 0 *match*/31) B/26) 2 + (if (== (field_imm 0 *match*/31) C/27) 3 4)) + (if (field_imm 2 param/30) 12 11)))))) + (apply (field_mut 1 (global Toploop!)) "f" f/28)) val f : t * bool * bool -> int = <fun> |}] diff --git a/testsuite/tests/callback/minor_named.ml b/testsuite/tests/callback/minor_named.ml new file mode 100644 index 0000000000..9bc01b77d5 --- /dev/null +++ b/testsuite/tests/callback/minor_named.ml @@ -0,0 +1,19 @@ +(* TEST + include unix + modules = "minor_named_.c" + * libunix + ** bytecode + ** native +*) + +(* Tests Callback.register and caml_named_value on a young object *) + +external incr_ref : unit -> unit = "incr_ref" + +let () = + let r = ref 40 in + Callback.register "incr_ref" r; + incr_ref (); + Gc.minor (); + incr_ref (); + Printf.printf "%d\n" !r diff --git a/testsuite/tests/callback/minor_named.mli b/testsuite/tests/callback/minor_named.mli new file mode 100644 index 0000000000..b47995c5c1 --- /dev/null +++ b/testsuite/tests/callback/minor_named.mli @@ -0,0 +1 @@ +external incr_ref : unit -> unit = "incr_ref" diff --git a/testsuite/tests/callback/minor_named.reference b/testsuite/tests/callback/minor_named.reference new file mode 100644 index 0000000000..d81cc0710e --- /dev/null +++ b/testsuite/tests/callback/minor_named.reference @@ -0,0 +1 @@ +42 diff --git a/testsuite/tests/callback/minor_named_.c b/testsuite/tests/callback/minor_named_.c new file mode 100644 index 0000000000..685f137010 --- /dev/null +++ b/testsuite/tests/callback/minor_named_.c @@ -0,0 +1,10 @@ +#include <caml/mlvalues.h> +#include <caml/memory.h> +#include <caml/callback.h> + +value incr_ref(value unit) { + static const value* v; + if (!v) v = caml_named_value("incr_ref"); + caml_modify_field(*v, 0, Val_int(Int_field(*v, 0) + 1)); + return Val_unit; +} diff --git a/testsuite/tests/callback/nested_fiber.ml b/testsuite/tests/callback/nested_fiber.ml new file mode 100644 index 0000000000..8575c093d5 --- /dev/null +++ b/testsuite/tests/callback/nested_fiber.ml @@ -0,0 +1,44 @@ +(* TEST + include unix + modules = "nested_fiber_.c" + * libunix + ** bytecode + ** native +*) + +external caml_to_c : (unit -> 'a) -> 'a = "caml_to_c" + +effect E : unit + +type 'a tree = Empty | Node of 'a tree * 'a tree + +let rec make d = + match d with + | 0 -> Node(Empty, Empty) + | _ -> let d = d - 1 in Node(make d, make d) + +let rec check = function Empty -> 0 | Node(l, r) -> 1 + check l + check r + +let g () = + caml_to_c (fun () -> + Gc.full_major (); + let x = make 10 in + Printf.printf "g() check %d\n%!" (check x)) + +let f () = + let x = make 3 in + let z = ref 1 in + (match g () with + | effect E k -> assert false + | () -> + Printf.printf "g() returned: %d\n%!" !z); + Printf.printf "f() check: %d\n%!" (check x) + +let () = + let x = make 3 in + let z = ref 2 in + (match f () with + | effect E k -> assert false + | () -> + Printf.printf "f() returned: %d\n%!" !z); + Printf.printf "() check: %d\n%!" (check x) diff --git a/testsuite/tests/callback/nested_fiber.mli b/testsuite/tests/callback/nested_fiber.mli new file mode 100644 index 0000000000..51fa3954b4 --- /dev/null +++ b/testsuite/tests/callback/nested_fiber.mli @@ -0,0 +1 @@ +external caml_to_c : (unit -> 'a) -> 'a = "caml_to_c" diff --git a/testsuite/tests/callback/nested_fiber.reference b/testsuite/tests/callback/nested_fiber.reference new file mode 100644 index 0000000000..e36b225e15 --- /dev/null +++ b/testsuite/tests/callback/nested_fiber.reference @@ -0,0 +1,5 @@ +g() check 2047 +g() returned: 1 +f() check: 15 +f() returned: 2 +() check: 15
\ No newline at end of file diff --git a/testsuite/tests/callback/nested_fiber_.c b/testsuite/tests/callback/nested_fiber_.c new file mode 100644 index 0000000000..0978ac9b20 --- /dev/null +++ b/testsuite/tests/callback/nested_fiber_.c @@ -0,0 +1,6 @@ +#include <caml/mlvalues.h> +#include <caml/callback.h> + +value caml_to_c (value f) { + return caml_callback(f, Val_unit); +} diff --git a/testsuite/tests/callback/stack_overflow.ml b/testsuite/tests/callback/stack_overflow.ml new file mode 100644 index 0000000000..1307b107e1 --- /dev/null +++ b/testsuite/tests/callback/stack_overflow.ml @@ -0,0 +1,22 @@ +(* TEST + include unix + modules = "stack_overflow_.c" + * libunix + ** bytecode + ** native +*) + +external caml_to_c : (unit -> 'a) -> 'a = "caml_to_c" + +let rec deep = function + | 0 -> + ref 42 + | n -> + caml_to_c (fun () -> deep (n-1)) + +effect E : unit + +let () = + Printf.printf "%d\n%d\n%!" + (!(deep 1000)) + (match deep 1000 with x -> !x | effect E k -> assert false) diff --git a/testsuite/tests/callback/stack_overflow.mli b/testsuite/tests/callback/stack_overflow.mli new file mode 100644 index 0000000000..51fa3954b4 --- /dev/null +++ b/testsuite/tests/callback/stack_overflow.mli @@ -0,0 +1 @@ +external caml_to_c : (unit -> 'a) -> 'a = "caml_to_c" diff --git a/testsuite/tests/callback/stack_overflow.reference b/testsuite/tests/callback/stack_overflow.reference new file mode 100644 index 0000000000..daaac9e303 --- /dev/null +++ b/testsuite/tests/callback/stack_overflow.reference @@ -0,0 +1,2 @@ +42 +42 diff --git a/testsuite/tests/callback/stack_overflow_.c b/testsuite/tests/callback/stack_overflow_.c new file mode 100644 index 0000000000..0978ac9b20 --- /dev/null +++ b/testsuite/tests/callback/stack_overflow_.c @@ -0,0 +1,6 @@ +#include <caml/mlvalues.h> +#include <caml/callback.h> + +value caml_to_c (value f) { + return caml_callback(f, Val_unit); +} diff --git a/testsuite/tests/callback/tcallback.ml b/testsuite/tests/callback/test1.ml index 9e4e09f5c6..72c06fec80 100644 --- a/testsuite/tests/callback/tcallback.ml +++ b/testsuite/tests/callback/test1.ml @@ -1,6 +1,6 @@ (* TEST include unix - modules = "callbackprim.c" + modules = "test1_.c" * libunix ** bytecode ** native diff --git a/testsuite/tests/callback/test1.mli b/testsuite/tests/callback/test1.mli new file mode 100644 index 0000000000..8559ebe245 --- /dev/null +++ b/testsuite/tests/callback/test1.mli @@ -0,0 +1,19 @@ +external mycallback1 : ('a -> 'b) -> 'a -> 'b = "mycallback1" +external mycallback2 : ('a -> 'b -> 'c) -> 'a -> 'b -> 'c = "mycallback2" +external mycallback3 : ('a -> 'b -> 'c -> 'd) -> 'a -> 'b -> 'c -> 'd + = "mycallback3" +external mycallback4 : + ('a -> 'b -> 'c -> 'd -> 'e) -> 'a -> 'b -> 'c -> 'd -> 'e = "mycallback4" +val tak : int * int * int -> int +val tak2 : int -> int * int -> int +val tak3 : int -> int -> int -> int +val tak4 : int -> int -> int -> int -> int +val raise_exit : unit -> unit +val trapexit : unit -> int +external mypushroot : 'a -> ('b -> 'c) -> 'b -> 'a = "mypushroot" +external mycamlparam : 'a -> ('b -> 'c) -> 'b -> 'a = "mycamlparam" +val tripwire : (string -> (unit -> int) -> unit -> 'a) -> 'a +val sighandler : 'a -> unit +external unix_getpid : unit -> int = "unix_getpid" [@@noalloc] +external unix_kill : int -> int -> unit = "unix_kill" [@@noalloc] +val callbacksig : unit -> string diff --git a/testsuite/tests/callback/test1.reference b/testsuite/tests/callback/test1.reference new file mode 100644 index 0000000000..b35993aa2c --- /dev/null +++ b/testsuite/tests/callback/test1.reference @@ -0,0 +1,8 @@ +7 +7 +7 +7 +7 +aaaaa +aaaaa +bbbbb diff --git a/testsuite/tests/callback/callbackprim.c b/testsuite/tests/callback/test1_.c index 45879a0191..45879a0191 100644 --- a/testsuite/tests/callback/callbackprim.c +++ b/testsuite/tests/callback/test1_.c diff --git a/testsuite/tests/callback/test2.ml b/testsuite/tests/callback/test2.ml new file mode 100644 index 0000000000..87314864f2 --- /dev/null +++ b/testsuite/tests/callback/test2.ml @@ -0,0 +1,25 @@ +(* TEST + include unix + modules = "test2_.c" + * libunix + ** bytecode + ** native +*) + +(* Tests nested calls from C (main C) to OCaml (main OCaml) to C (caml_to_c) to + * OCaml (c_to_caml) to C (printf functions). *) + +let printf = Printf.printf + +let c_to_caml () = + printf "[Caml] Enter c_to_caml\n%!"; + printf "[Caml] Leave c_to_caml\n%!" + +let _ = Callback.register "c_to_caml" c_to_caml + +external caml_to_c : unit -> unit = "caml_to_c" + +let _ = + printf "[Caml] Call caml_to_c\n%!"; + caml_to_c (); + printf "[Caml] Return from caml_to_c\n%!" diff --git a/testsuite/tests/callback/test2.mli b/testsuite/tests/callback/test2.mli new file mode 100644 index 0000000000..6aedf9522b --- /dev/null +++ b/testsuite/tests/callback/test2.mli @@ -0,0 +1 @@ +external caml_to_c : unit -> unit = "caml_to_c" diff --git a/testsuite/tests/callback/test2.reference b/testsuite/tests/callback/test2.reference new file mode 100644 index 0000000000..4b166b2223 --- /dev/null +++ b/testsuite/tests/callback/test2.reference @@ -0,0 +1,8 @@ +[Caml] Call caml_to_c +[Caml] Enter c_to_caml +[Caml] Leave c_to_caml +[Caml] Return from caml_to_c +[C] Enter caml_to_c +[C] Call c_to_caml +[C] Return from c_to_caml +[C] Leave caml_to_c diff --git a/testsuite/tests/callback/test2_.c b/testsuite/tests/callback/test2_.c new file mode 100644 index 0000000000..f16fe30c0e --- /dev/null +++ b/testsuite/tests/callback/test2_.c @@ -0,0 +1,21 @@ +#include <stdio.h> +#include <caml/mlvalues.h> +#include <caml/memory.h> +#include <caml/callback.h> + +value caml_to_c (value unit) { + CAMLparam1 (unit); + printf ("[C] Enter caml_to_c\n"); + + static const value* c_to_caml_closure = NULL; + + if (!c_to_caml_closure) + c_to_caml_closure = caml_named_value("c_to_caml"); + + printf ("[C] Call c_to_caml\n"); + caml_callback(*c_to_caml_closure, Val_unit); + printf ("[C] Return from c_to_caml\n"); + + printf ("[C] Leave caml_to_c\n"); + CAMLreturn (Val_unit); +} diff --git a/testsuite/tests/callback/test3.ml b/testsuite/tests/callback/test3.ml new file mode 100644 index 0000000000..efa92d00de --- /dev/null +++ b/testsuite/tests/callback/test3.ml @@ -0,0 +1,37 @@ +(* TEST + include unix + modules = "test3_.c" + * libunix + ** bytecode + ** native +*) + +(* Tests nested calls from C (main C) to OCaml (main OCaml) to C (caml_to_c) to + * OCaml (c_to_caml) to C (printf functions). A stack overflow and a heap + * overflow are triggered in c_to_caml. *) + +let printf = Printf.printf + +let rec mk_list length acc = + if length < 1 then acc + else mk_list (length-1) ((length-1)::acc) + +let rec sum n = if n = 0 then 0 else n + sum (n-1) + +let c_to_caml () = + printf "[Caml] Enter c_to_caml\n%!"; + (* Heap overflow *) + let l = mk_list 1000 [] in + Printf.printf "%d\n" (List.hd l); + (* Stack overflow *) + Printf.printf "%d\n" (sum 100000); + printf "[Caml] Leave c_to_caml\n%!" + +let _ = Callback.register "c_to_caml" c_to_caml + +external caml_to_c : unit -> unit = "caml_to_c" + +let _ = + printf "[Caml] Call caml_to_c\n%!"; + caml_to_c (); + printf "[Caml] Return from caml_to_c\n%!" diff --git a/testsuite/tests/callback/test3.mli b/testsuite/tests/callback/test3.mli new file mode 100644 index 0000000000..6aedf9522b --- /dev/null +++ b/testsuite/tests/callback/test3.mli @@ -0,0 +1 @@ +external caml_to_c : unit -> unit = "caml_to_c" diff --git a/testsuite/tests/callback/test3.reference b/testsuite/tests/callback/test3.reference new file mode 100644 index 0000000000..eb917de6dc --- /dev/null +++ b/testsuite/tests/callback/test3.reference @@ -0,0 +1,10 @@ +[Caml] Call caml_to_c +[Caml] Enter c_to_caml +0 +5000050000 +[Caml] Leave c_to_caml +[Caml] Return from caml_to_c +[C] Enter caml_to_c +[C] Call c_to_caml +[C] Return from c_to_caml +[C] Leave caml_to_c diff --git a/testsuite/tests/callback/test3_.c b/testsuite/tests/callback/test3_.c new file mode 100644 index 0000000000..f16fe30c0e --- /dev/null +++ b/testsuite/tests/callback/test3_.c @@ -0,0 +1,21 @@ +#include <stdio.h> +#include <caml/mlvalues.h> +#include <caml/memory.h> +#include <caml/callback.h> + +value caml_to_c (value unit) { + CAMLparam1 (unit); + printf ("[C] Enter caml_to_c\n"); + + static const value* c_to_caml_closure = NULL; + + if (!c_to_caml_closure) + c_to_caml_closure = caml_named_value("c_to_caml"); + + printf ("[C] Call c_to_caml\n"); + caml_callback(*c_to_caml_closure, Val_unit); + printf ("[C] Return from c_to_caml\n"); + + printf ("[C] Leave caml_to_c\n"); + CAMLreturn (Val_unit); +} diff --git a/testsuite/tests/callback/test4.ml b/testsuite/tests/callback/test4.ml new file mode 100644 index 0000000000..3c42317d7e --- /dev/null +++ b/testsuite/tests/callback/test4.ml @@ -0,0 +1,31 @@ +(* TEST + include unix + modules = "test4_.c" + * libunix + ** bytecode + ** native +*) + +(* Tests nested calls from C (main C) to OCaml (main OCaml) to C (caml_to_c) to + * OCaml (c_to_caml) to C (printf functions). Exception is raised in a + * Callback, which unwinds the C stack and gets caught in OCaml. *) + +exception E + +let printf = Printf.printf + +let c_to_caml () = + printf "[Caml] Enter c_to_caml\n%!"; + printf "[Caml] c_to_caml: raise exception\n%!"; + raise E + +let _ = Callback.register "c_to_caml" c_to_caml + +external caml_to_c : unit -> unit = "caml_to_c" + +let _ = + try + printf "[Caml] Call caml_to_c\n%!"; + caml_to_c (); + printf "[Caml] Return from caml_to_c\n%!" + with E -> printf "[Caml] Caught exception\n%!" diff --git a/testsuite/tests/callback/test4.mli b/testsuite/tests/callback/test4.mli new file mode 100644 index 0000000000..6aedf9522b --- /dev/null +++ b/testsuite/tests/callback/test4.mli @@ -0,0 +1 @@ +external caml_to_c : unit -> unit = "caml_to_c" diff --git a/testsuite/tests/callback/test4.reference b/testsuite/tests/callback/test4.reference new file mode 100644 index 0000000000..4aa50ab9ec --- /dev/null +++ b/testsuite/tests/callback/test4.reference @@ -0,0 +1,6 @@ +[Caml] Call caml_to_c +[Caml] Enter c_to_caml +[Caml] c_to_caml: raise exception +[Caml] Caught exception +[C] Enter caml_to_c +[C] Call c_to_caml diff --git a/testsuite/tests/callback/test4_.c b/testsuite/tests/callback/test4_.c new file mode 100644 index 0000000000..f16fe30c0e --- /dev/null +++ b/testsuite/tests/callback/test4_.c @@ -0,0 +1,21 @@ +#include <stdio.h> +#include <caml/mlvalues.h> +#include <caml/memory.h> +#include <caml/callback.h> + +value caml_to_c (value unit) { + CAMLparam1 (unit); + printf ("[C] Enter caml_to_c\n"); + + static const value* c_to_caml_closure = NULL; + + if (!c_to_caml_closure) + c_to_caml_closure = caml_named_value("c_to_caml"); + + printf ("[C] Call c_to_caml\n"); + caml_callback(*c_to_caml_closure, Val_unit); + printf ("[C] Return from c_to_caml\n"); + + printf ("[C] Leave caml_to_c\n"); + CAMLreturn (Val_unit); +} diff --git a/testsuite/tests/callback/test5.ml b/testsuite/tests/callback/test5.ml new file mode 100644 index 0000000000..62fd8b9b0e --- /dev/null +++ b/testsuite/tests/callback/test5.ml @@ -0,0 +1,29 @@ +(* TEST + include unix + modules = "test5_.c" + * libunix + ** bytecode + ** native +*) + +(* Tests nested calls from C (main C) to OCaml (main OCaml) to C (caml_to_c) to + * OCaml (c_to_caml) to C (printf functions). Test calls with arguments passed + * on the stack from C to OCaml and OCaml to C. *) + +let printf = Printf.printf + +let c_to_caml n = + printf "[Caml] Enter c_to_caml\n%!"; + printf "c_to_caml: n=%d\n" n; + printf "[Caml] Leave c_to_caml\n%!" + +let _ = Callback.register "c_to_caml" c_to_caml + +external caml_to_c : int -> int -> int -> int -> int + -> int -> int -> int -> int -> int + -> int -> unit = "caml_to_c_bytecode" "caml_to_c_native" + +let _ = + printf "[Caml] Call caml_to_c\n%!"; + caml_to_c 1 2 3 4 5 6 7 8 9 10 11; + printf "[Caml] Return from caml_to_c\n%!" diff --git a/testsuite/tests/callback/test5.mli b/testsuite/tests/callback/test5.mli new file mode 100644 index 0000000000..8c0a90422e --- /dev/null +++ b/testsuite/tests/callback/test5.mli @@ -0,0 +1,3 @@ +external caml_to_c : int -> int -> int -> int -> int + -> int -> int -> int -> int -> int + -> int -> unit = "caml_to_c_bytecode" "caml_to_c_native" diff --git a/testsuite/tests/callback/test5.reference b/testsuite/tests/callback/test5.reference new file mode 100644 index 0000000000..d930c4d1ff --- /dev/null +++ b/testsuite/tests/callback/test5.reference @@ -0,0 +1,9 @@ +[Caml] Call caml_to_c +[Caml] Enter c_to_caml +c_to_caml: n=66 +[Caml] Leave c_to_caml +[Caml] Return from caml_to_c +[C] Enter caml_to_c +[C] Call c_to_caml +[C] Return from c_to_caml +[C] Leave caml_to_c diff --git a/testsuite/tests/callback/test5_.c b/testsuite/tests/callback/test5_.c new file mode 100644 index 0000000000..5e77080e78 --- /dev/null +++ b/testsuite/tests/callback/test5_.c @@ -0,0 +1,35 @@ +#include <stdio.h> +#include <caml/mlvalues.h> +#include <caml/memory.h> +#include <caml/callback.h> + +value caml_to_c_native (value a1, value a2, value a3, value a4, value a5, + value a6, value a7, value a8, value a9, value a10, + value a11) +{ + CAMLparam0 (); + long l; + + printf ("[C] Enter caml_to_c\n"); + + static const value* c_to_caml_closure = NULL; + if (!c_to_caml_closure) + c_to_caml_closure = caml_named_value("c_to_caml"); + + l = Long_val (a1) + Long_val (a2) + Long_val (a3) + Long_val (a4) + + Long_val (a5) + Long_val (a6) + Long_val (a7) + Long_val (a8) + + Long_val (a9) + Long_val (a10) + Long_val (a11); + + printf ("[C] Call c_to_caml\n"); + caml_callback(*c_to_caml_closure, Val_long(l)); + printf ("[C] Return from c_to_caml\n"); + + printf ("[C] Leave caml_to_c\n"); + CAMLreturn (Val_unit); +} + +value caml_to_c_bytecode (value * argv, int argn) { + return caml_to_c_native (argv[0], argv[1], argv[2], argv[3], argv[4], + argv[5], argv[6], argv[7], argv[8], argv[9], + argv[10]); +} diff --git a/testsuite/tests/callback/test6.ml b/testsuite/tests/callback/test6.ml new file mode 100644 index 0000000000..e3ff477f5b --- /dev/null +++ b/testsuite/tests/callback/test6.ml @@ -0,0 +1,34 @@ +(* TEST + include unix + modules = "test6_.c" + * libunix + ** bytecode + ** native +*) + +(* Tests nested calls from C (main C) to OCaml (main OCaml) to C (caml_to_c) to + * OCaml (c_to_caml) to C (printf functions). Exception is raised in a + * Callback, which unwinds the C stack and gets caught in OCaml. *) + +exception E + +let printf = Printf.printf + +let c_to_caml () = + printf "[Caml] Enter c_to_caml\n%!"; + printf "[Caml] c_to_caml: raise exception\n%!"; + raise E + +let _ = Callback.register "c_to_caml" c_to_caml + +external caml_to_c : unit -> unit = "caml_to_c" + +let _ = + try + printf "[Caml] Call caml_to_c\n%!"; + caml_to_c (); + printf "[Caml] Return from caml_to_c\n%!" + with E -> + (printf "[Caml] Caught exception\n%!"; + try caml_to_c() with E -> printf "[Caml] Caught exceception again\n%!"; + printf "[Caml] Done\n%!") diff --git a/testsuite/tests/callback/test6.mli b/testsuite/tests/callback/test6.mli new file mode 100644 index 0000000000..6aedf9522b --- /dev/null +++ b/testsuite/tests/callback/test6.mli @@ -0,0 +1 @@ +external caml_to_c : unit -> unit = "caml_to_c" diff --git a/testsuite/tests/callback/test6.reference b/testsuite/tests/callback/test6.reference new file mode 100644 index 0000000000..266679b319 --- /dev/null +++ b/testsuite/tests/callback/test6.reference @@ -0,0 +1,12 @@ +[Caml] Call caml_to_c +[Caml] Enter c_to_caml +[Caml] c_to_caml: raise exception +[Caml] Caught exception +[Caml] Enter c_to_caml +[Caml] c_to_caml: raise exception +[Caml] Caught exceception again +[Caml] Done +[C] Enter caml_to_c +[C] Call c_to_caml +[C] Enter caml_to_c +[C] Call c_to_caml diff --git a/testsuite/tests/callback/test6_.c b/testsuite/tests/callback/test6_.c new file mode 100644 index 0000000000..f16fe30c0e --- /dev/null +++ b/testsuite/tests/callback/test6_.c @@ -0,0 +1,21 @@ +#include <stdio.h> +#include <caml/mlvalues.h> +#include <caml/memory.h> +#include <caml/callback.h> + +value caml_to_c (value unit) { + CAMLparam1 (unit); + printf ("[C] Enter caml_to_c\n"); + + static const value* c_to_caml_closure = NULL; + + if (!c_to_caml_closure) + c_to_caml_closure = caml_named_value("c_to_caml"); + + printf ("[C] Call c_to_caml\n"); + caml_callback(*c_to_caml_closure, Val_unit); + printf ("[C] Return from c_to_caml\n"); + + printf ("[C] Leave caml_to_c\n"); + CAMLreturn (Val_unit); +} diff --git a/testsuite/tests/callback/test7.ml b/testsuite/tests/callback/test7.ml new file mode 100644 index 0000000000..1f76775b83 --- /dev/null +++ b/testsuite/tests/callback/test7.ml @@ -0,0 +1,36 @@ +(* TEST + include unix + modules = "test7_.c" + * libunix + ** bytecode + ** native +*) + +(* Tests nested calls from C (main C) to OCaml (main OCaml) to C (caml_to_c) to + * OCaml (c_to_caml) to C (printf functions). Effect E is performed in the + * callback, which does not have a handler. *) + +effect E : unit + +let printf = Printf.printf + +let c_to_caml () = + printf "[Caml] Enter c_to_caml\n%!"; + printf "[Caml] c_to_caml: perform effect\n%!"; + perform E + +let _ = Callback.register "c_to_caml" c_to_caml + +external caml_to_c : unit -> unit = "caml_to_c" + +let _ = + try + printf "[Caml] Call caml_to_c\n%!"; + begin try + caml_to_c () + with Unhandled -> + (printf "[Caml] Caught Unhandled, perform effect\n%!"; + perform E) + end; + printf "[Caml] Return from caml_to_c\n%!" + with effect E k -> printf "[Caml] Caught effect\n%!" diff --git a/testsuite/tests/callback/test7.mli b/testsuite/tests/callback/test7.mli new file mode 100644 index 0000000000..6aedf9522b --- /dev/null +++ b/testsuite/tests/callback/test7.mli @@ -0,0 +1 @@ +external caml_to_c : unit -> unit = "caml_to_c" diff --git a/testsuite/tests/callback/test7.reference b/testsuite/tests/callback/test7.reference new file mode 100644 index 0000000000..4b346e5fcd --- /dev/null +++ b/testsuite/tests/callback/test7.reference @@ -0,0 +1,7 @@ +[Caml] Call caml_to_c +[Caml] Enter c_to_caml +[Caml] c_to_caml: perform effect +[Caml] Caught Unhandled, perform effect +[Caml] Caught effect +[C] Enter caml_to_c +[C] Call c_to_caml diff --git a/testsuite/tests/callback/test7_.c b/testsuite/tests/callback/test7_.c new file mode 100644 index 0000000000..f16fe30c0e --- /dev/null +++ b/testsuite/tests/callback/test7_.c @@ -0,0 +1,21 @@ +#include <stdio.h> +#include <caml/mlvalues.h> +#include <caml/memory.h> +#include <caml/callback.h> + +value caml_to_c (value unit) { + CAMLparam1 (unit); + printf ("[C] Enter caml_to_c\n"); + + static const value* c_to_caml_closure = NULL; + + if (!c_to_caml_closure) + c_to_caml_closure = caml_named_value("c_to_caml"); + + printf ("[C] Call c_to_caml\n"); + caml_callback(*c_to_caml_closure, Val_unit); + printf ("[C] Return from c_to_caml\n"); + + printf ("[C] Leave caml_to_c\n"); + CAMLreturn (Val_unit); +} diff --git a/testsuite/tests/effects-disallowed/when_test.compilers.reference b/testsuite/tests/effects-disallowed/when_test.compilers.reference new file mode 100644 index 0000000000..35b9b0dc6c --- /dev/null +++ b/testsuite/tests/effects-disallowed/when_test.compilers.reference @@ -0,0 +1,6 @@ +effect E : unit +Line 4, characters 31-32: +4 | | effect E k when (continue k (); false) -> assert false + ^ +Error: Unbound value k + diff --git a/testsuite/tests/effects-disallowed/when_test.ml b/testsuite/tests/effects-disallowed/when_test.ml new file mode 100644 index 0000000000..bfce9f5e61 --- /dev/null +++ b/testsuite/tests/effects-disallowed/when_test.ml @@ -0,0 +1,11 @@ +(* TEST + * toplevel +*) + +effect E : unit;; +let () = + (match perform E with + | v -> v + | effect E k when (continue k (); false) -> assert false + | effect E k' -> continue k' ()) +;; diff --git a/testsuite/tests/effects/clone_test.ml b/testsuite/tests/effects/clone_test.ml new file mode 100644 index 0000000000..bbd450eeac --- /dev/null +++ b/testsuite/tests/effects/clone_test.ml @@ -0,0 +1,63 @@ +(* TEST + *) + +module Segfault = struct + module Nondet = struct + effect Fork : bool + let fork () = perform Fork + + let rec forkEach f = function + | [] -> () + | x::xs -> + (* if branches are swapped, then no segfault occurs *) + if (fork ()) then (f x) else (forkEach f xs) + + (** Explores alternatives in BFS *) + let run worlds action = + let scheduleNext () = + begin match !worlds with + | [] -> () + | w::ws -> worlds := ws; w () + end in + begin match action () with + | x -> scheduleNext () + | effect Fork k -> + let k2 = Obj.clone_continuation k in + let choices = [(fun () -> continue k true); (fun () -> continue k2 false)] in + worlds := !worlds @ choices; + scheduleNext () + end + + let handle action = run (ref []) action + end + + let randArray n = + Array.init n (fun i -> Random.int 1073741823) + + effect Yield: int -> unit + let yield v = perform (Yield v) + + let boom () = + let unyield action () = + try action () with + effect (Yield _) k -> + try discontinue k Exit with Exit -> () + in + let state = ref [] in + let stateful action () = + try action () with + | effect (Yield i) k -> + state := i :: !state; + (* Important: each yield invocation does not return. *) + Nondet.forkEach yield !state; + (* Exactly one of the forked computations will return here. *) + continue k () + in + let count = 10000 in (* for count < 10000, no segfault *) + let a1 = randArray count in + let iter () = Array.iter yield a1 in + Nondet.handle (unyield (stateful iter)) + + let _ = boom () + let _ = print_string "ok" +end diff --git a/testsuite/tests/effects/clone_test.reference b/testsuite/tests/effects/clone_test.reference new file mode 100644 index 0000000000..b5754e2037 --- /dev/null +++ b/testsuite/tests/effects/clone_test.reference @@ -0,0 +1 @@ +ok
\ No newline at end of file diff --git a/testsuite/tests/effects/cmphash.ml b/testsuite/tests/effects/cmphash.ml new file mode 100644 index 0000000000..36c3aeec83 --- /dev/null +++ b/testsuite/tests/effects/cmphash.ml @@ -0,0 +1,18 @@ +(* TEST + *) + +effect Yield : unit + +let `Cont k = + match perform Yield with + | x -> assert false + | effect Yield k -> `Cont (k : (unit, _) continuation) + +let () = + match k = k with + | _ -> assert false + | exception (Invalid_argument _) -> print_endline "ok" + +let () = + match Hashtbl.hash k with + | _ -> Printf.printf "ok\n" diff --git a/testsuite/tests/effects/cmphash.reference b/testsuite/tests/effects/cmphash.reference new file mode 100644 index 0000000000..79ebd0860f --- /dev/null +++ b/testsuite/tests/effects/cmphash.reference @@ -0,0 +1,2 @@ +ok +ok diff --git a/testsuite/tests/effects/cont_gc_test.ml b/testsuite/tests/effects/cont_gc_test.ml new file mode 100644 index 0000000000..8ee6fad569 --- /dev/null +++ b/testsuite/tests/effects/cont_gc_test.ml @@ -0,0 +1,86 @@ +(* TEST *) + +(* This test intends to exercise the minor and major collectors + while also dropping, cloning and storing continuations + *) + +effect Yield : unit + +type 'a tree = Empty | Node of 'a tree * 'a tree + +let rec make d = + match d with + | 0 -> Node(Empty, Empty) + | _ -> let d = d - 1 in Node(make d, make d) + +let rec check = function Empty -> 0 | Node(l, r) -> 1 + check l + check r + +let work () = + let n = 18 in + let arr = Array.init n make in + let x = ref 0 in + + while true do + let j = Random.int n in + let next_tree = make j in + perform Yield; + x := !x + (check (Array.get arr j)); + Array.set arr j next_tree + done; + () + +type stored = None | Cont of (unit,unit) continuation * int tree + +let run n = + let m = 10 in + let arr = Array.make m None in + let n_left = ref n in + + let scheduleNext () = + let rec getCont () = + let j = Random.int m in + match (Array.get arr j) with + | Cont (k, t) -> begin + ignore (check t); + Array.set arr j (Cont (Obj.clone_continuation k, make 2)); + k + end + | None -> getCont () + in + + (* every now and then do some garbage collection *) + if !n_left mod 10 == 0 then begin + if Random.bool () + then Gc.minor () + else Gc.full_major () + end; + + (* stop scheduling and return *) + if !n_left < 0 then () + else begin + n_left := !n_left - 1; + continue (getCont ()) () + end + in + + (match work () with + | effect Yield k -> begin + (* random insert of the continuations *) + let rec insertClone c = + let j = Random.int m in + match Array.get arr j with + | None -> (Array.set arr j (Cont (c, make 4)); insertClone (Obj.clone_continuation c)) + | Cont (c2, _) -> (Array.set arr j (Cont (c, make 4)); c2) + in + + (* we drop the last one we stop at *) + ignore (insertClone k); + scheduleNext () + end + | () -> scheduleNext ()); + + print_endline "ok" + +let _ = Random.init 2493 + +let _ = run 500 diff --git a/testsuite/tests/effects/cont_gc_test.reference b/testsuite/tests/effects/cont_gc_test.reference new file mode 100644 index 0000000000..b5754e2037 --- /dev/null +++ b/testsuite/tests/effects/cont_gc_test.reference @@ -0,0 +1 @@ +ok
\ No newline at end of file diff --git a/testsuite/tests/effects/evenodd.ml b/testsuite/tests/effects/evenodd.ml new file mode 100644 index 0000000000..2e3d88e0d8 --- /dev/null +++ b/testsuite/tests/effects/evenodd.ml @@ -0,0 +1,15 @@ +(* TEST + *) + +effect E : unit + +let rec even n = + if n = 0 then true + else try odd (n-1) with effect E _ -> assert false +and odd n = + if n = 0 then false + else even (n-1) + +let _ = + let n = 1_000_000 in + Printf.printf "even %d is %B\n%!" n (even n) diff --git a/testsuite/tests/effects/evenodd.reference b/testsuite/tests/effects/evenodd.reference new file mode 100644 index 0000000000..4dfddc3329 --- /dev/null +++ b/testsuite/tests/effects/evenodd.reference @@ -0,0 +1 @@ +even 1000000 is true
\ No newline at end of file diff --git a/testsuite/tests/effects/manylive.ml b/testsuite/tests/effects/manylive.ml new file mode 100644 index 0000000000..04c1f53936 --- /dev/null +++ b/testsuite/tests/effects/manylive.ml @@ -0,0 +1,29 @@ +(* TEST + *) + +let f x = + let a0 = ref 1 in + let a1 = ref 1 in + let a2 = ref 1 in + let a3 = ref 1 in + let a4 = ref 1 in + let a5 = ref 1 in + let a6 = ref 1 in + let a7 = ref 1 in + let a8 = ref 1 in + let a9 = ref 1 in + let a10 = ref 1 in + let a11 = ref 1 in + let a12 = ref 1 in + if x then raise Not_found; + [| a0; a1; a2; a3; a4; a5; a6; a7; a8; a9; a10; a11; a12 |] + +let () = + for i = 1 to 50000 do + let rs = Sys.opaque_identity f false in + assert (Array.for_all (fun x -> !x = 1) rs); + let _ = Array.make (Random.int 30) 'a' in () + done; + print_string "ok\n" + + diff --git a/testsuite/tests/effects/manylive.reference b/testsuite/tests/effects/manylive.reference new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/testsuite/tests/effects/manylive.reference @@ -0,0 +1 @@ +ok diff --git a/testsuite/tests/effects/overflow.ml b/testsuite/tests/effects/overflow.ml new file mode 100644 index 0000000000..7a689fed7b --- /dev/null +++ b/testsuite/tests/effects/overflow.ml @@ -0,0 +1,32 @@ +(* TEST + *) + +effect E : unit +let f a b c d e f g h = + let bb = b + b in + let bbb = bb + b in + let cc = c + c in + let ccc = cc + c in + let dd = d + d in + let ddd = dd + d in + let ee = e + e in + let eee = ee + e in + let ff = f + f in + let fff = ff + f in + let gg = g + g in + let ggg = gg + g in + let hh = h + h in + let hhh = hh + h in + min 20 a + + b + bb + bbb + + c + cc + ccc + + d + dd + ddd + + e + ee + eee + + f + ff + fff + + g + gg + ggg + + h + hh + hhh + +let () = + match f 1 2 3 4 5 6 7 8 with + | effect E k -> assert false + | n -> Printf.printf "%d\n" n diff --git a/testsuite/tests/effects/overflow.reference b/testsuite/tests/effects/overflow.reference new file mode 100644 index 0000000000..dba40afcf7 --- /dev/null +++ b/testsuite/tests/effects/overflow.reference @@ -0,0 +1 @@ +211 diff --git a/testsuite/tests/effects/partial.ml b/testsuite/tests/effects/partial.ml new file mode 100644 index 0000000000..8a4b523f89 --- /dev/null +++ b/testsuite/tests/effects/partial.ml @@ -0,0 +1,20 @@ +(* TEST + *) + +effect E : unit +exception Done + +let handle_partial f = + try f () with + | effect E k -> assert false + +let f () x = perform E + +let () = + match + let g = handle_partial f in + g () + with + | x -> assert false + | exception Done -> print_string "ok\n" + | effect E k -> discontinue k Done diff --git a/testsuite/tests/effects/partial.reference b/testsuite/tests/effects/partial.reference new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/testsuite/tests/effects/partial.reference @@ -0,0 +1 @@ +ok diff --git a/testsuite/tests/effects/reperform.ml b/testsuite/tests/effects/reperform.ml new file mode 100644 index 0000000000..5b43eed0f4 --- /dev/null +++ b/testsuite/tests/effects/reperform.ml @@ -0,0 +1,24 @@ +(* TEST + *) + +effect E : int -> int +effect F : unit + +let rec nest = function + | 0 -> perform (E 42) + | n -> + match Printf.printf "[%d\n" n; nest (n - 1) with + | effect F k -> assert false + | exception e -> Printf.printf " !%d]\n" n; raise e + | x -> Printf.printf " %d]\n" n; x + +let () = + match nest 5 with + | effect (E n) k -> continue k (n + 100) + | x -> Printf.printf "= %d\n" x + +let () = + match nest 5 with + | x -> assert false + | effect F k -> assert false + | exception e -> Printf.printf "%s\n" (Printexc.to_string e) diff --git a/testsuite/tests/effects/reperform.reference b/testsuite/tests/effects/reperform.reference new file mode 100644 index 0000000000..4c69a7f94c --- /dev/null +++ b/testsuite/tests/effects/reperform.reference @@ -0,0 +1,22 @@ +[5 +[4 +[3 +[2 +[1 + 1] + 2] + 3] + 4] + 5] += 142 +[5 +[4 +[3 +[2 +[1 + !1] + !2] + !3] + !4] + !5] +Unhandled diff --git a/testsuite/tests/effects/sched.ml b/testsuite/tests/effects/sched.ml new file mode 100644 index 0000000000..0759a61675 --- /dev/null +++ b/testsuite/tests/effects/sched.ml @@ -0,0 +1,49 @@ +(* TEST + *) + +exception E +effect Yield : unit +effect Fork : (unit -> string) -> unit +effect Ping : unit +exception Pong + +let say = print_string + +let run main = + let run_q = Queue.create () in + let enqueue k = Queue.push k run_q in + let rec dequeue () = + if Queue.is_empty run_q then `Finished + else continue (Queue.pop run_q) () + in + let rec spawn f = + match f () with + | "ok" -> say "."; dequeue () + | s -> failwith ("Unexpected result: " ^ s) + | exception E -> + say "!"; dequeue () + | effect Yield k -> + say ","; enqueue k; dequeue () + | effect (Fork f) k -> + say "+"; enqueue k; spawn f + | effect Ping k -> + say "["; discontinue k Pong + in + spawn main + +let test () = + say "A"; + perform (Fork (fun () -> + perform Yield; say "C"; perform Yield; + (try (perform Ping; failwith "no pong?") + with effect Yield k -> failwith "what?" | Pong -> say "]"); + raise E)); + perform (Fork (fun () -> say "B"; "ok")); + say "D"; + perform Yield; + say "E"; + "ok" + +let () = + let `Finished = run test in + say "\n" diff --git a/testsuite/tests/effects/sched.reference b/testsuite/tests/effects/sched.reference new file mode 100644 index 0000000000..47294f1ef7 --- /dev/null +++ b/testsuite/tests/effects/sched.reference @@ -0,0 +1 @@ +A+,+B.C,D,[]!E. diff --git a/testsuite/tests/effects/test1.ml b/testsuite/tests/effects/test1.ml new file mode 100644 index 0000000000..c59c184010 --- /dev/null +++ b/testsuite/tests/effects/test1.ml @@ -0,0 +1,6 @@ +(* TEST + *) + +effect E : unit +let () = + Printf.printf "%d\n%!" @@ try 10 with effect E k -> 11 diff --git a/testsuite/tests/effects/test1.reference b/testsuite/tests/effects/test1.reference new file mode 100644 index 0000000000..f599e28b8a --- /dev/null +++ b/testsuite/tests/effects/test1.reference @@ -0,0 +1 @@ +10 diff --git a/testsuite/tests/effects/test10.ml b/testsuite/tests/effects/test10.ml new file mode 100644 index 0000000000..58308b9bc7 --- /dev/null +++ b/testsuite/tests/effects/test10.ml @@ -0,0 +1,27 @@ +(* TEST + *) + +effect Peek : int +effect Poke : unit + +let rec a i = perform Peek + Random.int i +let rec b i = a i + Random.int i +let rec c i = b i + Random.int i + +let rec d i = + Random.int i + + match c i with + | v -> v + | effect Poke k -> continue k () + +let rec e i = + Random.int i + + match d i with + | v -> v + | effect Peek k -> + ignore (Printexc.get_continuation_callstack k 100); + continue k 42 + +let _ = + ignore (e 1); + print_string "ok\n" diff --git a/testsuite/tests/effects/test10.reference b/testsuite/tests/effects/test10.reference new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/testsuite/tests/effects/test10.reference @@ -0,0 +1 @@ +ok diff --git a/testsuite/tests/effects/test11.ml b/testsuite/tests/effects/test11.ml new file mode 100644 index 0000000000..a55985d088 --- /dev/null +++ b/testsuite/tests/effects/test11.ml @@ -0,0 +1,17 @@ +(* TEST +*) + +(* Tests RESUMETERM with extra_args != 0 in bytecode, + by calling a handler with a tail-continue that returns a function *) +effect E : int + +let handle comp = + match comp () with + | f -> f + | effect E k -> + continue k 10 + +let () = + handle (fun () -> + Printf.printf "%d\n" (perform E); + Printf.printf "%d\n") 42 diff --git a/testsuite/tests/effects/test11.reference b/testsuite/tests/effects/test11.reference new file mode 100644 index 0000000000..5c8f9eaff1 --- /dev/null +++ b/testsuite/tests/effects/test11.reference @@ -0,0 +1,2 @@ +10 +42 diff --git a/testsuite/tests/effects/test2.ml b/testsuite/tests/effects/test2.ml new file mode 100644 index 0000000000..c3d9a6fd04 --- /dev/null +++ b/testsuite/tests/effects/test2.ml @@ -0,0 +1,23 @@ +(* TEST + *) + +open Printf + +effect E : int -> int + +let f () = + printf "perform effect (E 0)\n%!"; + let v = perform (E 0) in + printf "perform returns %d\n%!" v; + v + 1 + +let v = + match f () with + | v -> printf "done %d\n%!" v; v + 1 + | effect (E v) k -> + printf "caught effect (E %d). continuting..\n%!" v; + let v = continue k (v + 1) in + printf "continue returns %d\n%!" v; + v + 1 + +let () = printf "result=%d\n%!" v diff --git a/testsuite/tests/effects/test2.reference b/testsuite/tests/effects/test2.reference new file mode 100644 index 0000000000..951cd4f387 --- /dev/null +++ b/testsuite/tests/effects/test2.reference @@ -0,0 +1,6 @@ +perform effect (E 0) +caught effect (E 0). continuting.. +perform returns 1 +done 2 +continue returns 3 +result=4 diff --git a/testsuite/tests/effects/test3.ml b/testsuite/tests/effects/test3.ml new file mode 100644 index 0000000000..c34cbafa24 --- /dev/null +++ b/testsuite/tests/effects/test3.ml @@ -0,0 +1,14 @@ +(* TEST + *) + +effect E : unit +exception X + +let () = + Printf.printf "%d\n%!" @@ + try + Printf.printf "in handler. raising X\n%!"; + raise X + with + | X -> 10 + | effect E k -> 11 diff --git a/testsuite/tests/effects/test3.reference b/testsuite/tests/effects/test3.reference new file mode 100644 index 0000000000..78ea20d6e8 --- /dev/null +++ b/testsuite/tests/effects/test3.reference @@ -0,0 +1,2 @@ +in handler. raising X +10 diff --git a/testsuite/tests/effects/test4.ml b/testsuite/tests/effects/test4.ml new file mode 100644 index 0000000000..8633cba8be --- /dev/null +++ b/testsuite/tests/effects/test4.ml @@ -0,0 +1,15 @@ +(* TEST + *) + +effect Foo : int -> int + +let r = + try + perform (Foo 3) + with effect (Foo i) k -> + (* continuation called outside try/with *) + try + continue k (i + 1) + with effect (Foo i) k -> failwith "NO" + +let () = Printf.printf "%d\n" r diff --git a/testsuite/tests/effects/test4.reference b/testsuite/tests/effects/test4.reference new file mode 100644 index 0000000000..b8626c4cff --- /dev/null +++ b/testsuite/tests/effects/test4.reference @@ -0,0 +1 @@ +4 diff --git a/testsuite/tests/effects/test5.ml b/testsuite/tests/effects/test5.ml new file mode 100644 index 0000000000..300e8cb1cb --- /dev/null +++ b/testsuite/tests/effects/test5.ml @@ -0,0 +1,18 @@ +(* TEST + *) + +effect Foo : int -> int + +let f () = (perform (Foo 3)) (* 3 + 1 *) + + (perform (Foo 3)) (* 3 + 1 *) + +let r = + try + f () + with effect (Foo i) k -> + (* continuation called outside try/with *) + try + continue k (i + 1) + with effect (Foo i) k -> failwith "NO" + +let () = Printf.printf "%d\n" r diff --git a/testsuite/tests/effects/test5.reference b/testsuite/tests/effects/test5.reference new file mode 100644 index 0000000000..45a4fb75db --- /dev/null +++ b/testsuite/tests/effects/test5.reference @@ -0,0 +1 @@ +8 diff --git a/testsuite/tests/effects/test6.ml b/testsuite/tests/effects/test6.ml new file mode 100644 index 0000000000..8f83e1102b --- /dev/null +++ b/testsuite/tests/effects/test6.ml @@ -0,0 +1,13 @@ +(* TEST + *) + +effect E : unit +effect F : unit +let () = + let ok1 = ref false and ok2 = ref false in + let f r = + try perform E with Unhandled -> r := true in + f ok1; + Printf.printf "%b\n%!" !ok1; + (match f ok2 with () -> () | effect F k -> assert false); + Printf.printf "%b\n%!" !ok2 diff --git a/testsuite/tests/effects/test6.reference b/testsuite/tests/effects/test6.reference new file mode 100644 index 0000000000..bb101b641b --- /dev/null +++ b/testsuite/tests/effects/test6.reference @@ -0,0 +1,2 @@ +true +true diff --git a/testsuite/tests/effects/test7.ml b/testsuite/tests/effects/test7.ml new file mode 100644 index 0000000000..b66749e5c0 --- /dev/null +++ b/testsuite/tests/effects/test7.ml @@ -0,0 +1,11 @@ +(* TEST + *) + +effect E : string + +let _ = + try print_endline @@ "Hello" ^ perform E with + | effect E k -> + let k' = Obj.clone_continuation k in + continue k ""; + continue k' ", again!" diff --git a/testsuite/tests/effects/test7.reference b/testsuite/tests/effects/test7.reference new file mode 100644 index 0000000000..5731df1720 --- /dev/null +++ b/testsuite/tests/effects/test7.reference @@ -0,0 +1,2 @@ +Hello +Hello, again! diff --git a/testsuite/tests/effects/test8.ml b/testsuite/tests/effects/test8.ml new file mode 100644 index 0000000000..dac3609a79 --- /dev/null +++ b/testsuite/tests/effects/test8.ml @@ -0,0 +1,19 @@ +(* TEST + *) + +effect E : string + +let _ = + try + try + print_endline @@ "Hello" ^ perform E + with + | effect E k -> + print_endline "intercepting request.."; + continue k (perform E) + with + | Continuation_already_taken -> Printf.printf "raised Continuation_already_taken\n" + | effect E k -> + let k' = Obj.clone_continuation k in + continue k ""; + continue k' ", again!" diff --git a/testsuite/tests/effects/test8.reference b/testsuite/tests/effects/test8.reference new file mode 100644 index 0000000000..f1cc292f17 --- /dev/null +++ b/testsuite/tests/effects/test8.reference @@ -0,0 +1,3 @@ +intercepting request.. +Hello +raised Continuation_already_taken diff --git a/testsuite/tests/effects/test9.ml b/testsuite/tests/effects/test9.ml new file mode 100644 index 0000000000..3224ea3ecd --- /dev/null +++ b/testsuite/tests/effects/test9.ml @@ -0,0 +1,17 @@ +(* TEST + *) + +effect E : string +effect F : unit + +let _ = + try + try + print_endline @@ "Hello" ^ perform E + with + | effect F _ -> failwith "impossible.." + with + | effect E k -> + let k' = Obj.clone_continuation k in + continue k ""; + continue k' ", again!" diff --git a/testsuite/tests/effects/test9.reference b/testsuite/tests/effects/test9.reference new file mode 100644 index 0000000000..5731df1720 --- /dev/null +++ b/testsuite/tests/effects/test9.reference @@ -0,0 +1,2 @@ +Hello +Hello, again! diff --git a/testsuite/tests/effects/used_cont.ml b/testsuite/tests/effects/used_cont.ml new file mode 100644 index 0000000000..41fea2a313 --- /dev/null +++ b/testsuite/tests/effects/used_cont.ml @@ -0,0 +1,14 @@ +(* TEST + *) + +effect E : unit + +let r = ref None +let () = + match perform E; 42 with + | n -> assert (n = 42) + | effect E k -> + continue k (); + r := Some (k : (unit, unit) continuation); + Gc.full_major (); + print_string "ok\n" diff --git a/testsuite/tests/effects/used_cont.reference b/testsuite/tests/effects/used_cont.reference new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/testsuite/tests/effects/used_cont.reference @@ -0,0 +1 @@ +ok diff --git a/testsuite/tests/formatting/test_locations.dlocations.ocamlopt.clambda.reference b/testsuite/tests/formatting/test_locations.dlocations.ocamlopt.clambda.reference index 53054491e1..3a00b16148 100644 --- a/testsuite/tests/formatting/test_locations.dlocations.ocamlopt.clambda.reference +++ b/testsuite/tests/formatting/test_locations.dlocations.ocamlopt.clambda.reference @@ -4,7 +4,7 @@ cmm: (data int 3063 "camlTest_locations__1": - addr "camlTest_locations__fib_81" + addr "camlTest_locations__fib_82" int 72057594037927941) (data int 1792 global "camlTest_locations" "camlTest_locations": int 1) (data @@ -12,20 +12,20 @@ cmm: "camlTest_locations__gc_roots": addr "camlTest_locations" int 0) -(function{test_locations.ml:42,14-72} camlTest_locations__fib_81 (n: val) +(function{test_locations.ml:42,14-72} camlTest_locations__fib_82 (n: val) (if (<a 3 n) (+ (+ - (app{test_locations.ml:44,9-20} "camlTest_locations__fib_81" (+ n -2) + (app{test_locations.ml:44,9-20} "camlTest_locations__fib_82" (+ n -2) val) - (app{test_locations.ml:44,23-34} "camlTest_locations__fib_81" + (app{test_locations.ml:44,23-34} "camlTest_locations__fib_82" (+ n -4) val)) -1) 3)) (function camlTest_locations__entry () (let clos "camlTest_locations__1" - (store val(root-init) "camlTest_locations" clos)) + (extcall "caml_initialize_field" "camlTest_locations" 0 clos unit)) 1) (data) diff --git a/testsuite/tests/formatting/test_locations.dno-locations.ocamlopt.clambda.reference b/testsuite/tests/formatting/test_locations.dno-locations.ocamlopt.clambda.reference index eec611773e..e870882345 100644 --- a/testsuite/tests/formatting/test_locations.dno-locations.ocamlopt.clambda.reference +++ b/testsuite/tests/formatting/test_locations.dno-locations.ocamlopt.clambda.reference @@ -4,7 +4,7 @@ cmm: (data int 3063 "camlTest_locations__1": - addr "camlTest_locations__fib_81" + addr "camlTest_locations__fib_82" int 72057594037927941) (data int 1792 global "camlTest_locations" "camlTest_locations": int 1) (data @@ -12,17 +12,17 @@ cmm: "camlTest_locations__gc_roots": addr "camlTest_locations" int 0) -(function camlTest_locations__fib_81 (n: val) +(function camlTest_locations__fib_82 (n: val) (if (<a 3 n) (+ - (+ (app "camlTest_locations__fib_81" (+ n -2) val) - (app "camlTest_locations__fib_81" (+ n -4) val)) + (+ (app "camlTest_locations__fib_82" (+ n -2) val) + (app "camlTest_locations__fib_82" (+ n -4) val)) -1) 3)) (function camlTest_locations__entry () (let clos "camlTest_locations__1" - (store val(root-init) "camlTest_locations" clos)) + (extcall "caml_initialize_field" "camlTest_locations" 0 clos unit)) 1) (data) diff --git a/testsuite/tests/functors/functors.compilers.reference b/testsuite/tests/functors/functors.compilers.reference index a3ae39de50..17bc253eac 100644 --- a/testsuite/tests/functors/functors.compilers.reference +++ b/testsuite/tests/functors/functors.compilers.reference @@ -4,7 +4,7 @@ (module-defn(O) Functors functors.ml(12):184-279 (function X is_a_functor always_inline (let - (cow = (function x[int] : int (apply (field 0 X) x)) + (cow = (function x[int] : int (apply (field_imm 0 X) x)) sheep = (function x[int] : int (+ 1 (apply cow x)))) (makeblock 0 cow sheep)))) F = @@ -13,7 +13,7 @@ (let (cow = (function x[int] : int - (apply (field 0 Y) (apply (field 0 X) x))) + (apply (field_imm 0 Y) (apply (field_imm 0 X) x))) sheep = (function x[int] : int (+ 1 (apply cow x)))) (makeblock 0 cow sheep)))) F1 = @@ -22,17 +22,17 @@ (let (sheep = (function x[int] : int - (+ 1 (apply (field 0 Y) (apply (field 0 X) x))))) + (+ 1 (apply (field_imm 0 Y) (apply (field_imm 0 X) x))))) (makeblock 0 sheep)))) F2 = (module-defn(F2) Functors functors.ml(36):634-784 (function X Y is_a_functor always_inline (let - (X =a (makeblock 0 (field 1 X)) - Y =a (makeblock 0 (field 1 Y)) + (X =a (makeblock 0 (field_mut 1 X)) + Y =a (makeblock 0 (field_mut 1 Y)) sheep = (function x[int] : int - (+ 1 (apply (field 0 Y) (apply (field 0 X) x))))) + (+ 1 (apply (field_imm 0 Y) (apply (field_imm 0 X) x))))) (makeblock 0 sheep)))) M = (module-defn(M) Functors functors.ml(41):786-970 @@ -43,14 +43,14 @@ (let (cow = (function x[int] : int - (apply (field 0 Y) (apply (field 0 X) x))) + (apply (field_imm 0 Y) (apply (field_imm 0 X) x))) sheep = (function x[int] : int (+ 1 (apply cow x)))) (makeblock 0 cow sheep))))) (makeblock 0 (function funarg funarg is_a_functor stub (let (let = - (apply F (makeblock 0 (field 1 funarg)) - (makeblock 0 (field 1 funarg)))) - (makeblock 0 (field 1 let)))))))) + (apply F (makeblock 0 (field_mut 1 funarg)) + (makeblock 0 (field_mut 1 funarg)))) + (makeblock 0 (field_mut 1 let)))))))) (makeblock 0 O F F1 F2 M))) diff --git a/testsuite/tests/gc-roots/globrootsprim.c b/testsuite/tests/gc-roots/globrootsprim.c index 0eb777b0a5..28d6fb9418 100644 --- a/testsuite/tests/gc-roots/globrootsprim.c +++ b/testsuite/tests/gc-roots/globrootsprim.c @@ -13,10 +13,13 @@ /* For testing global root registration */ +#define CAML_INTERNALS + #include "caml/mlvalues.h" #include "caml/memory.h" #include "caml/alloc.h" #include "caml/gc.h" +#include "caml/shared_heap.h" #include "caml/callback.h" struct block { value header; value v; }; @@ -32,7 +35,7 @@ value gb_get(value vblock) value gb_classic_register(value v) { struct block * b = caml_stat_alloc(sizeof(struct block)); - b->header = Make_header(1, 0, Caml_black); + b->header = Make_header(1, 0, NOT_MARKABLE); b->v = v; caml_register_global_root(&(b->v)); return Val_block(b); @@ -53,7 +56,7 @@ value gb_classic_remove(value vblock) value gb_generational_register(value v) { struct block * b = caml_stat_alloc(sizeof(struct block)); - b->header = Make_header(1, 0, Caml_black); + b->header = Make_header(1, 0, NOT_MARKABLE); b->v = v; caml_register_generational_global_root(&(b->v)); return Val_block(b); diff --git a/testsuite/tests/generalized-open/gpr1506.ml b/testsuite/tests/generalized-open/gpr1506.ml index 52ff509d32..c36eaafe6c 100644 --- a/testsuite/tests/generalized-open/gpr1506.ml +++ b/testsuite/tests/generalized-open/gpr1506.ml @@ -103,9 +103,9 @@ include struct open struct type t = T end let x = T end Line 1, characters 15-41: 1 | include struct open struct type t = T end let x = T end ^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: The type t/150 introduced by this open appears in the signature +Error: The type t/151 introduced by this open appears in the signature Line 1, characters 46-47: - The value x has no valid type if t/150 is hidden + The value x has no valid type if t/151 is hidden |}];; module A = struct @@ -123,9 +123,9 @@ Lines 3-6, characters 4-7: 4 | type t = T 5 | let x = T 6 | end -Error: The type t/155 introduced by this open appears in the signature +Error: The type t/156 introduced by this open appears in the signature Line 7, characters 8-9: - The value y has no valid type if t/155 is hidden + The value y has no valid type if t/156 is hidden |}];; module A = struct @@ -142,9 +142,9 @@ Lines 3-5, characters 4-7: 3 | ....open struct 4 | type t = T 5 | end -Error: The type t/160 introduced by this open appears in the signature +Error: The type t/161 introduced by this open appears in the signature Line 6, characters 8-9: - The value y has no valid type if t/160 is hidden + The value y has no valid type if t/161 is hidden |}] (* It was decided to not allow this anymore. *) diff --git a/testsuite/tests/lazy/lazy2.ml b/testsuite/tests/lazy/lazy2.ml new file mode 100644 index 0000000000..cccbd96d71 --- /dev/null +++ b/testsuite/tests/lazy/lazy2.ml @@ -0,0 +1,10 @@ +(* TEST + ocamlopt_flags += " -O3 " +*) + +open Domain + +let () = + let l = lazy (print_string "Lazy Forced\n") in + let d = spawn (fun () -> Lazy.force l) in + join d diff --git a/testsuite/tests/lazy/lazy2.reference b/testsuite/tests/lazy/lazy2.reference new file mode 100644 index 0000000000..9a0db54156 --- /dev/null +++ b/testsuite/tests/lazy/lazy2.reference @@ -0,0 +1 @@ +Lazy Forced diff --git a/testsuite/tests/lazy/lazy3.ml b/testsuite/tests/lazy/lazy3.ml new file mode 100644 index 0000000000..a22a0893b9 --- /dev/null +++ b/testsuite/tests/lazy/lazy3.ml @@ -0,0 +1,27 @@ +(* TEST + ocamlopt_flags += " -O3 " +*) + +let f count = + let _n = (Domain.self ():> int) in + let r = ref 0 in + for i = 1 to count do + incr r; + done; + !r + +let main () = + let l = lazy (f 1_000_000_000) in + let d1 = + Domain.spawn (fun () -> + let _n = (Domain.self ():> int) in + Lazy.force l) + in + let n2 = Lazy.force l in + let n1 = Domain.join d1 in + (n1, n2) + +let _ = + match main () with + | (n1, n2) -> Printf.printf "n1=%d n2=%d\n" n1 n2 + | exception Lazy.Undefined -> print_endline "Undefined" diff --git a/testsuite/tests/lazy/lazy3.reference b/testsuite/tests/lazy/lazy3.reference new file mode 100644 index 0000000000..bcd790260a --- /dev/null +++ b/testsuite/tests/lazy/lazy3.reference @@ -0,0 +1 @@ +Undefined diff --git a/testsuite/tests/lazy/lazy4.ml b/testsuite/tests/lazy/lazy4.ml new file mode 100644 index 0000000000..3988318c79 --- /dev/null +++ b/testsuite/tests/lazy/lazy4.ml @@ -0,0 +1,15 @@ +(* TEST + ocamlopt_flags += " -O3 " +*) +let r = ref None + +let f () = + match !r with + | Some l -> Lazy.force l + | None -> () + +let l = Lazy.from_fun f +let _ = r := Some l +let _ = + try Lazy.force l + with Lazy.Undefined -> print_endline "Undefined" diff --git a/testsuite/tests/lazy/lazy4.reference b/testsuite/tests/lazy/lazy4.reference new file mode 100644 index 0000000000..bcd790260a --- /dev/null +++ b/testsuite/tests/lazy/lazy4.reference @@ -0,0 +1 @@ +Undefined diff --git a/testsuite/tests/lazy/lazy5.ml b/testsuite/tests/lazy/lazy5.ml new file mode 100644 index 0000000000..3bfc474af8 --- /dev/null +++ b/testsuite/tests/lazy/lazy5.ml @@ -0,0 +1,28 @@ +(* TEST + ocamlopt_flags += " -O3 " +*) +let rec safe_force l = + match Lazy.try_force l with + | Some x -> x + | None -> ( + Domain.Sync.cpu_relax () ; + safe_force l + ) + +let f count = + let _n = (Domain.self ():> int) in + let r = ref 0 in + for i = 1 to count do + incr r; + done; + !r + +let l = lazy (f 1_000_000_000) +let d1 = + Domain.spawn (fun () -> + let _n = (Domain.self ():> int) in + safe_force l) +let n2 = safe_force l +let n1 = Domain.join d1 + +let _ = Printf.printf "n1=%d n2=%d\n" n1 n2 diff --git a/testsuite/tests/lazy/lazy5.reference b/testsuite/tests/lazy/lazy5.reference new file mode 100644 index 0000000000..b6706a70ab --- /dev/null +++ b/testsuite/tests/lazy/lazy5.reference @@ -0,0 +1 @@ +n1=1000000000 n2=1000000000 diff --git a/testsuite/tests/lazy/minor_major_force.ml b/testsuite/tests/lazy/minor_major_force.ml new file mode 100644 index 0000000000..b18fe44a9b --- /dev/null +++ b/testsuite/tests/lazy/minor_major_force.ml @@ -0,0 +1,73 @@ +(* TEST + ocamlopt_flags += " -O3 " +*) + +(* + - create a record with a mutable field that has a lazy value in it + - force a minor_gc to make sure that record is on the heap + - update the lazy value to be a minor heap value + - force the lazy value to be a forward to an item in the minor heap + - call minor_gc and watch it fail the assert which makes sure that all remembered set items have been forwarded +*) + +type test_record = { + mutable lzy_str: string Lazy.t; + mutable lzy_int: int Lazy.t; +} + +let is_shared x = Obj.is_shared (Obj.repr x) + +let glbl_int = ref 0 +let glbl_string = ref "init" + +let get_random_int () = + Random.int 256 + +let get_random_string () = + Printf.sprintf "%f" (Random.float 1.) + + +let get_lazy_status fmt_str x = + if Lazy.is_val x then + Printf.sprintf fmt_str (Lazy.force x) + else + "<not forced>" + +let get_lazy_int_status x = get_lazy_status "%d" x +let get_lazy_string_status x = get_lazy_status "%s" x + +let dump_record_status x = + Printf.printf "x.lzy_string=%s [shared=%b]\n" (get_lazy_string_status x.lzy_str) (is_shared x.lzy_str); + Printf.printf "x.lzy_int=%s [shared=%b]\n" (get_lazy_int_status x.lzy_int) (is_shared x.lzy_int) + +let force_lazy_vals x = + let v = Lazy.force x.lzy_str in + Printf.printf "forcing x.lzy_str [%s] %b %d\n%!" v (is_shared x.lzy_str) (Obj.tag (Obj.repr x.lzy_str)); + let v = Lazy.force x.lzy_int in + Printf.printf "forcing x.lzy_int [%d] %b %d\n%!" v (is_shared x.lzy_int) (Obj.tag (Obj.repr x.lzy_int)) + +let do_minor_gc () = + Printf.printf "Gc.minor ()\n%!"; + Gc.minor () + +let () = + Random.init 34; + let x = { + lzy_str = lazy (glbl_string := get_random_string (); !glbl_string); + lzy_int = lazy (glbl_int := get_random_int (); !glbl_int); + } in + + do_minor_gc (); + (* x should now be on the heap *) + dump_record_status x; + Printf.printf "x is setup on major heap\n\n%!"; + + Printf.printf "updating fields in x\n\n%!"; + x.lzy_str <- lazy (glbl_string := get_random_string (); !glbl_string); + x.lzy_int <- lazy (glbl_int := get_random_int (); !glbl_int); + dump_record_status x; + + force_lazy_vals x; + dump_record_status x; + do_minor_gc (); + dump_record_status x diff --git a/testsuite/tests/lazy/minor_major_force.reference b/testsuite/tests/lazy/minor_major_force.reference new file mode 100644 index 0000000000..af75cd6e63 --- /dev/null +++ b/testsuite/tests/lazy/minor_major_force.reference @@ -0,0 +1,16 @@ +Gc.minor () +x.lzy_string=<not forced> [shared=true] +x.lzy_int=<not forced> [shared=true] +x is setup on major heap + +updating fields in x + +x.lzy_string=<not forced> [shared=false] +x.lzy_int=<not forced> [shared=false] +forcing x.lzy_str [0.152944] false 250 +forcing x.lzy_int [175] false 250 +x.lzy_string=0.152944 [shared=false] +x.lzy_int=175 [shared=false] +Gc.minor () +x.lzy_string=0.152944 [shared=true] +x.lzy_int=175 [shared=true] diff --git a/testsuite/tests/letrec-compilation/modrec.ml b/testsuite/tests/letrec-compilation/modrec.ml new file mode 100644 index 0000000000..b467039fa7 --- /dev/null +++ b/testsuite/tests/letrec-compilation/modrec.ml @@ -0,0 +1,8 @@ +module rec M : sig + val f : unit -> unit + val g : unit -> unit +end = struct + let rec f () = () and g () = () +end + +let () = print_endline "ok" diff --git a/testsuite/tests/letrec-compilation/modrec.reference b/testsuite/tests/letrec-compilation/modrec.reference new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/testsuite/tests/letrec-compilation/modrec.reference @@ -0,0 +1 @@ +ok diff --git a/testsuite/tests/lib-dynlink-initializers/test10_main.native.reference b/testsuite/tests/lib-dynlink-initializers/test10_main.native.reference index 30d9984363..0e84488d01 100755 --- a/testsuite/tests/lib-dynlink-initializers/test10_main.native.reference +++ b/testsuite/tests/lib-dynlink-initializers/test10_main.native.reference @@ -1,9 +1,5 @@ Error: Failure("Plugin error") -Raised at Stdlib.failwith in file "stdlib.ml", line 29, characters 17-33 -Called from Test10_plugin.g in file "test10_plugin.ml", line 2, characters 15-38 -Called from Test10_plugin in file "test10_plugin.ml", line 10, characters 2-6 -Called from Dynlink.Native.run.(fun) in file "otherlibs/dynlink/native/dynlink.ml", line 85, characters 12-29 -Called from Dynlink.Native.run.(fun) in file "otherlibs/dynlink/native/dynlink.ml", line 85, characters 12-29 +Raised by primitive operation at Dynlink.Native.run.(fun) in file "otherlibs/dynlink/native/dynlink.ml", line 85, characters 12-29 Re-raised at Dynlink.Native.run.(fun) in file "otherlibs/dynlink/native/dynlink.ml", line 87, characters 10-149 Called from Stdlib__list.iter in file "list.ml", line 110, characters 12-15 Called from Dynlink_common.Make.load.(fun) in file "otherlibs/dynlink/dynlink_common.ml", line 347, characters 13-44 diff --git a/testsuite/tests/lib-obj/reachable_words_np.ml b/testsuite/tests/lib-obj/reachable_words_np.ml deleted file mode 100644 index 8a50268d20..0000000000 --- a/testsuite/tests/lib-obj/reachable_words_np.ml +++ /dev/null @@ -1,21 +0,0 @@ -(* TEST - * naked_pointers - ** bytecode - ** native -*) - -let native = - match Sys.backend_type with - | Sys.Native -> true - | Sys.Bytecode -> false - | Sys.Other s -> print_endline s; assert false - -let size x = Obj.reachable_words (Obj.repr x) - -let expect_size s x = - let i = size x in - if i <> s then - Printf.printf "size = %i; expected = %i\n%!" i s - -let () = - expect_size (if native then 0 else 3) (1, 2) diff --git a/testsuite/tests/lib-systhreads/testpreempt.ml b/testsuite/tests/lib-systhreads-todo/testpreempt.ml index 11d69152d6..11d69152d6 100644 --- a/testsuite/tests/lib-systhreads/testpreempt.ml +++ b/testsuite/tests/lib-systhreads-todo/testpreempt.ml diff --git a/testsuite/tests/lib-systhreads/testpreempt.reference b/testsuite/tests/lib-systhreads-todo/testpreempt.reference index 9599527514..9599527514 100644 --- a/testsuite/tests/lib-systhreads/testpreempt.reference +++ b/testsuite/tests/lib-systhreads-todo/testpreempt.reference diff --git a/testsuite/tests/lib-systhreads/threadsigmask.ml b/testsuite/tests/lib-systhreads-todo/threadsigmask.ml index acfaaf9319..acfaaf9319 100644 --- a/testsuite/tests/lib-systhreads/threadsigmask.ml +++ b/testsuite/tests/lib-systhreads-todo/threadsigmask.ml diff --git a/testsuite/tests/lib-systhreads/threadsigmask.reference b/testsuite/tests/lib-systhreads-todo/threadsigmask.reference index d86bac9de5..d86bac9de5 100644 --- a/testsuite/tests/lib-systhreads/threadsigmask.reference +++ b/testsuite/tests/lib-systhreads-todo/threadsigmask.reference diff --git a/testsuite/tests/lib-systhreads/test_c_thread_register.ml b/testsuite/tests/lib-systhreads/test_c_thread_register.ml new file mode 100644 index 0000000000..01e7f35fd3 --- /dev/null +++ b/testsuite/tests/lib-systhreads/test_c_thread_register.ml @@ -0,0 +1,19 @@ +(* TEST + modules = "test_c_thread_register_cstubs.c" + * hassysthreads + include systhreads + ** not-bsd + *** libunix + **** bytecode + **** native +*) + +(* spins a external thread from C and register it to the OCaml runtime *) + +external spawn_thread : (unit -> unit) -> unit = "spawn_thread" + +let passed () = Printf.printf "passed\n" + +let _ = + spawn_thread (passed); + Thread.delay 0.5 diff --git a/testsuite/tests/lib-systhreads/test_c_thread_register.reference b/testsuite/tests/lib-systhreads/test_c_thread_register.reference new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/testsuite/tests/lib-systhreads/test_c_thread_register.reference @@ -0,0 +1 @@ +passed diff --git a/testsuite/tests/lib-systhreads/test_c_thread_register_cstubs.c b/testsuite/tests/lib-systhreads/test_c_thread_register_cstubs.c new file mode 100644 index 0000000000..9fd7858978 --- /dev/null +++ b/testsuite/tests/lib-systhreads/test_c_thread_register_cstubs.c @@ -0,0 +1,27 @@ +#include <string.h> +#include <pthread.h> +#include "caml/mlvalues.h" +#include "caml/gc.h" +#include "caml/memory.h" +#include "caml/callback.h" +#include "threads.h" + +void *thread_func(void *fn) { + caml_c_thread_register(); + caml_acquire_runtime_system(); + caml_callback((value) fn, Val_unit); + caml_release_runtime_system(); + caml_c_thread_unregister(); + return 0; +} + +value spawn_thread(value clos) +{ + pthread_t thr; + pthread_attr_t attr; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&thr, &attr, thread_func, (void *) clos); + return Val_unit; +} diff --git a/testsuite/tests/lib-systhreads/testfork2.ml b/testsuite/tests/lib-systhreads/testfork2.ml new file mode 100644 index 0000000000..9f95024eee --- /dev/null +++ b/testsuite/tests/lib-systhreads/testfork2.ml @@ -0,0 +1,37 @@ +(* TEST + * hassysthreads + include systhreads + ** not-bsd + *** libunix + **** bytecode + **** native +*) + +(* POSIX threads and fork() *) + +let alloc_string () = ignore(String.make 2048 '0') + +let compute_thread () = + Thread.create begin fun () -> + alloc_string () + end () + +let fork () = + match Unix.fork() with + | 0 -> + alloc_string (); + print_string "passed"; + print_newline (); + Thread.delay 1.0; + exit 0 + | pid -> + Thread.delay 4.0; + exit 0 + +let main () = + ignore(compute_thread ()); + ignore(compute_thread ()); + ignore(compute_thread ()); + fork () + +let _ = main() diff --git a/testsuite/tests/lib-systhreads/testfork2.reference b/testsuite/tests/lib-systhreads/testfork2.reference new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/testsuite/tests/lib-systhreads/testfork2.reference @@ -0,0 +1 @@ +passed diff --git a/testsuite/tests/lib-threads/trylock.ml b/testsuite/tests/lib-threads/trylock.ml new file mode 100644 index 0000000000..ba36d58f15 --- /dev/null +++ b/testsuite/tests/lib-threads/trylock.ml @@ -0,0 +1,19 @@ +(* TEST + +* hassysthreads +include systhreads +** bytecode +** native + +*) + +(* Test Mutex.try_lock *) + +let () = + let m = Mutex.create () in + Mutex.lock m; + let res = Mutex.try_lock m in + if res = false then + print_endline "passed" + else + print_endline "FAILED (try_lock returned true)" diff --git a/testsuite/tests/lib-threads/trylock.reference b/testsuite/tests/lib-threads/trylock.reference new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/testsuite/tests/lib-threads/trylock.reference @@ -0,0 +1 @@ +passed diff --git a/testsuite/tests/lib-threads/trylock2.ml b/testsuite/tests/lib-threads/trylock2.ml new file mode 100644 index 0000000000..8d66fa8a4f --- /dev/null +++ b/testsuite/tests/lib-threads/trylock2.ml @@ -0,0 +1,16 @@ +(* TEST + +* hassysthreads +include systhreads +** bytecode +** native + +*) + +(* Test Mutex.try_lock *) + +let () = + let m = Mutex.create () in + assert (Mutex.try_lock m); + Mutex.unlock m; + print_endline "passed" diff --git a/testsuite/tests/lib-threads/trylock2.reference b/testsuite/tests/lib-threads/trylock2.reference new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/testsuite/tests/lib-threads/trylock2.reference @@ -0,0 +1 @@ +passed diff --git a/testsuite/tests/parallel/atomics.ml b/testsuite/tests/parallel/atomics.ml new file mode 100644 index 0000000000..9c1d0a3cf2 --- /dev/null +++ b/testsuite/tests/parallel/atomics.ml @@ -0,0 +1,64 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +type u = U of unit +let () = + (* See https://github.com/ocaml-multicore/ocaml-multicore/issues/252 *) + let make_cell (x : unit) : u Atomic.t = + let cell = Atomic.make (U x) in + Atomic.set cell (U x) ; + cell in + (* the error shows up with an array of length 256 or larger *) + let a = Array.make 256 (make_cell ()) in + ignore (Sys.opaque_identity a) + + +let test_fetch_add () = + let ndoms = 4 in + let count = 10000 in + let arr = Array.make (ndoms * count) (-1) in + let step = 1493 in + let r = Atomic.make 0 in + (* step is relatively prime to Array.length arr *) + let loop () = + let self = (Domain.self () :> int) in + for i = 1 to count do + let n = Atomic.fetch_and_add r step mod Array.length arr in + assert (arr.(n) == (-1)); + arr.(n) <- self + done in + let _ = Array.init 4 (fun i -> + Domain.spawn loop) + |> Array.map Domain.join in + assert (Array.for_all (fun x -> x >= 0) arr) + +let () = + test_fetch_add (); + print_endline "ok" + + + + +let test v = + let open Atomic in + assert (get v = 42); + set v 10; + assert (get v = 10); + let b = compare_and_set v 11 20 in + assert (b = false); + assert (get v = 10); + let b = compare_and_set v 10 20 in + assert (b = true); + assert (get v = 20) + +let () = + let r = Atomic.make 42 in + test r; + Atomic.set r 42; + Gc.full_major (); + test r; + print_endline "ok" diff --git a/testsuite/tests/parallel/atomics.reference b/testsuite/tests/parallel/atomics.reference new file mode 100644 index 0000000000..79ebd0860f --- /dev/null +++ b/testsuite/tests/parallel/atomics.reference @@ -0,0 +1,2 @@ +ok +ok diff --git a/testsuite/tests/parallel/backup_thread.ml b/testsuite/tests/parallel/backup_thread.ml new file mode 100644 index 0000000000..05b06cc47c --- /dev/null +++ b/testsuite/tests/parallel/backup_thread.ml @@ -0,0 +1,17 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + + +let _ = + (* start a dummy domain and shut it down to cause a domain reuse *) + let d = Domain.spawn (fun _ -> ()) in + Domain.join d; + let _d = Domain.spawn (fun _ -> + Unix.sleep 10; + print_endline "Should not reach here!") in + Gc.full_major (); + print_endline "OK" diff --git a/testsuite/tests/parallel/backup_thread.reference b/testsuite/tests/parallel/backup_thread.reference new file mode 100644 index 0000000000..d86bac9de5 --- /dev/null +++ b/testsuite/tests/parallel/backup_thread.reference @@ -0,0 +1 @@ +OK diff --git a/testsuite/tests/parallel/backup_thread_pipe.ml b/testsuite/tests/parallel/backup_thread_pipe.ml new file mode 100644 index 0000000000..41fd101c1f --- /dev/null +++ b/testsuite/tests/parallel/backup_thread_pipe.ml @@ -0,0 +1,22 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + + +let producer oc = output_string oc "passed\n"; close_out oc + +let consumer ic = print_endline @@ input_line ic; close_in ic + +let main () = + let (in_fd, out_fd) = Unix.pipe() in + let ipipe = Unix.in_channel_of_descr in_fd in + let opipe = Unix.out_channel_of_descr out_fd in + let prod = Domain.spawn (fun () -> Unix.sleep 3; Gc.full_major(); producer opipe) in + let cons = Domain.spawn (fun () -> consumer ipipe) in + Domain.join prod; + Domain.join cons + +let _ = Unix.handle_unix_error main (); exit 0 diff --git a/testsuite/tests/parallel/backup_thread_pipe.reference b/testsuite/tests/parallel/backup_thread_pipe.reference new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/testsuite/tests/parallel/backup_thread_pipe.reference @@ -0,0 +1 @@ +passed diff --git a/testsuite/tests/parallel/constpromote.ml b/testsuite/tests/parallel/constpromote.ml new file mode 100644 index 0000000000..fc9fd65ff6 --- /dev/null +++ b/testsuite/tests/parallel/constpromote.ml @@ -0,0 +1,19 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +(* when run with the bytecode debug runtime, this test + used to trigger a bug where the constant [13] + remained unpromoted *) + +let rec burn l = + if List.hd l > 14 then () + else burn (l @ l |> List.map (fun x -> x + 1)) + +let () = + ignore (Domain.spawn (fun () -> burn [13])); + burn [0]; + Printf.printf "all done\n%!" diff --git a/testsuite/tests/parallel/constpromote.reference b/testsuite/tests/parallel/constpromote.reference new file mode 100644 index 0000000000..de63914305 --- /dev/null +++ b/testsuite/tests/parallel/constpromote.reference @@ -0,0 +1 @@ +all done diff --git a/testsuite/tests/parallel/deadcont.ml b/testsuite/tests/parallel/deadcont.ml new file mode 100644 index 0000000000..b00ab6e0e2 --- /dev/null +++ b/testsuite/tests/parallel/deadcont.ml @@ -0,0 +1,44 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +(* + Test handling of continuations created by a domain that has since terminated. + Bug report and testcase by Žiga Lukšič, see: + https://github.com/ocamllabs/ocaml-multicore/issues/175 + *) + +effect Poke : unit + +type result = Done | Poking of (unit -> result) + +(* Debug help. *) +let print s = print_string s; Format.pp_print_flush Format.std_formatter () + +(* Just poke the handler n times. *) +let rec poke = function + | 0 -> () + | n -> perform Poke; poke (n-1) + +(* The handler inside the domain, that captures the continuation whenever + it gets poked. *) +let domain_handler f = + match f () with + | effect Poke k -> Poking (fun () -> print "..."; continue k () |> ignore; print "success\n"; Done) + | () -> Done + +(* Re-runs the poker that happened inside a domain. *) +let rerunner = function + | Poking f -> f () (*re-runs the function*) + | Done -> Done + +(* Test. *) +let test n = + (* Messy handler wrapping. *) + let inner () = domain_handler (fun () -> poke n) in + rerunner (Domain.join (Domain.spawn inner)) + +let _ = test 100 |> ignore; print_endline "done" diff --git a/testsuite/tests/parallel/deadcont.reference b/testsuite/tests/parallel/deadcont.reference new file mode 100644 index 0000000000..cb738d6524 --- /dev/null +++ b/testsuite/tests/parallel/deadcont.reference @@ -0,0 +1,2 @@ +...success +done diff --git a/testsuite/tests/parallel/domain_dls.ml b/testsuite/tests/parallel/domain_dls.ml new file mode 100644 index 0000000000..4e416f7f0c --- /dev/null +++ b/testsuite/tests/parallel/domain_dls.ml @@ -0,0 +1,23 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +let check () = + let k1 = Domain.DLS.new_key (fun () -> 10) in + let k2 = Domain.DLS.new_key (fun () -> 1.0) in + Domain.DLS.set k1 100; + Domain.DLS.set k2 200.0; + let v1 = Domain.DLS.get k1 in + let v2 = Domain.DLS.get k2 in + assert (v1 = 100); + assert (v2 = 200.0); + Gc.major () + +let _ = + let domains = Array.init 3 (fun _ -> Domain.spawn(check)) in + check (); + Array.iter Domain.join domains; + print_endline "ok" diff --git a/testsuite/tests/parallel/domain_dls.reference b/testsuite/tests/parallel/domain_dls.reference new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/testsuite/tests/parallel/domain_dls.reference @@ -0,0 +1 @@ +ok diff --git a/testsuite/tests/parallel/domain_id.ml b/testsuite/tests/parallel/domain_id.ml new file mode 100644 index 0000000000..cc2c6e6fe1 --- /dev/null +++ b/testsuite/tests/parallel/domain_id.ml @@ -0,0 +1,68 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +open Domain + +let id () = () + + +let newdom_id () = + let d = Domain.spawn id in + let n = Domain.get_id d in + join d; + (n :> int) + +let test_domain_reuse () = + (* checks that domain slots are getting reused quickly, + by checking that subsequent domain IDs are an arithmetic + progression (implies that you're getting the same domain + over and over, but its ID increases by Max_domains. + + this test has to run first, since it makes assumptions + about domain IDs *) + let first = newdom_id () in + let curr = ref (newdom_id ()) in + let delta = !curr - first in + assert (delta > 0); + for i = 1 to 10000 do + let next = newdom_id () in + assert (next - !curr = delta); + curr := next + done + + +let test_different_ids () = + let d1 = Domain.spawn id in + let d2 = Domain.spawn id in + assert (get_id d1 <> get_id d2); + join d1; join d2; + let d3 = Domain.spawn id in + assert (get_id d1 <> get_id d3) + +let test_interrupt_routing () = + (* checks that domains do not get each others interrupts, + even if they reuse the same internal domain *) + let d1 = Domain.spawn id in + join d1; + let r = Atomic.make false in + let d2 = Domain.spawn (fun () -> + Sync.(critical_section (fun () -> + Atomic.set r true; wait (); Atomic.set r false))) in + while not (Atomic.get r) do () done; + Sync.notify (get_id d1); (* d2 must not get this interrupt *) + for i = 1 to 100000 do + assert (Atomic.get r = true) + done; + Sync.notify (get_id d2); + join d2; + assert (Atomic.get r = false) + +let () = + test_domain_reuse (); + test_interrupt_routing (); + test_different_ids (); + print_endline "ok" diff --git a/testsuite/tests/parallel/domain_id.reference b/testsuite/tests/parallel/domain_id.reference new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/testsuite/tests/parallel/domain_id.reference @@ -0,0 +1 @@ +ok diff --git a/testsuite/tests/parallel/domain_parallel_spawn_burn.ml b/testsuite/tests/parallel/domain_parallel_spawn_burn.ml new file mode 100644 index 0000000000..98335c3042 --- /dev/null +++ b/testsuite/tests/parallel/domain_parallel_spawn_burn.ml @@ -0,0 +1,43 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +open Domain + +(* This test looks to spawn domains while doing a bunch of explicit minor and major GC calls + from parallel domains *) + +let rec burn l = + if List.hd l > 14 then () + else + burn (l @ l |> List.map (fun x -> x + 1)) + +let test_parallel_spawn () = + for i = 1 to 20 do + let a = Array.init 25 (fun _ -> Domain.spawn (fun () -> burn [0])) in + for j = 0 to 24 do + join a.(j) + done + done + +let () = + let running = ref true in + let rec run_until_stop fn () = + while !running do + fn (); + done + in + + let domain_minor_gc = Domain.spawn (run_until_stop (fun () -> burn [8]; Gc.minor ())) in + let domain_major_gc = Domain.spawn (run_until_stop (fun () -> burn [8]; Gc.major ())) in + + test_parallel_spawn (); + + running := false; + join domain_minor_gc; + join domain_major_gc; + + print_endline "ok" diff --git a/testsuite/tests/parallel/domain_parallel_spawn_burn.reference b/testsuite/tests/parallel/domain_parallel_spawn_burn.reference new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/testsuite/tests/parallel/domain_parallel_spawn_burn.reference @@ -0,0 +1 @@ +ok diff --git a/testsuite/tests/parallel/domain_serial_spawn_burn.ml b/testsuite/tests/parallel/domain_serial_spawn_burn.ml new file mode 100644 index 0000000000..fd4c35bf1e --- /dev/null +++ b/testsuite/tests/parallel/domain_serial_spawn_burn.ml @@ -0,0 +1,49 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +open Domain + +(* This test looks to spawn domains while doing a bunch of explicit minor and major GC calls + from parallel domains *) + +let rec burn l = + if List.hd l > 14 then () + else + burn (l @ l |> List.map (fun x -> x + 1)) + +let test_serial_domain_spawn () = + for i = 1 to 250 do + let d = Domain.spawn (fun () -> burn [0]) in + join d + done + +let test_parallel_spawn () = + for i = 1 to 10 do + let a = Array.init 25 (fun _ -> Domain.spawn (fun () -> burn [0])) in + for j = 0 to 24 do + join a.(j) + done + done + +let () = + let running = ref true in + let rec run_until_stop fn () = + while !running do + fn (); + done + in + + let domain_minor_gc = Domain.spawn (run_until_stop (fun () -> burn [8]; Gc.minor ())) in + let domain_major_gc = Domain.spawn (run_until_stop (fun () -> burn [8]; Gc.major ())) in + + test_serial_domain_spawn (); + + running := false; + join domain_minor_gc; + join domain_major_gc; + + print_endline "ok" diff --git a/testsuite/tests/parallel/domain_serial_spawn_burn.reference b/testsuite/tests/parallel/domain_serial_spawn_burn.reference new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/testsuite/tests/parallel/domain_serial_spawn_burn.reference @@ -0,0 +1 @@ +ok diff --git a/testsuite/tests/parallel/fib_threads.ml b/testsuite/tests/parallel/fib_threads.ml new file mode 100644 index 0000000000..f6005729b7 --- /dev/null +++ b/testsuite/tests/parallel/fib_threads.ml @@ -0,0 +1,23 @@ +(* TEST +* hassysthreads +include systhreads +** bytecode +** native +*) + + +let n = 42 +let num_domains = try int_of_string Sys.argv.(1) with _ -> 4 + +let rec fib n = + if (n < 2) then n + else fib (n - 1) + fib (n - 2) + +let th_create () = + let t = Thread.create fib in + Thread.join (t n) + +let _ = + let domains = Array.init num_domains (fun _ -> Domain.spawn(th_create)) in + Array.iter Domain.join domains; + print_endline "done" diff --git a/testsuite/tests/parallel/fib_threads.reference b/testsuite/tests/parallel/fib_threads.reference new file mode 100644 index 0000000000..19f86f493a --- /dev/null +++ b/testsuite/tests/parallel/fib_threads.reference @@ -0,0 +1 @@ +done diff --git a/testsuite/tests/parallel/interrupt.ml b/testsuite/tests/parallel/interrupt.ml new file mode 100644 index 0000000000..7106be47b9 --- /dev/null +++ b/testsuite/tests/parallel/interrupt.ml @@ -0,0 +1,57 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +open Domain.Sync + +let n = 25 +let iter = 20 + +let counts = Array.make n 0 +let running = Array.make n false + +let main = Domain.self () + +let rec burn l = + if List.hd l > 14 then () + else + burn (l @ l |> List.map (fun x -> x + 1)) + +let go id = + counts.(id) <- counts.(id) + 1; + burn [0]; + running.(id) <- false; + notify main + + + +let rec wait_all () = + if critical_section (fun () -> + let still_running = + running |> Array.to_list |> List.mapi (fun i r -> i, r) |> List.filter (fun (i, r) -> r) in + match still_running with + | [] -> Printf.printf "done\n%!"; true + | xs -> + (* Printf.printf "%d... %!" (List.length xs); *) + wait (); + false) + then + () + else + wait_all () + +let () = + for i = 1 to iter do + for j = 0 to n - 1 do + running.(j) <- true; + ignore (Domain.spawn (fun () -> go j)); + done; + wait_all (); + done; + for i = 1 to n - 1 do + assert (counts.(i) = iter) + done; + Gc.full_major () diff --git a/testsuite/tests/parallel/interrupt.reference b/testsuite/tests/parallel/interrupt.reference new file mode 100644 index 0000000000..64bd491020 --- /dev/null +++ b/testsuite/tests/parallel/interrupt.reference @@ -0,0 +1,20 @@ +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done +done diff --git a/testsuite/tests/parallel/join.ml b/testsuite/tests/parallel/join.ml new file mode 100644 index 0000000000..fba31533e3 --- /dev/null +++ b/testsuite/tests/parallel/join.ml @@ -0,0 +1,59 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +let main_join n = + let a = Array.init n (fun _ -> false) in + Array.init n (fun i -> Domain.spawn (fun () -> + a.(i) <- true; + Some i + )) |> + Array.iteri (fun i d -> let v = Domain.join d in assert (v = Some i)); + let ok = Array.to_list a |> List.for_all (fun x -> x) in + assert ok + +let rec other_join flags n domain = + if n > 0 then + Domain.spawn (fun () -> flags.(n-1) <- true; Domain.join domain) + |> other_join flags (n-1) + else + Domain.join domain + +exception Ex of string +let join_exn () = + match Domain.(join (spawn (fun () -> raise (Ex (String.make 5 '!'))))) with + | _ -> assert false + | exception (Ex "!!!!!") -> () + +let join_slow () = + let rec burn l = + if List.hd l > 14 then () + else + burn (l @ l |> List.map (fun x -> x + 1)) in + assert (Domain.(join (spawn (fun () -> burn [0]; 42))) = 42) + + +let join2 () = + let r = ref false in + let t = Domain.spawn (fun () -> r := true) in + Domain.join t; + assert !r; + try + Domain.join t; + assert false + with Invalid_argument _ -> + assert !r + +let () = + main_join 100; + let flags = Array.make 100 false in + other_join flags (Array.length flags) (Domain.spawn ignore); + assert (Array.for_all (fun x -> x) flags); + join2 (); + join_exn (); + join_slow (); + Gc.full_major (); + Gc.full_major () diff --git a/testsuite/tests/misc/finaliser.reference b/testsuite/tests/parallel/join.reference index e69de29bb2..e69de29bb2 100644 --- a/testsuite/tests/misc/finaliser.reference +++ b/testsuite/tests/parallel/join.reference diff --git a/testsuite/tests/parallel/major_gc_wait_backup.ml b/testsuite/tests/parallel/major_gc_wait_backup.ml new file mode 100644 index 0000000000..c835af935f --- /dev/null +++ b/testsuite/tests/parallel/major_gc_wait_backup.ml @@ -0,0 +1,40 @@ +(* TEST +* hasunix +include unix +** native +** bytecode +*) + +type 'a tree = Empty | Node of 'a tree * 'a tree + +let rec make d = + if d = 0 then Node(Empty, Empty) + else let d = d - 1 in Node(make d, make d) + +(* you need to use Gc.quick_stat, because Gc.stat forces a major cycle *) +let major_collections () = + (Gc.quick_stat ()).major_collections + +(* test to force domain to do a full GC while another is waiting *) +let _ = + let d = Domain.spawn (fun _ -> + Domain.Sync.critical_section (fun () -> Domain.Sync.wait()); + ) in + Gc.full_major (); + let n = major_collections () in + ignore (make 22); + assert ((major_collections ()) > n); + Domain.Sync.notify (Domain.get_id d); + Domain.join d; + print_endline "wait OK" + +(* test to force domain to do a full GC while another is blocking *) +let _ = + let _ = Domain.spawn (fun _ -> + Unix.sleep 10000 + ) in + Gc.full_major (); + let n = major_collections () in + ignore (make 22); + assert ((major_collections ()) > n); + print_endline "sleep OK" diff --git a/testsuite/tests/parallel/major_gc_wait_backup.reference b/testsuite/tests/parallel/major_gc_wait_backup.reference new file mode 100644 index 0000000000..05f78790ba --- /dev/null +++ b/testsuite/tests/parallel/major_gc_wait_backup.reference @@ -0,0 +1,2 @@ +wait OK +sleep OK diff --git a/testsuite/tests/parallel/mctest.ml b/testsuite/tests/parallel/mctest.ml new file mode 100644 index 0000000000..ed424cd8ec --- /dev/null +++ b/testsuite/tests/parallel/mctest.ml @@ -0,0 +1,238 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +(* + * Copyright (c) 2015, Théo Laurent <theo.laurent@ens.fr> + * Copyright (c) 2015, KC Sivaramakrishnan <sk826@cl.cam.ac.uk> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + *) + +(* Michael-Scott queue *) + +module type BS = sig + type t + val create : ?max:int -> unit -> t + val once : t -> unit + val reset : t -> unit +end + +module B : BS = struct + + type t = int * int ref + + let _ = Random.self_init () + + let create ?(max=32) () = (max, ref 1) + + let once (maxv, r) = + let t = Random.int (!r) in + r := min (2 * !r) maxv; + if t = 0 then () + else ignore (Unix.select [] [] [] (0.001 *. (float_of_int t))) + + let reset (_,r) = r := 1 + +end + +(* TODO KC: Replace with concurrent lock free bag -- + * http://dl.acm.org/citation.cfm?id=1989550 *) + + +module type QS = sig + type 'a t + val create : unit -> 'a t + val is_empty : 'a t -> bool + val push : 'a t -> 'a -> unit + val pop : 'a t -> 'a option + val clean_until : 'a t -> ('a -> bool) -> unit + + type 'a cursor + val snapshot : 'a t -> 'a cursor + val next : 'a cursor -> ('a * 'a cursor) option +end + +module Q : QS = struct + + type 'a node = + | Nil + | Next of 'a * 'a node Atomic.t + + type 'a t = + { head : 'a node Atomic.t ; + tail : 'a node Atomic.t } + + let create () = + let head = (Next (Obj.magic (), Atomic.make Nil)) in + { head = Atomic.make head ; tail = Atomic.make head } + + let is_empty q = + match Atomic.get q.head with + | Nil -> failwith "MSQueue.is_empty: impossible" + | Next (_,x) -> + ( match Atomic.get x with + | Nil -> true + | _ -> false ) + + let pop q = + let b = B.create () in + let rec loop () = + let s = Atomic.get q.head in + let nhead = match s with + | Nil -> failwith "MSQueue.pop: impossible" + | Next (_, x) -> Atomic.get x + in match nhead with + | Nil -> None + | Next (v, _) when Atomic.compare_and_set q.head s nhead -> Some v + | _ -> ( B.once b ; loop () ) + in loop () + + let push q v = + let rec find_tail_and_enq curr_end node = + if Atomic.compare_and_set curr_end Nil node then () + else match Atomic.get curr_end with + | Nil -> find_tail_and_enq curr_end node + | Next (_, n) -> find_tail_and_enq n node + in + let newnode = Next (v, Atomic.make Nil) in + let tail = Atomic.get q.tail in + match tail with + | Nil -> failwith "HW_MSQueue.push: impossible" + | Next (_, n) -> begin + find_tail_and_enq n newnode; + ignore (Atomic.compare_and_set q.tail tail newnode) + end + + let rec clean_until q f = + let b = B.create () in + let rec loop () = + let s = Atomic.get q.head in + let nhead = match s with + | Nil -> failwith "MSQueue.pop: impossible" + | Next (_, x) -> Atomic.get x + in match nhead with + | Nil -> () + | Next (v, _) -> + if not (f v) then + if Atomic.compare_and_set q.head s nhead + then (B.reset b; loop ()) + else (B.once b; loop ()) + else () + in loop () + + type 'a cursor = 'a node + + let snapshot q = + match Atomic.get q.head with + | Nil -> failwith "MSQueue.snapshot: impossible" + | Next (_, n) -> Atomic.get n + + let next c = + match c with + | Nil -> None + | Next (a, n) -> Some (a, Atomic.get n) + +end + +module Scheduler = +struct + type 'a cont = ('a, unit) continuation + + effect Suspend : ('a cont -> 'a option) -> 'a + effect Resume : ('a cont * 'a) -> unit + effect GetTid : int + effect Spawn : (unit -> unit) -> unit + effect Yield : unit + + let suspend f = perform (Suspend f) + let resume t v = perform (Resume (t, v)) + let get_tid () = perform GetTid + let spawn f = perform (Spawn f) + let yield () = perform Yield + + let pqueue = Q.create () + + let get_free_pid () = Oo.id (object end) + + let enqueue k = Q.push pqueue k; Gc.minor () + + let rec dequeue () = + match Q.pop pqueue with + | Some k -> + continue k () + | None -> + ignore (Unix.select [] [] [] 0.01); + dequeue () + + let rec exec f = + let pid = get_free_pid () in + match f () with + | () -> dequeue () + | effect (Suspend f) k -> ( + match f k with + | None -> dequeue () + | Some v -> continue k v + ) + | effect (Resume (t, v)) k -> + enqueue k; + continue t v + | effect GetTid k -> + continue k pid + | effect (Spawn f) k -> + enqueue k; + exec f + | effect Yield k -> + enqueue k; + dequeue () + + let num_threads = 2 + + let start f = + for i = 1 to num_threads - 1 do + ignore (Domain.spawn dequeue) + done; + exec f + + +end + +let _ = + let procs = 4 in + let counter = Atomic.make 0 in + let rec finish () = + let v = Atomic.get counter in + if not (Atomic.compare_and_set counter v (v+1)) then finish (); + if v + 1 = procs then exit 0 + in + let rec worker n = + let r = ref 0 in + for i = 1 to 10000 do + Scheduler.yield (); + for j = 1 to 10000 do + incr r + done + done; + print_string (Printf.sprintf "done %d\n" !r); flush stdout; + finish () + in + Scheduler.start + (fun () -> + for i = 1 to procs do + (*Scheduler.yield ();*) + Scheduler.spawn (fun () -> worker i) + done; + ) diff --git a/testsuite/tests/parallel/mctest.reference b/testsuite/tests/parallel/mctest.reference new file mode 100644 index 0000000000..dd265608af --- /dev/null +++ b/testsuite/tests/parallel/mctest.reference @@ -0,0 +1,4 @@ +done 100000000 +done 100000000 +done 100000000 +done 100000000 diff --git a/testsuite/tests/parallel/multicore_systhreads.ml b/testsuite/tests/parallel/multicore_systhreads.ml new file mode 100644 index 0000000000..2f0fcf20b0 --- /dev/null +++ b/testsuite/tests/parallel/multicore_systhreads.ml @@ -0,0 +1,32 @@ +(* TEST +* hassysthreads +include systhreads +** bytecode +** native +*) + + +let producer oc = output_string oc "passed\n"; close_out oc + +let consumer ic = print_endline @@ input_line ic; close_in ic + +let main () = + let (in_fd, out_fd) = Unix.pipe() in + let ipipe = Unix.in_channel_of_descr in_fd in + let opipe = Unix.out_channel_of_descr out_fd in + let prod = Domain.spawn begin fun () -> + let t = Thread.create + (fun () -> Unix.sleep 3; Gc.full_major(); producer opipe) () + in + Thread.join t + end + in + let cons = Domain.spawn begin fun () -> + let t = Thread.create (fun () -> consumer ipipe) () in + Thread.join t + end + in + Domain.join prod; + Domain.join cons + +let _ = Unix.handle_unix_error main (); exit 0 diff --git a/testsuite/tests/parallel/multicore_systhreads.reference b/testsuite/tests/parallel/multicore_systhreads.reference new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/testsuite/tests/parallel/multicore_systhreads.reference @@ -0,0 +1 @@ +passed diff --git a/testsuite/tests/parallel/pingpong.ml b/testsuite/tests/parallel/pingpong.ml new file mode 100644 index 0000000000..eded360a15 --- /dev/null +++ b/testsuite/tests/parallel/pingpong.ml @@ -0,0 +1,49 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +let r = ref (Some 0) + +let () = Gc.minor () + + +let rec even lim put = + match !r with + | Some n when n = lim -> () + | (Some n) when n mod 2 == 0 -> + let next = Some (n + 1) in + put next; + even lim put + | _ -> let _ = [!r] in even lim put + +let rec odd lim put = + match !r with + | Some n when n = lim -> () + | (Some n) when n mod 2 == 1 -> + let next = Some (n + 1) in + put next; + odd lim put + | _ -> let _ = [!r] in odd lim put + + + + +let go n put = + r := Some 0; + let d = Domain.spawn (fun () -> even n put) in + odd n put; + (match !r with + | Some n -> + Printf.printf "%d\n%!" n + | None -> + assert false); + Domain.join d + + +let () = + go 100_000 (fun x -> r := Gc.promote_to x r); + go 100_000 (fun x -> r := x) + diff --git a/testsuite/tests/parallel/pingpong.reference b/testsuite/tests/parallel/pingpong.reference new file mode 100644 index 0000000000..7ab314964e --- /dev/null +++ b/testsuite/tests/parallel/pingpong.reference @@ -0,0 +1,2 @@ +100000 +100000 diff --git a/testsuite/tests/parallel/poll.ml b/testsuite/tests/parallel/poll.ml new file mode 100644 index 0000000000..73de1fe65c --- /dev/null +++ b/testsuite/tests/parallel/poll.ml @@ -0,0 +1,15 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +let rec loop () = + Domain.Sync.poll (); + loop () + +let _ = + ignore (Domain.spawn loop); + Gc.full_major(); + print_endline "OK" diff --git a/testsuite/tests/parallel/poll.reference b/testsuite/tests/parallel/poll.reference new file mode 100644 index 0000000000..d86bac9de5 --- /dev/null +++ b/testsuite/tests/parallel/poll.reference @@ -0,0 +1 @@ +OK diff --git a/testsuite/tests/parallel/prodcons_domains.ml b/testsuite/tests/parallel/prodcons_domains.ml new file mode 100644 index 0000000000..67499d342a --- /dev/null +++ b/testsuite/tests/parallel/prodcons_domains.ml @@ -0,0 +1,71 @@ +(* TEST + +* hassysthreads +include systhreads +** bytecode +** native + +*) + +(* Classic producer-consumer *) + +type 'a prodcons = + { buffer: 'a array; + lock: Mutex.t; + mutable readpos: int; + mutable writepos: int; + notempty: Condition.t; + notfull: Condition.t } + +let create size init = + { buffer = Array.make size init; + lock = Mutex.create(); + readpos = 0; + writepos = 0; + notempty = Condition.create(); + notfull = Condition.create() } + +let put p data = + Mutex.lock p.lock; + while (p.writepos + 1) mod Array.length p.buffer = p.readpos do + Condition.wait p.notfull p.lock + done; + p.buffer.(p.writepos) <- data; + p.writepos <- (p.writepos + 1) mod Array.length p.buffer; + Condition.signal p.notempty; + Mutex.unlock p.lock + +let get p = + Mutex.lock p.lock; + while p.writepos = p.readpos do + Condition.wait p.notempty p.lock + done; + let data = p.buffer.(p.readpos) in + p.readpos <- (p.readpos + 1) mod Array.length p.buffer; + Condition.signal p.notfull; + Mutex.unlock p.lock; + data + +(* Test *) + +let rec produce buff n max = + put buff n; + if n < max then produce buff (n+1) max + +let rec consume buff cur max = + let n = get buff in + if n <> cur then false + else if n = max then true + else consume buff (cur + 1) max + +let _ = + let buff1 = create 20 0 and buff2 = create 30 0 in + let ok1 = ref false and ok2 = ref false in + let _p1 = Domain.spawn (fun () -> produce buff1 0 10000) + and _p2 = Domain.spawn (fun () -> produce buff2 0 8000) + and c1 = Domain.spawn (fun () -> ok1 := consume buff1 0 10000) in + ok2 := consume buff2 0 8000; + Domain.join c1; + if !ok1 && !ok2 + then print_string "passed\n" + else print_string "FAILED\n" diff --git a/testsuite/tests/parallel/prodcons_domains.reference b/testsuite/tests/parallel/prodcons_domains.reference new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/testsuite/tests/parallel/prodcons_domains.reference @@ -0,0 +1 @@ +passed diff --git a/testsuite/tests/parallel/test_c_thread_register.ml b/testsuite/tests/parallel/test_c_thread_register.ml new file mode 100644 index 0000000000..352424a377 --- /dev/null +++ b/testsuite/tests/parallel/test_c_thread_register.ml @@ -0,0 +1,24 @@ +(* TEST + modules = "test_c_thread_register_cstubs.c" + * hassysthreads + include systhreads + ** bytecode + ** native +*) + +(* spins a external thread from C and register it to the OCaml runtime *) + +external spawn_thread : (unit -> unit) -> unit = "spawn_thread" + +let passed () = Printf.printf "passed\n" + +let _ = + let d = + Domain.spawn begin fun () -> + spawn_thread passed; + Thread.delay 0.5 + end + in + let t = Thread.create (fun () -> Thread.delay 1.0) () in + Thread.join t; + Domain.join d diff --git a/testsuite/tests/parallel/test_c_thread_register.reference b/testsuite/tests/parallel/test_c_thread_register.reference new file mode 100644 index 0000000000..b0aad4deb5 --- /dev/null +++ b/testsuite/tests/parallel/test_c_thread_register.reference @@ -0,0 +1 @@ +passed diff --git a/testsuite/tests/parallel/test_c_thread_register_cstubs.c b/testsuite/tests/parallel/test_c_thread_register_cstubs.c new file mode 100644 index 0000000000..9fd7858978 --- /dev/null +++ b/testsuite/tests/parallel/test_c_thread_register_cstubs.c @@ -0,0 +1,27 @@ +#include <string.h> +#include <pthread.h> +#include "caml/mlvalues.h" +#include "caml/gc.h" +#include "caml/memory.h" +#include "caml/callback.h" +#include "threads.h" + +void *thread_func(void *fn) { + caml_c_thread_register(); + caml_acquire_runtime_system(); + caml_callback((value) fn, Val_unit); + caml_release_runtime_system(); + caml_c_thread_unregister(); + return 0; +} + +value spawn_thread(value clos) +{ + pthread_t thr; + pthread_attr_t attr; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_create(&thr, &attr, thread_func, (void *) clos); + return Val_unit; +} diff --git a/testsuite/tests/parallel/timing.ml b/testsuite/tests/parallel/timing.ml new file mode 100644 index 0000000000..6c844fd1f8 --- /dev/null +++ b/testsuite/tests/parallel/timing.ml @@ -0,0 +1,69 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +open Domain +open Domain.Sync + +let millis_since event = + Int64.(to_int (div (sub (timer_ticks ()) event) (of_int 1_000_000))) + +let after_millis n event = + Int64.(add event (mul (of_int n) (of_int 1_000_000))) + +(* Waiting until a time that already passed should not take long. *) +let () = + let start = timer_ticks () in + for i = 0 to 2000 do + critical_section (fun () -> + let r = wait_until start in + assert (r = Timeout)); + done; + assert (millis_since start < 1000) (* can spuriously fail, in principle *) + +(* Waiting for a negative interval should not take long. *) +let () = + let start = timer_ticks () in + for i = 0 to 2000 do + critical_section (fun () -> + let r = wait_for (Int64.of_int (-50_000_000)) in + assert (r = Timeout)); + done; + assert (millis_since start < 1000) (* can spuriously fail, in principle *) + +(* Waiting until a time 50ms in the future should take at least 50ms *) +let () = + let start = timer_ticks () in + critical_section (fun () -> + let r = wait_until (after_millis 50 start) in + assert (r = Timeout)); + assert (millis_since start >= 50) + +(* Waiting for 50ms should take at least 50ms *) +let () = + let start = timer_ticks () in + critical_section (fun () -> + let r = wait_for (Int64.of_int 50_000_000) in + assert (r = Timeout)); + assert (millis_since start >= 50) + +(* Test that notifications interrupt waits *) +let () = + let start = timer_ticks () in + let flag = Atomic.make false in + let d1 = spawn (fun () -> + critical_section (fun () -> + let r = wait_until Int64.(add start (of_int 1000_000_000)) in + assert (r = Notified); + Atomic.set flag true)) in + let d2 = spawn (fun () -> + notify (get_id d1); + assert (Atomic.get flag)) in + join d1; + join d2; + assert (millis_since start < 1000) + +let () = print_endline "ok" diff --git a/testsuite/tests/parallel/timing.reference b/testsuite/tests/parallel/timing.reference new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/testsuite/tests/parallel/timing.reference @@ -0,0 +1 @@ +ok diff --git a/testsuite/tests/parallel/wait.ml b/testsuite/tests/parallel/wait.ml new file mode 100644 index 0000000000..a4767c00b5 --- /dev/null +++ b/testsuite/tests/parallel/wait.ml @@ -0,0 +1,81 @@ +(* TEST +* hasunix +include unix +** bytecode +** native +*) + +open Domain +open Domain.Sync + +let rec await r = + if Atomic.get r then () else (cpu_relax(); await r) + +external critical_adjust : int -> unit + = "caml_ml_domain_critical_section" + +let go () = + let in_crit = Atomic.make false in + (* notify does actually notify *) + let d = spawn (fun () -> + critical_section (fun () -> + Atomic.set in_crit true; + wait (); + Atomic.set in_crit false)) in + await in_crit; + notify (get_id d); + (* notify does not return early *) + assert (not (Atomic.get in_crit)); + join d; + (* notify works even if it arrives before wait *) + let entered_crit = Atomic.make false in + let woken = Atomic.make false in + let d = spawn (fun () -> + critical_section (fun () -> + Atomic.set entered_crit true; + await woken; + wait ())) in + await entered_crit; + Atomic.set woken true; + notify (get_id d); + join d; + (* a single notification wakes all waits in a single crit sec *) + let entered_crit = Atomic.make false in + let in_second_crit = Atomic.make false in + let d = spawn (fun () -> + critical_section (fun () -> + Atomic.set entered_crit true; + wait (); + wait ()); + critical_section (fun () -> + Atomic.set in_second_crit true; + wait (); + Atomic.set in_second_crit false)) in + await entered_crit; + notify (get_id d); + await in_second_crit; + join (spawn (fun () -> ())); (* some busywork *) + assert (Atomic.get in_second_crit); + notify (get_id d); + (* interrupt returns only after crit ends *) + assert (not (Atomic.get in_second_crit)); + join d; + (* critical sections end at termination *) + let in_crit = Atomic.make false in + let d = Domain.spawn (fun () -> + critical_adjust (+1); + Atomic.set in_crit true; + wait (); + Atomic.set in_crit false) in + await in_crit; + for i = 1 to 10000 do + assert (Atomic.get in_crit) + done; + notify (get_id d); + assert (not (Atomic.get in_crit)); + join d + + +let () = + for i = 1 to 1000 do go () done; + print_endline "ok" diff --git a/testsuite/tests/parallel/wait.reference b/testsuite/tests/parallel/wait.reference new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/testsuite/tests/parallel/wait.reference @@ -0,0 +1 @@ +ok diff --git a/testsuite/tests/promotion/bigimmut.ml b/testsuite/tests/promotion/bigimmut.ml new file mode 100644 index 0000000000..97cd7e6b0e --- /dev/null +++ b/testsuite/tests/promotion/bigimmut.ml @@ -0,0 +1,146 @@ +(* TEST + *) + +type 'a r = { + f000 : 'a; f001 : 'a; f002 : 'a; f003 : 'a; f004 : 'a; f005 : 'a; f006 : 'a; + f007 : 'a; f008 : 'a; f009 : 'a; f010 : 'a; f011 : 'a; f012 : 'a; f013 : 'a; + f014 : 'a; f015 : 'a; f016 : 'a; f017 : 'a; f018 : 'a; f019 : 'a; f020 : 'a; + f021 : 'a; f022 : 'a; f023 : 'a; f024 : 'a; f025 : 'a; f026 : 'a; f027 : 'a; + f028 : 'a; f029 : 'a; f030 : 'a; f031 : 'a; f032 : 'a; f033 : 'a; f034 : 'a; + f035 : 'a; f036 : 'a; f037 : 'a; f038 : 'a; f039 : 'a; f040 : 'a; f041 : 'a; + f042 : 'a; f043 : 'a; f044 : 'a; f045 : 'a; f046 : 'a; f047 : 'a; f048 : 'a; + f049 : 'a; f050 : 'a; f051 : 'a; f052 : 'a; f053 : 'a; f054 : 'a; f055 : 'a; + f056 : 'a; f057 : 'a; f058 : 'a; f059 : 'a; f060 : 'a; f061 : 'a; f062 : 'a; + f063 : 'a; f064 : 'a; f065 : 'a; f066 : 'a; f067 : 'a; f068 : 'a; f069 : 'a; + f070 : 'a; f071 : 'a; f072 : 'a; f073 : 'a; f074 : 'a; f075 : 'a; f076 : 'a; + f077 : 'a; f078 : 'a; f079 : 'a; f080 : 'a; f081 : 'a; f082 : 'a; f083 : 'a; + f084 : 'a; f085 : 'a; f086 : 'a; f087 : 'a; f088 : 'a; f089 : 'a; f090 : 'a; + f091 : 'a; f092 : 'a; f093 : 'a; f094 : 'a; f095 : 'a; f096 : 'a; f097 : 'a; + f098 : 'a; f099 : 'a; f100 : 'a; f101 : 'a; f102 : 'a; f103 : 'a; f104 : 'a; + f105 : 'a; f106 : 'a; f107 : 'a; f108 : 'a; f109 : 'a; f110 : 'a; f111 : 'a; + f112 : 'a; f113 : 'a; f114 : 'a; f115 : 'a; f116 : 'a; f117 : 'a; f118 : 'a; + f119 : 'a; f120 : 'a; f121 : 'a; f122 : 'a; f123 : 'a; f124 : 'a; f125 : 'a; + f126 : 'a; f127 : 'a; f128 : 'a; f129 : 'a; f130 : 'a; f131 : 'a; f132 : 'a; + f133 : 'a; f134 : 'a; f135 : 'a; f136 : 'a; f137 : 'a; f138 : 'a; f139 : 'a; + f140 : 'a; f141 : 'a; f142 : 'a; f143 : 'a; f144 : 'a; f145 : 'a; f146 : 'a; + f147 : 'a; f148 : 'a; f149 : 'a; f150 : 'a; f151 : 'a; f152 : 'a; f153 : 'a; + f154 : 'a; f155 : 'a; f156 : 'a; f157 : 'a; f158 : 'a; f159 : 'a; f160 : 'a; + f161 : 'a; f162 : 'a; f163 : 'a; f164 : 'a; f165 : 'a; f166 : 'a; f167 : 'a; + f168 : 'a; f169 : 'a; f170 : 'a; f171 : 'a; f172 : 'a; f173 : 'a; f174 : 'a; + f175 : 'a; f176 : 'a; f177 : 'a; f178 : 'a; f179 : 'a; f180 : 'a; f181 : 'a; + f182 : 'a; f183 : 'a; f184 : 'a; f185 : 'a; f186 : 'a; f187 : 'a; f188 : 'a; + f189 : 'a; f190 : 'a; f191 : 'a; f192 : 'a; f193 : 'a; f194 : 'a; f195 : 'a; + f196 : 'a; f197 : 'a; f198 : 'a; f199 : 'a; f200 : 'a; f201 : 'a; f202 : 'a; + f203 : 'a; f204 : 'a; f205 : 'a; f206 : 'a; f207 : 'a; f208 : 'a; f209 : 'a; + f210 : 'a; f211 : 'a; f212 : 'a; f213 : 'a; f214 : 'a; f215 : 'a; f216 : 'a; + f217 : 'a; f218 : 'a; f219 : 'a; f220 : 'a; f221 : 'a; f222 : 'a; f223 : 'a; + f224 : 'a; f225 : 'a; f226 : 'a; f227 : 'a; f228 : 'a; f229 : 'a; f230 : 'a; + f231 : 'a; f232 : 'a; f233 : 'a; f234 : 'a; f235 : 'a; f236 : 'a; f237 : 'a; + f238 : 'a; f239 : 'a; f240 : 'a; f241 : 'a; f242 : 'a; f243 : 'a; f244 : 'a; + f245 : 'a; f246 : 'a; f247 : 'a; f248 : 'a; f249 : 'a; f250 : 'a; f251 : 'a; + f252 : 'a; f253 : 'a; f254 : 'a; f255 : 'a; f256 : 'a; f257 : 'a; f258 : 'a; + f259 : 'a; f260 : 'a; f261 : 'a; f262 : 'a; f263 : 'a; f264 : 'a; f265 : 'a; + f266 : 'a; f267 : 'a; f268 : 'a; f269 : 'a; f270 : 'a; f271 : 'a; f272 : 'a; + f273 : 'a; f274 : 'a; f275 : 'a; f276 : 'a; f277 : 'a; f278 : 'a; f279 : 'a; + f280 : 'a; f281 : 'a; f282 : 'a; f283 : 'a; f284 : 'a; f285 : 'a; f286 : 'a; + f287 : 'a; f288 : 'a; f289 : 'a; f290 : 'a; f291 : 'a; f292 : 'a; f293 : 'a; + f294 : 'a; f295 : 'a; f296 : 'a; f297 : 'a; f298 : 'a; f299 : 'a; f300 : 'a; +} + +let new_r x = + { + f000 = x; f001 = x; f002 = x; f003 = x; f004 = x; f005 = x; f006 = x; + f007 = x; f008 = x; f009 = x; f010 = x; f011 = x; f012 = x; f013 = x; + f014 = x; f015 = x; f016 = x; f017 = x; f018 = x; f019 = x; f020 = x; + f021 = x; f022 = x; f023 = x; f024 = x; f025 = x; f026 = x; f027 = x; + f028 = x; f029 = x; f030 = x; f031 = x; f032 = x; f033 = x; f034 = x; + f035 = x; f036 = x; f037 = x; f038 = x; f039 = x; f040 = x; f041 = x; + f042 = x; f043 = x; f044 = x; f045 = x; f046 = x; f047 = x; f048 = x; + f049 = x; f050 = x; f051 = x; f052 = x; f053 = x; f054 = x; f055 = x; + f056 = x; f057 = x; f058 = x; f059 = x; f060 = x; f061 = x; f062 = x; + f063 = x; f064 = x; f065 = x; f066 = x; f067 = x; f068 = x; f069 = x; + f070 = x; f071 = x; f072 = x; f073 = x; f074 = x; f075 = x; f076 = x; + f077 = x; f078 = x; f079 = x; f080 = x; f081 = x; f082 = x; f083 = x; + f084 = x; f085 = x; f086 = x; f087 = x; f088 = x; f089 = x; f090 = x; + f091 = x; f092 = x; f093 = x; f094 = x; f095 = x; f096 = x; f097 = x; + f098 = x; f099 = x; f100 = x; f101 = x; f102 = x; f103 = x; f104 = x; + f105 = x; f106 = x; f107 = x; f108 = x; f109 = x; f110 = x; f111 = x; + f112 = x; f113 = x; f114 = x; f115 = x; f116 = x; f117 = x; f118 = x; + f119 = x; f120 = x; f121 = x; f122 = x; f123 = x; f124 = x; f125 = x; + f126 = x; f127 = x; f128 = x; f129 = x; f130 = x; f131 = x; f132 = x; + f133 = x; f134 = x; f135 = x; f136 = x; f137 = x; f138 = x; f139 = x; + f140 = x; f141 = x; f142 = x; f143 = x; f144 = x; f145 = x; f146 = x; + f147 = x; f148 = x; f149 = x; f150 = x; f151 = x; f152 = x; f153 = x; + f154 = x; f155 = x; f156 = x; f157 = x; f158 = x; f159 = x; f160 = x; + f161 = x; f162 = x; f163 = x; f164 = x; f165 = x; f166 = x; f167 = x; + f168 = x; f169 = x; f170 = x; f171 = x; f172 = x; f173 = x; f174 = x; + f175 = x; f176 = x; f177 = x; f178 = x; f179 = x; f180 = x; f181 = x; + f182 = x; f183 = x; f184 = x; f185 = x; f186 = x; f187 = x; f188 = x; + f189 = x; f190 = x; f191 = x; f192 = x; f193 = x; f194 = x; f195 = x; + f196 = x; f197 = x; f198 = x; f199 = x; f200 = x; f201 = x; f202 = x; + f203 = x; f204 = x; f205 = x; f206 = x; f207 = x; f208 = x; f209 = x; + f210 = x; f211 = x; f212 = x; f213 = x; f214 = x; f215 = x; f216 = x; + f217 = x; f218 = x; f219 = x; f220 = x; f221 = x; f222 = x; f223 = x; + f224 = x; f225 = x; f226 = x; f227 = x; f228 = x; f229 = x; f230 = x; + f231 = x; f232 = x; f233 = x; f234 = x; f235 = x; f236 = x; f237 = x; + f238 = x; f239 = x; f240 = x; f241 = x; f242 = x; f243 = x; f244 = x; + f245 = x; f246 = x; f247 = x; f248 = x; f249 = x; f250 = x; f251 = x; + f252 = x; f253 = x; f254 = x; f255 = x; f256 = x; f257 = x; f258 = x; + f259 = x; f260 = x; f261 = x; f262 = x; f263 = x; f264 = x; f265 = x; + f266 = x; f267 = x; f268 = x; f269 = x; f270 = x; f271 = x; f272 = x; + f273 = x; f274 = x; f275 = x; f276 = x; f277 = x; f278 = x; f279 = x; + f280 = x; f281 = x; f282 = x; f283 = x; f284 = x; f285 = x; f286 = x; + f287 = x; f288 = x; f289 = x; f290 = x; f291 = x; f292 = x; f293 = x; + f294 = x; f295 = x; f296 = x; f297 = x; f298 = x; f299 = x; f300 = x; + } + +type 'a box = Box of 'a +type t = string ref box + +let p s x = + let ptr = Obj.(((magic (add_offset (repr x) Int32.one)) : int)) in + Printf.printf "%s %x\n%!" s ptr + + +type phase = +| Starting +| DomainStarted +| MakingObject +| MadeObject +| GettingForeign +| GotForeign +| GcStart +| GcDone +| DerefForeign +| Finish1 +| Finish2 + +let curr_phase = ref Starting +let transition a b = + while not (Obj.(compare_and_swap_field (repr curr_phase) 0 (repr a) (repr b))) do () done + +let go () = + let r = ref None in + ignore @@ Domain.spawn (fun () -> + transition Starting DomainStarted; + transition MadeObject GettingForeign; + let foreign = match !r with Some {f000} -> f000 | None -> assert false in + (*p "for" foreign;*) + transition GettingForeign GotForeign; + transition GcDone DerefForeign; + Printf.printf "message: %s\n" (let Box r = foreign in !r); + transition DerefForeign Finish1); + transition DomainStarted MakingObject; + let g = new_r (Box (ref "hello")) in + (*p "g" g; + p "f0" g.f000;*) + r := Some g; + transition MakingObject MadeObject; + transition GotForeign GcStart; + Gc.full_major (); + let rec minor_junk a = function 0 -> [] | n -> minor_junk (Some n) (n-1) in + let _ = Obj.(is_block (repr (minor_junk None 10000))) in + transition GcStart GcDone; + transition Finish1 Finish2 + +let () = go () diff --git a/testsuite/tests/promotion/bigimmut.reference b/testsuite/tests/promotion/bigimmut.reference new file mode 100644 index 0000000000..0279c7bf6a --- /dev/null +++ b/testsuite/tests/promotion/bigimmut.reference @@ -0,0 +1 @@ +message: hello diff --git a/testsuite/tests/promotion/bigletrec.ml b/testsuite/tests/promotion/bigletrec.ml new file mode 100644 index 0000000000..ccee4d5891 --- /dev/null +++ b/testsuite/tests/promotion/bigletrec.ml @@ -0,0 +1,111 @@ +(* TEST + *) + +(* check that promotion occurs when immutable objects are assigned to *) + +(* will always be shared, because it's big *) +type ('x,'y,'a) r = { + f000 : 'x; f001 : 'y; f002 : 'a; f003 : 'a; f004 : 'a; f005 : 'a; f006 : 'a; + f007 : 'a; f008 : 'a; f009 : 'a; f010 : 'a; f011 : 'a; f012 : 'a; f013 : 'a; + f014 : 'a; f015 : 'a; f016 : 'a; f017 : 'a; f018 : 'a; f019 : 'a; f020 : 'a; + f021 : 'a; f022 : 'a; f023 : 'a; f024 : 'a; f025 : 'a; f026 : 'a; f027 : 'a; + f028 : 'a; f029 : 'a; f030 : 'a; f031 : 'a; f032 : 'a; f033 : 'a; f034 : 'a; + f035 : 'a; f036 : 'a; f037 : 'a; f038 : 'a; f039 : 'a; f040 : 'a; f041 : 'a; + f042 : 'a; f043 : 'a; f044 : 'a; f045 : 'a; f046 : 'a; f047 : 'a; f048 : 'a; + f049 : 'a; f050 : 'a; f051 : 'a; f052 : 'a; f053 : 'a; f054 : 'a; f055 : 'a; + f056 : 'a; f057 : 'a; f058 : 'a; f059 : 'a; f060 : 'a; f061 : 'a; f062 : 'a; + f063 : 'a; f064 : 'a; f065 : 'a; f066 : 'a; f067 : 'a; f068 : 'a; f069 : 'a; + f070 : 'a; f071 : 'a; f072 : 'a; f073 : 'a; f074 : 'a; f075 : 'a; f076 : 'a; + f077 : 'a; f078 : 'a; f079 : 'a; f080 : 'a; f081 : 'a; f082 : 'a; f083 : 'a; + f084 : 'a; f085 : 'a; f086 : 'a; f087 : 'a; f088 : 'a; f089 : 'a; f090 : 'a; + f091 : 'a; f092 : 'a; f093 : 'a; f094 : 'a; f095 : 'a; f096 : 'a; f097 : 'a; + f098 : 'a; f099 : 'a; f100 : 'a; f101 : 'a; f102 : 'a; f103 : 'a; f104 : 'a; + f105 : 'a; f106 : 'a; f107 : 'a; f108 : 'a; f109 : 'a; f110 : 'a; f111 : 'a; + f112 : 'a; f113 : 'a; f114 : 'a; f115 : 'a; f116 : 'a; f117 : 'a; f118 : 'a; + f119 : 'a; f120 : 'a; f121 : 'a; f122 : 'a; f123 : 'a; f124 : 'a; f125 : 'a; + f126 : 'a; f127 : 'a; f128 : 'a; f129 : 'a; f130 : 'a; f131 : 'a; f132 : 'a; + f133 : 'a; f134 : 'a; f135 : 'a; f136 : 'a; f137 : 'a; f138 : 'a; f139 : 'a; + f140 : 'a; f141 : 'a; f142 : 'a; f143 : 'a; f144 : 'a; f145 : 'a; f146 : 'a; + f147 : 'a; f148 : 'a; f149 : 'a; f150 : 'a; f151 : 'a; f152 : 'a; f153 : 'a; + f154 : 'a; f155 : 'a; f156 : 'a; f157 : 'a; f158 : 'a; f159 : 'a; f160 : 'a; + f161 : 'a; f162 : 'a; f163 : 'a; f164 : 'a; f165 : 'a; f166 : 'a; f167 : 'a; + f168 : 'a; f169 : 'a; f170 : 'a; f171 : 'a; f172 : 'a; f173 : 'a; f174 : 'a; + f175 : 'a; f176 : 'a; f177 : 'a; f178 : 'a; f179 : 'a; f180 : 'a; f181 : 'a; + f182 : 'a; f183 : 'a; f184 : 'a; f185 : 'a; f186 : 'a; f187 : 'a; f188 : 'a; + f189 : 'a; f190 : 'a; f191 : 'a; f192 : 'a; f193 : 'a; f194 : 'a; f195 : 'a; + f196 : 'a; f197 : 'a; f198 : 'a; f199 : 'a; f200 : 'a; f201 : 'a; f202 : 'a; + f203 : 'a; f204 : 'a; f205 : 'a; f206 : 'a; f207 : 'a; f208 : 'a; f209 : 'a; + f210 : 'a; f211 : 'a; f212 : 'a; f213 : 'a; f214 : 'a; f215 : 'a; f216 : 'a; + f217 : 'a; f218 : 'a; f219 : 'a; f220 : 'a; f221 : 'a; f222 : 'a; f223 : 'a; + f224 : 'a; f225 : 'a; f226 : 'a; f227 : 'a; f228 : 'a; f229 : 'a; f230 : 'a; + f231 : 'a; f232 : 'a; f233 : 'a; f234 : 'a; f235 : 'a; f236 : 'a; f237 : 'a; + f238 : 'a; f239 : 'a; f240 : 'a; f241 : 'a; f242 : 'a; f243 : 'a; f244 : 'a; + f245 : 'a; f246 : 'a; f247 : 'a; f248 : 'a; f249 : 'a; f250 : 'a; f251 : 'a; + f252 : 'a; f253 : 'a; f254 : 'a; f255 : 'a; f256 : 'a; f257 : 'a; f258 : 'a; + f259 : 'a; f260 : 'a; f261 : 'a; f262 : 'a; f263 : 'a; f264 : 'a; f265 : 'a; + f266 : 'a; f267 : 'a; f268 : 'a; f269 : 'a; f270 : 'a; f271 : 'a; f272 : 'a; + f273 : 'a; f274 : 'a; f275 : 'a; f276 : 'a; f277 : 'a; f278 : 'a; f279 : 'a; + f280 : 'a; f281 : 'a; f282 : 'a; f283 : 'a; f284 : 'a; f285 : 'a; f286 : 'a; + f287 : 'a; f288 : 'a; f289 : 'a; f290 : 'a; f291 : 'a; f292 : 'a; f293 : 'a; + f294 : 'a; f295 : 'a; f296 : 'a; f297 : 'a; f298 : 'a; f299 : 'a; f300 : 'a; +} + +let test_recimmut () = + let x = ref 1000 in + let rec small1 = `Foo record + and record = { + f000 = small1; f001 = small2; f002 = x; f003 = x; f004 = x; f005 = x; f006 = x; + f007 = x; f008 = x; f009 = x; f010 = x; f011 = x; f012 = x; f013 = x; + f014 = x; f015 = x; f016 = x; f017 = x; f018 = x; f019 = x; f020 = x; + f021 = x; f022 = x; f023 = x; f024 = x; f025 = x; f026 = x; f027 = x; + f028 = x; f029 = x; f030 = x; f031 = x; f032 = x; f033 = x; f034 = x; + f035 = x; f036 = x; f037 = x; f038 = x; f039 = x; f040 = x; f041 = x; + f042 = x; f043 = x; f044 = x; f045 = x; f046 = x; f047 = x; f048 = x; + f049 = x; f050 = x; f051 = x; f052 = x; f053 = x; f054 = x; f055 = x; + f056 = x; f057 = x; f058 = x; f059 = x; f060 = x; f061 = x; f062 = x; + f063 = x; f064 = x; f065 = x; f066 = x; f067 = x; f068 = x; f069 = x; + f070 = x; f071 = x; f072 = x; f073 = x; f074 = x; f075 = x; f076 = x; + f077 = x; f078 = x; f079 = x; f080 = x; f081 = x; f082 = x; f083 = x; + f084 = x; f085 = x; f086 = x; f087 = x; f088 = x; f089 = x; f090 = x; + f091 = x; f092 = x; f093 = x; f094 = x; f095 = x; f096 = x; f097 = x; + f098 = x; f099 = x; f100 = x; f101 = x; f102 = x; f103 = x; f104 = x; + f105 = x; f106 = x; f107 = x; f108 = x; f109 = x; f110 = x; f111 = x; + f112 = x; f113 = x; f114 = x; f115 = x; f116 = x; f117 = x; f118 = x; + f119 = x; f120 = x; f121 = x; f122 = x; f123 = x; f124 = x; f125 = x; + f126 = x; f127 = x; f128 = x; f129 = x; f130 = x; f131 = x; f132 = x; + f133 = x; f134 = x; f135 = x; f136 = x; f137 = x; f138 = x; f139 = x; + f140 = x; f141 = x; f142 = x; f143 = x; f144 = x; f145 = x; f146 = x; + f147 = x; f148 = x; f149 = x; f150 = x; f151 = x; f152 = x; f153 = x; + f154 = x; f155 = x; f156 = x; f157 = x; f158 = x; f159 = x; f160 = x; + f161 = x; f162 = x; f163 = x; f164 = x; f165 = x; f166 = x; f167 = x; + f168 = x; f169 = x; f170 = x; f171 = x; f172 = x; f173 = x; f174 = x; + f175 = x; f176 = x; f177 = x; f178 = x; f179 = x; f180 = x; f181 = x; + f182 = x; f183 = x; f184 = x; f185 = x; f186 = x; f187 = x; f188 = x; + f189 = x; f190 = x; f191 = x; f192 = x; f193 = x; f194 = x; f195 = x; + f196 = x; f197 = x; f198 = x; f199 = x; f200 = x; f201 = x; f202 = x; + f203 = x; f204 = x; f205 = x; f206 = x; f207 = x; f208 = x; f209 = x; + f210 = x; f211 = x; f212 = x; f213 = x; f214 = x; f215 = x; f216 = x; + f217 = x; f218 = x; f219 = x; f220 = x; f221 = x; f222 = x; f223 = x; + f224 = x; f225 = x; f226 = x; f227 = x; f228 = x; f229 = x; f230 = x; + f231 = x; f232 = x; f233 = x; f234 = x; f235 = x; f236 = x; f237 = x; + f238 = x; f239 = x; f240 = x; f241 = x; f242 = x; f243 = x; f244 = x; + f245 = x; f246 = x; f247 = x; f248 = x; f249 = x; f250 = x; f251 = x; + f252 = x; f253 = x; f254 = x; f255 = x; f256 = x; f257 = x; f258 = x; + f259 = x; f260 = x; f261 = x; f262 = x; f263 = x; f264 = x; f265 = x; + f266 = x; f267 = x; f268 = x; f269 = x; f270 = x; f271 = x; f272 = x; + f273 = x; f274 = x; f275 = x; f276 = x; f277 = x; f278 = x; f279 = x; + f280 = x; f281 = x; f282 = x; f283 = x; f284 = x; f285 = x; f286 = x; + f287 = x; f288 = x; f289 = x; f290 = x; f291 = x; f292 = x; f293 = x; + f294 = x; f295 = x; f296 = x; f297 = x; f298 = x; f299 = x; f300 = x; + } + and small2 = `Bar record in + Printf.printf "%b %b %b %b %b %b %b\n" + (Obj.is_shared (Obj.repr record)) + (Obj.is_shared (Obj.repr small1)) + (Obj.is_shared (Obj.repr small2)) + (Obj.is_shared (Obj.repr x)) + (record.f000 == small1) + (record.f001 == small2) + (record.f002 == x) + +let () = test_recimmut () diff --git a/testsuite/tests/promotion/bigletrec.reference b/testsuite/tests/promotion/bigletrec.reference new file mode 100644 index 0000000000..f592485175 --- /dev/null +++ b/testsuite/tests/promotion/bigletrec.reference @@ -0,0 +1 @@ +true false false false true true true diff --git a/testsuite/tests/promotion/bigrecmod.ml b/testsuite/tests/promotion/bigrecmod.ml new file mode 100644 index 0000000000..0f6268db75 --- /dev/null +++ b/testsuite/tests/promotion/bigrecmod.ml @@ -0,0 +1,193 @@ +(* TEST + *) + +module type Big = sig + type a + + val f000 : a val f001 : a val f002 : a val f003 : a val f004 : a val f005 : a val f006 : a + val f007 : a val f008 : a val f009 : a val f010 : a val f011 : a val f012 : a val f013 : a + val f014 : a val f015 : a val f016 : a val f017 : a val f018 : a val f019 : a val f020 : a + val f021 : a val f022 : a val f023 : a val f024 : a val f025 : a val f026 : a val f027 : a + val f028 : a val f029 : a val f030 : a val f031 : a val f032 : a val f033 : a val f034 : a + val f035 : a val f036 : a val f037 : a val f038 : a val f039 : a val f040 : a val f041 : a + val f042 : a val f043 : a val f044 : a val f045 : a val f046 : a val f047 : a val f048 : a + val f049 : a val f050 : a val f051 : a val f052 : a val f053 : a val f054 : a val f055 : a + val f056 : a val f057 : a val f058 : a val f059 : a val f060 : a val f061 : a val f062 : a + val f063 : a val f064 : a val f065 : a val f066 : a val f067 : a val f068 : a val f069 : a + val f070 : a val f071 : a val f072 : a val f073 : a val f074 : a val f075 : a val f076 : a + val f077 : a val f078 : a val f079 : a val f080 : a val f081 : a val f082 : a val f083 : a + val f084 : a val f085 : a val f086 : a val f087 : a val f088 : a val f089 : a val f090 : a + val f091 : a val f092 : a val f093 : a val f094 : a val f095 : a val f096 : a val f097 : a + val f098 : a val f099 : a val f100 : a val f101 : a val f102 : a val f103 : a val f104 : a + val f105 : a val f106 : a val f107 : a val f108 : a val f109 : a val f110 : a val f111 : a + val f112 : a val f113 : a val f114 : a val f115 : a val f116 : a val f117 : a val f118 : a + val f119 : a val f120 : a val f121 : a val f122 : a val f123 : a val f124 : a val f125 : a + val f126 : a val f127 : a val f128 : a val f129 : a val f130 : a val f131 : a val f132 : a + val f133 : a val f134 : a val f135 : a val f136 : a val f137 : a val f138 : a val f139 : a + val f140 : a val f141 : a val f142 : a val f143 : a val f144 : a val f145 : a val f146 : a + val f147 : a val f148 : a val f149 : a val f150 : a val f151 : a val f152 : a val f153 : a + val f154 : a val f155 : a val f156 : a val f157 : a val f158 : a val f159 : a val f160 : a + val f161 : a val f162 : a val f163 : a val f164 : a val f165 : a val f166 : a val f167 : a + val f168 : a val f169 : a val f170 : a val f171 : a val f172 : a val f173 : a val f174 : a + val f175 : a val f176 : a val f177 : a val f178 : a val f179 : a val f180 : a val f181 : a + val f182 : a val f183 : a val f184 : a val f185 : a val f186 : a val f187 : a val f188 : a + val f189 : a val f190 : a val f191 : a val f192 : a val f193 : a val f194 : a val f195 : a + val f196 : a val f197 : a val f198 : a val f199 : a val f200 : a val f201 : a val f202 : a + val f203 : a val f204 : a val f205 : a val f206 : a val f207 : a val f208 : a val f209 : a + val f210 : a val f211 : a val f212 : a val f213 : a val f214 : a val f215 : a val f216 : a + val f217 : a val f218 : a val f219 : a val f220 : a val f221 : a val f222 : a val f223 : a + val f224 : a val f225 : a val f226 : a val f227 : a val f228 : a val f229 : a val f230 : a + val f231 : a val f232 : a val f233 : a val f234 : a val f235 : a val f236 : a val f237 : a + val f238 : a val f239 : a val f240 : a val f241 : a val f242 : a val f243 : a val f244 : a + val f245 : a val f246 : a val f247 : a val f248 : a val f249 : a val f250 : a val f251 : a + val f252 : a val f253 : a val f254 : a val f255 : a val f256 : a val f257 : a val f258 : a + val f259 : a val f260 : a val f261 : a val f262 : a val f263 : a val f264 : a val f265 : a + val f266 : a val f267 : a val f268 : a val f269 : a val f270 : a val f271 : a val f272 : a + val f273 : a val f274 : a val f275 : a val f276 : a val f277 : a val f278 : a val f279 : a + val f280 : a val f281 : a val f282 : a val f283 : a val f284 : a val f285 : a val f286 : a + val f287 : a val f288 : a val f289 : a val f290 : a val f291 : a val f292 : a val f293 : a + val f294 : a val f295 : a val f296 : a val f297 : a val f298 : a val f299 : a val f300 : a +end + +let p = ref 42 +module Big = struct + type a = [`Foo of int ref] + let a : a = `Foo p + + let f000 = a let f001 = a let f002 = a let f003 = a let f004 = a let f005 = a let f006 = a + let f007 = a let f008 = a let f009 = a let f010 = a let f011 = a let f012 = a let f013 = a + let f014 = a let f015 = a let f016 = a let f017 = a let f018 = a let f019 = a let f020 = a + let f021 = a let f022 = a let f023 = a let f024 = a let f025 = a let f026 = a let f027 = a + let f028 = a let f029 = a let f030 = a let f031 = a let f032 = a let f033 = a let f034 = a + let f035 = a let f036 = a let f037 = a let f038 = a let f039 = a let f040 = a let f041 = a + let f042 = a let f043 = a let f044 = a let f045 = a let f046 = a let f047 = a let f048 = a + let f049 = a let f050 = a let f051 = a let f052 = a let f053 = a let f054 = a let f055 = a + let f056 = a let f057 = a let f058 = a let f059 = a let f060 = a let f061 = a let f062 = a + let f063 = a let f064 = a let f065 = a let f066 = a let f067 = a let f068 = a let f069 = a + let f070 = a let f071 = a let f072 = a let f073 = a let f074 = a let f075 = a let f076 = a + let f077 = a let f078 = a let f079 = a let f080 = a let f081 = a let f082 = a let f083 = a + let f084 = a let f085 = a let f086 = a let f087 = a let f088 = a let f089 = a let f090 = a + let f091 = a let f092 = a let f093 = a let f094 = a let f095 = a let f096 = a let f097 = a + let f098 = a let f099 = a let f100 = a let f101 = a let f102 = a let f103 = a let f104 = a + let f105 = a let f106 = a let f107 = a let f108 = a let f109 = a let f110 = a let f111 = a + let f112 = a let f113 = a let f114 = a let f115 = a let f116 = a let f117 = a let f118 = a + let f119 = a let f120 = a let f121 = a let f122 = a let f123 = a let f124 = a let f125 = a + let f126 = a let f127 = a let f128 = a let f129 = a let f130 = a let f131 = a let f132 = a + let f133 = a let f134 = a let f135 = a let f136 = a let f137 = a let f138 = a let f139 = a + let f140 = a let f141 = a let f142 = a let f143 = a let f144 = a let f145 = a let f146 = a + let f147 = a let f148 = a let f149 = a let f150 = a let f151 = a let f152 = a let f153 = a + let f154 = a let f155 = a let f156 = a let f157 = a let f158 = a let f159 = a let f160 = a + let f161 = a let f162 = a let f163 = a let f164 = a let f165 = a let f166 = a let f167 = a + let f168 = a let f169 = a let f170 = a let f171 = a let f172 = a let f173 = a let f174 = a + let f175 = a let f176 = a let f177 = a let f178 = a let f179 = a let f180 = a let f181 = a + let f182 = a let f183 = a let f184 = a let f185 = a let f186 = a let f187 = a let f188 = a + let f189 = a let f190 = a let f191 = a let f192 = a let f193 = a let f194 = a let f195 = a + let f196 = a let f197 = a let f198 = a let f199 = a let f200 = a let f201 = a let f202 = a + let f203 = a let f204 = a let f205 = a let f206 = a let f207 = a let f208 = a let f209 = a + let f210 = a let f211 = a let f212 = a let f213 = a let f214 = a let f215 = a let f216 = a + let f217 = a let f218 = a let f219 = a let f220 = a let f221 = a let f222 = a let f223 = a + let f224 = a let f225 = a let f226 = a let f227 = a let f228 = a let f229 = a let f230 = a + let f231 = a let f232 = a let f233 = a let f234 = a let f235 = a let f236 = a let f237 = a + let f238 = a let f239 = a let f240 = a let f241 = a let f242 = a let f243 = a let f244 = a + let f245 = a let f246 = a let f247 = a let f248 = a let f249 = a let f250 = a let f251 = a + let f252 = a let f253 = a let f254 = a let f255 = a let f256 = a let f257 = a let f258 = a + let f259 = a let f260 = a let f261 = a let f262 = a let f263 = a let f264 = a let f265 = a + let f266 = a let f267 = a let f268 = a let f269 = a let f270 = a let f271 = a let f272 = a + let f273 = a let f274 = a let f275 = a let f276 = a let f277 = a let f278 = a let f279 = a + let f280 = a let f281 = a let f282 = a let f283 = a let f284 = a let f285 = a let f286 = a + let f287 = a let f288 = a let f289 = a let f290 = a let f291 = a let f292 = a let f293 = a + let f294 = a let f295 = a let f296 = a let f297 = a let f298 = a let f299 = a let f300 = a + +end + +let () = + let p' = match Big.f132 with `Foo p -> p in + Printf.printf "%b %b %b %b\n%!" + (Obj.is_shared (Obj.repr (module Big : Big))) + (Obj.is_shared (Obj.repr Big.f000)) + (Obj.is_shared (Obj.repr p)) + (p == p') + + +let () = Gc.full_major () + +module type T = sig + val f : unit -> int ref + val g : unit -> int ref +end +module type Big' = Big with type a = unit -> int ref + +module F (X : sig val p : int ref end) = struct + module rec M : T = struct + let f () = Big'.f000 () + let g () = N.g () + end + and Big' : Big' = struct + type a = unit -> int ref + let a () = N.f () + + let f000 () = M.g () let f001 () = a () let f002 () = a () let f003 () = a () let f004 () = a () let f005 () = a () let f006 () = a () + let f007 () = a () let f008 () = a () let f009 () = a () let f010 () = a () let f011 () = a () let f012 () = a () let f013 () = a () + let f014 () = a () let f015 () = a () let f016 () = a () let f017 () = a () let f018 () = a () let f019 () = a () let f020 () = a () + let f021 () = a () let f022 () = a () let f023 () = a () let f024 () = a () let f025 () = a () let f026 () = a () let f027 () = a () + let f028 () = a () let f029 () = a () let f030 () = a () let f031 () = a () let f032 () = a () let f033 () = a () let f034 () = a () + let f035 () = a () let f036 () = a () let f037 () = a () let f038 () = a () let f039 () = a () let f040 () = a () let f041 () = a () + let f042 () = a () let f043 () = a () let f044 () = a () let f045 () = a () let f046 () = a () let f047 () = a () let f048 () = a () + let f049 () = a () let f050 () = a () let f051 () = a () let f052 () = a () let f053 () = a () let f054 () = a () let f055 () = a () + let f056 () = a () let f057 () = a () let f058 () = a () let f059 () = a () let f060 () = a () let f061 () = a () let f062 () = a () + let f063 () = a () let f064 () = a () let f065 () = a () let f066 () = a () let f067 () = a () let f068 () = a () let f069 () = a () + let f070 () = a () let f071 () = a () let f072 () = a () let f073 () = a () let f074 () = a () let f075 () = a () let f076 () = a () + let f077 () = a () let f078 () = a () let f079 () = a () let f080 () = a () let f081 () = a () let f082 () = a () let f083 () = a () + let f084 () = a () let f085 () = a () let f086 () = a () let f087 () = a () let f088 () = a () let f089 () = a () let f090 () = a () + let f091 () = a () let f092 () = a () let f093 () = a () let f094 () = a () let f095 () = a () let f096 () = a () let f097 () = a () + let f098 () = a () let f099 () = a () let f100 () = a () let f101 () = a () let f102 () = a () let f103 () = a () let f104 () = a () + let f105 () = a () let f106 () = a () let f107 () = a () let f108 () = a () let f109 () = a () let f110 () = a () let f111 () = a () + let f112 () = a () let f113 () = a () let f114 () = a () let f115 () = a () let f116 () = a () let f117 () = a () let f118 () = a () + let f119 () = a () let f120 () = a () let f121 () = a () let f122 () = a () let f123 () = a () let f124 () = a () let f125 () = a () + let f126 () = a () let f127 () = a () let f128 () = a () let f129 () = a () let f130 () = a () let f131 () = a () let f132 () = a () + let f133 () = a () let f134 () = a () let f135 () = a () let f136 () = a () let f137 () = a () let f138 () = a () let f139 () = a () + let f140 () = a () let f141 () = a () let f142 () = a () let f143 () = a () let f144 () = a () let f145 () = a () let f146 () = a () + let f147 () = a () let f148 () = a () let f149 () = a () let f150 () = a () let f151 () = a () let f152 () = a () let f153 () = a () + let f154 () = a () let f155 () = a () let f156 () = a () let f157 () = a () let f158 () = a () let f159 () = a () let f160 () = a () + let f161 () = a () let f162 () = a () let f163 () = a () let f164 () = a () let f165 () = a () let f166 () = a () let f167 () = a () + let f168 () = a () let f169 () = a () let f170 () = a () let f171 () = a () let f172 () = a () let f173 () = a () let f174 () = a () + let f175 () = a () let f176 () = a () let f177 () = a () let f178 () = a () let f179 () = a () let f180 () = a () let f181 () = a () + let f182 () = a () let f183 () = a () let f184 () = a () let f185 () = a () let f186 () = a () let f187 () = a () let f188 () = a () + let f189 () = a () let f190 () = a () let f191 () = a () let f192 () = a () let f193 () = a () let f194 () = a () let f195 () = a () + let f196 () = a () let f197 () = a () let f198 () = a () let f199 () = a () let f200 () = a () let f201 () = a () let f202 () = a () + let f203 () = a () let f204 () = a () let f205 () = a () let f206 () = a () let f207 () = a () let f208 () = a () let f209 () = a () + let f210 () = a () let f211 () = a () let f212 () = a () let f213 () = a () let f214 () = a () let f215 () = a () let f216 () = a () + let f217 () = a () let f218 () = a () let f219 () = a () let f220 () = a () let f221 () = a () let f222 () = a () let f223 () = a () + let f224 () = a () let f225 () = a () let f226 () = a () let f227 () = a () let f228 () = a () let f229 () = a () let f230 () = a () + let f231 () = a () let f232 () = a () let f233 () = a () let f234 () = a () let f235 () = a () let f236 () = a () let f237 () = a () + let f238 () = a () let f239 () = a () let f240 () = a () let f241 () = a () let f242 () = a () let f243 () = a () let f244 () = a () + let f245 () = a () let f246 () = a () let f247 () = a () let f248 () = a () let f249 () = a () let f250 () = a () let f251 () = a () + let f252 () = a () let f253 () = a () let f254 () = a () let f255 () = a () let f256 () = a () let f257 () = a () let f258 () = a () + let f259 () = a () let f260 () = a () let f261 () = a () let f262 () = a () let f263 () = a () let f264 () = a () let f265 () = a () + let f266 () = a () let f267 () = a () let f268 () = a () let f269 () = a () let f270 () = a () let f271 () = a () let f272 () = a () + let f273 () = a () let f274 () = a () let f275 () = a () let f276 () = a () let f277 () = a () let f278 () = a () let f279 () = a () + let f280 () = a () let f281 () = a () let f282 () = a () let f283 () = a () let f284 () = a () let f285 () = a () let f286 () = a () + let f287 () = a () let f288 () = a () let f289 () = a () let f290 () = a () let f291 () = a () let f292 () = a () let f293 () = a () + let f294 () = a () let f295 () = a () let f296 () = a () let f297 () = a () let f298 () = a () let f299 () = a () let f300 () = a () + + end + and N : T = struct + let f () = Big'.f000 () + let g () = X.p + end +end + +let () = + let module FX = F (struct let p = p end) in + let open FX in + let p' = M.f () in + Printf.printf "%b %b %b %b %b %b %b %b %b\n%!" + (Obj.is_shared (Obj.repr (module Big' : Big'))) + (Obj.is_shared (Obj.repr Big.f123)) + (Obj.is_shared (Obj.repr (module M : T))) + (Obj.is_shared (Obj.repr M.f)) + (Obj.is_shared (Obj.repr M.g)) + (Obj.is_shared (Obj.repr (module N : T))) + (Obj.is_shared (Obj.repr N.f)) + (Obj.is_shared (Obj.repr N.g)) + (p == p') diff --git a/testsuite/tests/promotion/bigrecmod.reference b/testsuite/tests/promotion/bigrecmod.reference new file mode 100644 index 0000000000..9f9292ca9a --- /dev/null +++ b/testsuite/tests/promotion/bigrecmod.reference @@ -0,0 +1,2 @@ +true false false true +true true true true true false false false true diff --git a/testsuite/tests/statmemprof/arrays_in_major.reference b/testsuite/tests/statmemprof/arrays_in_major.reference deleted file mode 100644 index 1f34ad8ec8..0000000000 --- a/testsuite/tests/statmemprof/arrays_in_major.reference +++ /dev/null @@ -1,11 +0,0 @@ -check_nosample -check_counts_full_major -check_counts_full_major -check_no_nested -check_distrib 300 3000 3 0.000010 -check_distrib 300 3000 1 0.000100 -check_distrib 300 3000 1 0.010000 -check_distrib 300 3000 1 0.900000 -check_distrib 300 300 100000 0.100000 -check_distrib 300000 300000 30 0.100000 -OK ! diff --git a/testsuite/tests/statmemprof/arrays_in_minor.reference b/testsuite/tests/statmemprof/arrays_in_minor.reference deleted file mode 100644 index 1dad91939c..0000000000 --- a/testsuite/tests/statmemprof/arrays_in_minor.reference +++ /dev/null @@ -1,11 +0,0 @@ -check_nosample -check_counts_full_major -check_counts_full_major -check_no_nested -check_distrib 1 250 1000 0.000010 -check_distrib 1 250 1000 0.000100 -check_distrib 1 250 1000 0.010000 -check_distrib 1 250 1000 0.900000 -check_distrib 1 1 10000000 0.010000 -check_distrib 250 250 100000 0.100000 -OK ! diff --git a/testsuite/tests/statmemprof/intern.reference b/testsuite/tests/statmemprof/intern.reference deleted file mode 100644 index d83e8d6d50..0000000000 --- a/testsuite/tests/statmemprof/intern.reference +++ /dev/null @@ -1,10 +0,0 @@ -check_nosample -check_counts_full_major -check_counts_full_major -check_no_nested -check_distrib 2 3000 3 0.000010 -check_distrib 2 3000 1 0.000100 -check_distrib 2 2000 1 0.010000 -check_distrib 2 2000 1 0.900000 -check_distrib 300000 300000 20 0.100000 -OK ! diff --git a/testsuite/tests/statmemprof/lists_in_minor.reference b/testsuite/tests/statmemprof/lists_in_minor.reference deleted file mode 100644 index 11cfe0ca12..0000000000 --- a/testsuite/tests/statmemprof/lists_in_minor.reference +++ /dev/null @@ -1,8 +0,0 @@ -check_distrib 10 1000000 0.010000 -check_distrib 1000000 10 0.000010 -check_distrib 1000000 10 0.000100 -check_distrib 1000000 10 0.001000 -check_distrib 1000000 10 0.010000 -check_distrib 100000 10 0.100000 -check_distrib 100000 10 0.900000 -OK ! diff --git a/testsuite/tests/translprim/comparison_table.compilers.reference b/testsuite/tests/translprim/comparison_table.compilers.reference index e518956cf5..6a7f46a2f4 100644 --- a/testsuite/tests/translprim/comparison_table.compilers.reference +++ b/testsuite/tests/translprim/comparison_table.compilers.reference @@ -149,10 +149,12 @@ (function cmp eq ne lt gt le ge vec (let (uncurry = - (function f param (apply f (field 0 param) (field 1 param))) + (function f param + (apply f (field_imm 0 param) (field_imm 1 param))) map = (function f l - (apply (field 16 (global Stdlib__list!)) (apply uncurry f) l))) + (apply (field_imm 16 (global Stdlib__list!)) + (apply uncurry f) l))) (makeblock 0 (makeblock 0 (apply map gen_cmp vec) (apply map cmp vec)) (apply map @@ -187,10 +189,10 @@ (let (uncurry = (function f param - (apply f (field 0 param) (field 1 param))) + (apply f (field_imm 0 param) (field_imm 1 param))) map = (function f l - (apply (field 16 (global Stdlib__list!)) + (apply (field_imm 16 (global Stdlib__list!)) (apply uncurry f) l))) (makeblock 0 (makeblock 0 (apply map eta_gen_cmp vec) diff --git a/testsuite/tests/typing-gadts/gpr1997.ml b/testsuite/tests/typing-gadts/gpr1997.ml new file mode 100644 index 0000000000..f81085f582 --- /dev/null +++ b/testsuite/tests/typing-gadts/gpr1997.ml @@ -0,0 +1,53 @@ +(* TEST + * expect +*) + +module M : sig + type 'a t + + type _ typ = + | Foo : 'a -> [`Foo of 'a] typ + | Bar : string -> [`Bar] typ + + val use_bar : [`Bar] t -> int + + val foo : [`Foo of int] t + +end = struct + type 'a t = string + + type _ typ = + | Foo : 'a -> [`Foo of 'a] typ + | Bar : string -> [`Bar] typ + + let foo = "foo" + + let use_bar _ = 0 +end;; +[%%expect {| +module M : + sig + type 'a t + type _ typ = + Foo : 'a -> [ `Foo of 'a ] typ + | Bar : string -> [ `Bar ] typ + val use_bar : [ `Bar ] t -> int + val foo : [ `Foo of int ] t + end +|}];; + +let go (type a) (typ : a M.typ) (msg : a M.t) = + match typ with + | Bar s -> + (match M.use_bar msg with _ -> ()) +;; +[%%expect {| +Lines 2-4, characters 2-38: +2 | ..match typ with +3 | | Bar s -> +4 | (match M.use_bar msg with _ -> ()) +Warning 8: this pattern-matching is not exhaustive. +Here is an example of a case that is not matched: +Foo _ +val go : 'a M.typ -> 'a M.t -> unit = <fun> +|}];; diff --git a/testsuite/tests/typing-poly/poly.ml b/testsuite/tests/typing-poly/poly.ml index fc46d8d3b8..0b82bf456e 100644 --- a/testsuite/tests/typing-poly/poly.ml +++ b/testsuite/tests/typing-poly/poly.ml @@ -1004,6 +1004,7 @@ type 'a t = < a : 'a > type u = 'a t as 'a |}];; + (* pass typetexp, but fails during Typedecl.check_recursion *) type ('a, 'b) a = 'a -> unit constraint 'a = [> `B of ('a, 'b) b as 'b] and ('a, 'b) b = 'b -> unit constraint 'b = [> `A of ('a, 'b) a as 'a];; diff --git a/testsuite/tests/typing-sigsubst/sigsubst.ml b/testsuite/tests/typing-sigsubst/sigsubst.ml index 7cfa290283..aa2191445f 100644 --- a/testsuite/tests/typing-sigsubst/sigsubst.ml +++ b/testsuite/tests/typing-sigsubst/sigsubst.ml @@ -24,11 +24,11 @@ end Line 3, characters 2-36: 3 | include Comparable with type t = t ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Error: Illegal shadowing of included type t/98 by t/102 +Error: Illegal shadowing of included type t/99 by t/103 Line 2, characters 2-19: - Type t/98 came from this include + Type t/99 came from this include Line 3, characters 2-23: - The value print has no valid type if t/98 is shadowed + The value print has no valid type if t/99 is shadowed |}] module type Sunderscore = sig diff --git a/testsuite/tests/unwind/check-linker-version.sh b/testsuite/tests/unwind/check-linker-version.sh index f1120da762..fabd0ed9bc 100755 --- a/testsuite/tests/unwind/check-linker-version.sh +++ b/testsuite/tests/unwind/check-linker-version.sh @@ -13,4 +13,4 @@ else test_result=${TEST_PASS}; fi -exit ${TEST_RESULT} +exit ${test_result} diff --git a/testsuite/tests/unwind/driver.ml b/testsuite/tests/unwind/driver.ml index 421f85a66e..ccc4eabc90 100644 --- a/testsuite/tests/unwind/driver.ml +++ b/testsuite/tests/unwind/driver.ml @@ -15,9 +15,18 @@ flags = "-cclib -Wl,-keep_dwarf_unwind" all_modules = "mylib.ml driver.ml stack_walker.c" program = "${test_build_directory}/unwind_test" ****** run +output = "${test_build_directory}/program-output" +stdout = "${output}" +stderr = "${output}" +******* check-program-output +reference = "${test_source_directory}/unwind_test.reference" *) let () = Mylib.foo1 Mylib.bar 1 2 3 4 5 6 7 8 9 10; Mylib.foo2 Mylib.baz 1 2 3 4 5 6 7 8 9 10 + +(* https://github.com/ocaml-multicore/ocaml-multicore/issues/274 *) +let () = + Mylib.foo1 Mylib.bob 1 2 3 4 5 6 7 8 9 10 diff --git a/testsuite/tests/unwind/mylib.ml b/testsuite/tests/unwind/mylib.ml index 318b537ad9..22b7e9ef60 100644 --- a/testsuite/tests/unwind/mylib.ml +++ b/testsuite/tests/unwind/mylib.ml @@ -18,3 +18,10 @@ let baz x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 = func_with_10_params x1 x2 x3 x4 x5 x6 x7 x8 x9 x10; func_with_10_params x1 x2 x3 x4 x5 x6 x7 x8 x9 x10; perform_stack_walk () + +(* https://github.com/ocaml-multicore/ocaml-multicore/issues/274 *) +external do_no_alloc: unit -> unit = "ml_do_no_alloc" [@@noalloc] + +let bob x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 = + func_with_10_params x1 x2 x3 x4 x5 x6 x7 x8 x9 x10; + do_no_alloc () diff --git a/testsuite/tests/unwind/mylib.mli b/testsuite/tests/unwind/mylib.mli index c1655228fc..91bdcae59e 100644 --- a/testsuite/tests/unwind/mylib.mli +++ b/testsuite/tests/unwind/mylib.mli @@ -8,3 +8,5 @@ val bar: int -> int -> int -> int -> int -> int -> int -> int -> int -> int -> unit val baz: int -> int -> int -> int -> int -> int -> int -> int -> int -> int -> unit +val bob: + int -> int -> int -> int -> int -> int -> int -> int -> int -> int -> unit diff --git a/testsuite/tests/unwind/stack_walker.c b/testsuite/tests/unwind/stack_walker.c index 09afcadd73..55eb9505b5 100644 --- a/testsuite/tests/unwind/stack_walker.c +++ b/testsuite/tests/unwind/stack_walker.c @@ -3,6 +3,7 @@ #include <string.h> #include <caml/callback.h> #include <caml/mlvalues.h> +#define UNW_LOCAL_ONLY #include <libunwind.h> value ml_func_with_10_params_native(value x1, value x2, value x3, value x4, @@ -12,10 +13,11 @@ value ml_func_with_10_params_native(value x1, value x2, value x3, value x4, } void error() { - exit(1); + printf("<error>\n"); + exit(1); } -void perform_stack_walk() { +value ml_perform_stack_walk(value unused) { unw_context_t ctxt; unw_getcontext(&ctxt); @@ -25,7 +27,6 @@ void perform_stack_walk() { if (result != 0) error(); } - int reached_main = 0; for (;;) { { @@ -34,26 +35,32 @@ void perform_stack_walk() { int result = unw_get_proc_name(&cursor, procname, sizeof(procname), &ip_offset); if (result != 0) error(); - if (strcmp(procname, "main") == 0) - reached_main = 1; - //printf("%s + %lld\n", procname, (long long int)ip_offset); + if (strlen(procname) > 4 && + !memcmp(procname, "caml", 4) && + 'A' <= procname[4] && procname[4] <= 'Z' && + strstr(procname+4, "__")) { + /* mangled OCaml name, unmangle and print */ + const char* mangled = procname + 4; + const char* mod_end = strstr(mangled, "__"); + const char* id_begin = strchr(mod_end + 2, '_'); + if (!id_begin) id_begin = mangled + strlen(mangled); + printf("%.*s.%.*s\n", mod_end - mangled, mangled, id_begin - (mod_end + 2), mod_end + 2); + } else { + printf("%s\n", procname); + } + if (!strcmp(procname, "main")) break; } { int result = unw_step(&cursor); - if (result == 0) break; + if (result == 0) error(); /* didn't make it to main() */ if (result < 0) error(); } } - //printf("Reached end of stack.\n"); - if (!reached_main) { - //printf("Failure: Did not reach main.\n"); - error(); - } + return Val_unit; } -value ml_perform_stack_walk() { - perform_stack_walk(); - return Val_unit; +value ml_do_no_alloc(value unused) { + return ml_perform_stack_walk(unused); } diff --git a/testsuite/tests/unwind/unwind_test.reference b/testsuite/tests/unwind/unwind_test.reference new file mode 100644 index 0000000000..68a0dec147 --- /dev/null +++ b/testsuite/tests/unwind/unwind_test.reference @@ -0,0 +1,24 @@ +ml_perform_stack_walk +caml_c_call +Mylib.baz +caml_apply10 +Mylib.foo2 +caml_apply11 +Driver.entry +caml_program +caml_start_program +caml_startup_common +caml_main +main +ml_perform_stack_walk +ml_do_no_alloc +Mylib.bob +caml_apply10 +Mylib.foo1 +caml_apply11 +Driver.entry +caml_program +caml_start_program +caml_startup_common +caml_main +main
\ No newline at end of file diff --git a/testsuite/tests/misc/ephetest.ml b/testsuite/tests/weak-ephe-final/ephetest.ml index 5db285ae28..7ddaee67e7 100644 --- a/testsuite/tests/misc/ephetest.ml +++ b/testsuite/tests/weak-ephe-final/ephetest.ml @@ -69,7 +69,7 @@ let test2 () = is_key_value test eph 125; is_data_value test eph 42; ra := ref 13; - Gc.minor (); + Gc.minor (); Gc.full_major (); is_key_unset test eph; is_data_unset test eph let () = (test2 [@inlined never]) () @@ -85,7 +85,7 @@ let test3 () = is_key_value test eph 125; is_data_value test eph 13; ra := ref 14; - Gc.minor (); + Gc.minor (); Gc.full_major (); is_key_unset test eph; is_data_unset test eph let () = (test3 [@inlined never]) () @@ -120,7 +120,7 @@ let test5 () = is_data_value test eph 43; !rb := ref 4; Gc.minor (); - Gc.minor (); + Gc.minor (); Gc.full_major (); is_key_unset test eph; is_data_unset test eph let () = (test5 [@inlined never]) () diff --git a/testsuite/tests/misc/ephetest.reference b/testsuite/tests/weak-ephe-final/ephetest.reference index 2699fdf7f9..2699fdf7f9 100644 --- a/testsuite/tests/misc/ephetest.reference +++ b/testsuite/tests/weak-ephe-final/ephetest.reference diff --git a/testsuite/tests/misc/ephetest2.ml b/testsuite/tests/weak-ephe-final/ephetest2.ml index 1b92172bd5..1b92172bd5 100644 --- a/testsuite/tests/misc/ephetest2.ml +++ b/testsuite/tests/weak-ephe-final/ephetest2.ml diff --git a/testsuite/tests/misc/ephetest2.reference b/testsuite/tests/weak-ephe-final/ephetest2.reference index db17cd7aa6..db17cd7aa6 100644 --- a/testsuite/tests/misc/ephetest2.reference +++ b/testsuite/tests/weak-ephe-final/ephetest2.reference diff --git a/testsuite/tests/misc/ephetest3.ml b/testsuite/tests/weak-ephe-final/ephetest3.ml index e9c2b0f170..541910c91a 100644 --- a/testsuite/tests/misc/ephetest3.ml +++ b/testsuite/tests/weak-ephe-final/ephetest3.ml @@ -27,7 +27,6 @@ let pp = Int64.to_string module HW = Ephemeron.K1.Make(S) module SW = Weak.Make(S) - let sw = SW.create n let hashcons x = SW.merge sw x diff --git a/testsuite/tests/misc/ephetest3.reference b/testsuite/tests/weak-ephe-final/ephetest3.reference index 4fd03fb906..4fd03fb906 100644 --- a/testsuite/tests/misc/ephetest3.reference +++ b/testsuite/tests/weak-ephe-final/ephetest3.reference diff --git a/testsuite/tests/weak-ephe-final/ephetest4.ml b/testsuite/tests/weak-ephe-final/ephetest4.ml new file mode 100644 index 0000000000..6647c8375b --- /dev/null +++ b/testsuite/tests/weak-ephe-final/ephetest4.ml @@ -0,0 +1,33 @@ +(* TEST *) + +module E = Ephemeron.K1 + +let e = E.create () + +let _ = + let k = ref (ref 0) in + E.set_key e !k; + assert (E.check_key e); + Gc.full_major (); + assert (E.check_key e); + let d = Domain.spawn (fun () -> + let d = ref 0 in + E.set_data e d; + assert (E.check_key e); + assert (E.check_data e); + Gc.full_major (); + assert (E.check_key e); + assert (E.check_data e)) + in + Domain.join d; + assert (E.check_key e); + assert (E.check_data e); + Gc.full_major (); + assert (E.check_key e); + assert (E.check_data e); + assert (!(!k) = 0); + k := ref 0; + Gc.full_major (); + assert (not (E.check_key e)); + assert (not (E.check_data e)); + print_endline "ok" diff --git a/testsuite/tests/weak-ephe-final/ephetest4.reference b/testsuite/tests/weak-ephe-final/ephetest4.reference new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/testsuite/tests/weak-ephe-final/ephetest4.reference @@ -0,0 +1 @@ +ok diff --git a/testsuite/tests/weak-ephe-final/ephetest5.ml b/testsuite/tests/weak-ephe-final/ephetest5.ml new file mode 100644 index 0000000000..a9d684dae3 --- /dev/null +++ b/testsuite/tests/weak-ephe-final/ephetest5.ml @@ -0,0 +1,105 @@ +(* TEST *) + +module E = Ephemeron.K1 + +module S = struct + let make () = Atomic.make false + + let rec wait s = + let success = + Domain.Sync.critical_section (fun () -> + if Atomic.get s then true + else (Domain.Sync.wait (); false)) + in + if success then () else wait s + + let notify s d = + Atomic.set s true; + Domain.Sync.notify d +end + +let e1 = E.create () + +let _ = + let k = ref (ref 0) in + E.set_key e1 !k; + assert (E.check_key e1); + assert (not (E.check_data e1)); + Gc.full_major (); + assert (E.check_key e1); + assert (not (E.check_data e1)); + + let s1,s2 = S.make(), S.make() in + let main_domain = Domain.self () in + let child_domain = Domain.spawn (fun () -> + let e2 = E.create () in + E.set_key e2 !k; + E.set_data e1 e2; + assert (E.check_key e1); + assert (E.check_data e1); + assert (E.check_key e2); + assert (not (E.check_data e2)); + Gc.full_major (); + assert (E.check_key e1); + assert (E.check_data e1); + assert (E.check_key e2); + assert (not (E.check_data e2)); + S.notify s1 main_domain; + + S.wait s2; + let e3 = match E.get_data e2 with + | Some e -> e + | None -> assert false + in + + Gc.full_major(); + assert (E.check_key e1); + assert (E.check_data e1); + assert (E.check_key e2); + assert (E.check_data e2); + assert (E.check_key e3); + assert (E.check_data e3) + ) + in + + let _ = S.wait s1 in + let e2 = match E.get_data e1 with + | Some e -> e + | None -> assert (false) + in + + let e3 = E.create () in + E.set_key e3 !k; + E.set_data e3 0; + E.set_data e2 e3; + + Gc.full_major (); + assert (E.check_key e1); + assert (E.check_data e1); + assert (E.check_key e2); + assert (E.check_data e2); + assert (E.check_key e3); + assert (E.check_data e3); + + S.notify s2 (Domain.get_id child_domain); + Domain.join child_domain; + + Gc.full_major (); + assert (E.check_key e1); + assert (E.check_data e1); + assert (E.check_key e2); + assert (E.check_data e2); + assert (E.check_key e3); + assert (E.check_data e3); + + assert (!(!k) = 0); + k := ref 0; + Gc.full_major (); + assert (not (E.check_key e1)); + assert (not (E.check_data e1)); + assert (not (E.check_key e2)); + assert (not (E.check_data e2)); + assert (not (E.check_key e3)); + assert (not (E.check_data e3)); + print_endline "ok" + diff --git a/testsuite/tests/weak-ephe-final/ephetest5.reference b/testsuite/tests/weak-ephe-final/ephetest5.reference new file mode 100644 index 0000000000..9766475a41 --- /dev/null +++ b/testsuite/tests/weak-ephe-final/ephetest5.reference @@ -0,0 +1 @@ +ok diff --git a/testsuite/tests/weak-ephe-final/ephetest6.ml b/testsuite/tests/weak-ephe-final/ephetest6.ml new file mode 100644 index 0000000000..19ac0b9044 --- /dev/null +++ b/testsuite/tests/weak-ephe-final/ephetest6.ml @@ -0,0 +1,68 @@ +(* TEST *) + +module E = Ephemeron.Kn + +let test1 = + let e1 = E.create 16 in + for i = 0 to 15 do + E.set_key e1 i i + done; + let d = Domain.spawn (fun () -> + let e2 = E.create 16 in + E.blit_key e1 0 e2 0 16; + match E.get_key e2 1 with + | Some 1 -> () + | _ -> assert false) + in + Domain.join d; + print_endline "test1: ok" + +let _ = Gc.full_major () + +let test2 = + let e1 = E.create 16 in + let d = Domain.spawn (fun () -> + let e2 = E.create 16 in + for i = 0 to 15 do + E.set_key e2 i i + done; + E.blit_key e2 0 e1 0 16; + match E.get_key e1 1 with + | Some 1 -> () + | _ -> assert false) + in + Domain.join d; + print_endline "test2: ok" + +let test3 = + let e1 = E.create 16 in + for i = 0 to 15 do + E.set_key e1 i i + done; + let d1 = Domain.spawn (fun () -> + let e2 = E.create 16 in + let d2 = Domain.spawn (fun () -> + E.blit_key e1 0 e2 0 16; + match E.get_key e2 1 with + | Some 1 -> () + | _ -> assert false) + in + Domain.join d2) + in + Domain.join d1; + print_endline "test3: ok" + +let test4 = + let e1 = E.create 16 in + for i = 0 to 15 do + E.set_key e1 i i + done; + let e2 = E.create 16 in + let d = Domain.spawn (fun () -> + E.blit_key e1 0 e2 0 16; + match E.get_key e2 1 with + | Some 1 -> () + | _ -> assert false) + in + Domain.join d; + print_endline "test4: ok" diff --git a/testsuite/tests/weak-ephe-final/ephetest6.reference b/testsuite/tests/weak-ephe-final/ephetest6.reference new file mode 100644 index 0000000000..26552a8592 --- /dev/null +++ b/testsuite/tests/weak-ephe-final/ephetest6.reference @@ -0,0 +1,4 @@ +test1: ok +test2: ok +test3: ok +test4: ok diff --git a/testsuite/tests/weak-ephe-final/ephetest_par.ml b/testsuite/tests/weak-ephe-final/ephetest_par.ml new file mode 100644 index 0000000000..a8f36901f5 --- /dev/null +++ b/testsuite/tests/weak-ephe-final/ephetest_par.ml @@ -0,0 +1,194 @@ +(* TEST *) + +open Printf +open Ephemeron + +(* Due to GCs running at non-deterministic places, the output from these tests + * are unreliable except the bad value checks and as a check for catastrophic + * failures i.e) segfaults. *) + +let debug = false + +let dprintf x = + if debug then printf x + else ifprintf stdout x + +let is_true test s b = + if debug then + printf "%s %s: %s\n" test s (if b then "OK" else "FAIL") + +let is_false test s b = is_true test s (not b) + +let is_data_value test eph (v:int) = + match K1.get_data_copy eph with + | Some x -> + if !x = v + then dprintf "%s data set: OK\n" test + else printf "%s data set: FAIL(bad value %i)\n" test (!x) + | None -> dprintf "%s data set: FAIL\n" test + +let is_key_value test eph (v:int) = + match K1.get_key_copy eph with + | Some x -> + if !x = v + then dprintf "%s key set: OK\n" test + else printf "%s key set: FAIL(bad value %i)\n" test (!x) + | None -> dprintf "%s key unset: FAIL\n" test + +let is_key_unset test eph = + is_false test "key unset" (K1.check_key eph) + +let is_data_unset test eph = + is_false test "data unset" (K1.check_data eph) + +module M() = struct + +let make_ra () = ref (ref 1) [@@inline never] +let make_rb () = ref (ref (ref 2)) [@@inline never] +let ra = make_ra () +let rb = make_rb () + +(** test: key alive data dangling *) +let test1 () = + let test = "test1" in + Gc.minor (); + Gc.full_major (); + let eph : (int ref, int ref) K1.t = K1.create () in + K1.set_key eph (!ra); + K1.set_data eph (ref 42); + is_key_value test eph 1; + is_data_value test eph 42; + Gc.minor (); + is_key_value test eph 1; + is_data_value test eph 42; + Gc.full_major (); + is_key_value test eph 1; + is_data_value test eph 42; + ra := ref 12; + Gc.full_major (); + is_key_unset test eph; + is_data_unset test eph + +(** test: key dangling data dangling *) +let test2 () = + let test = "test2" in + Gc.minor (); + Gc.full_major (); + let eph : (int ref, int ref) K1.t = K1.create () in + K1.set_key eph (ref 125); + K1.set_data eph (ref 42); + is_key_value test eph 125; + is_data_value test eph 42; + ra := ref 13; + Gc.minor (); + is_key_unset test eph; + is_data_unset test eph + +(** test: key dangling data alive *) +let test3 () = + let test = "test3" in + Gc.minor (); + Gc.full_major (); + let eph : (int ref, int ref) K1.t = K1.create () in + K1.set_key eph (ref 125); + K1.set_data eph (!ra); + is_key_value test eph 125; + is_data_value test eph 13; + ra := ref 14; + Gc.minor (); + is_key_unset test eph; + is_data_unset test eph + +(** test: key alive but one away, data dangling *) +let test4 () = + let test = "test4" in + Gc.minor (); + Gc.full_major (); + let eph : (int ref, int ref) K1.t = K1.create () in + rb := ref (ref 3); + K1.set_key eph (!(!rb)); + K1.set_data eph (ref 43); + is_key_value test eph 3; + is_data_value test eph 43; + Gc.minor (); + Gc.minor (); + is_key_value test eph 3; + is_data_value test eph 43 + +(** test: key dangling but one away, data dangling *) +let test5 () = + let test = "test5" in + Gc.minor (); + Gc.full_major (); + let eph : (int ref, int ref) K1.t = K1.create () in + rb := ref (ref 3); + K1.set_key eph (!(!rb)); + K1.set_data eph (ref 43); + is_key_value test eph 3; + is_data_value test eph 43; + !rb := ref 4; + Gc.minor (); + Gc.minor (); + is_key_unset test eph; + is_data_unset test eph + +(** test: key accessible from data but all dangling *) +let test6 () = + let test = "test6" in + Gc.minor (); + Gc.full_major (); + let eph : (int ref, int ref ref) K1.t = K1.create () in + rb := ref (ref 3); + K1.set_key eph (!(!rb)); + K1.set_data eph (ref (!(!rb))); + Gc.minor (); + is_key_value test eph 3; + !rb := ref 4; + Gc.full_major (); + is_key_unset test eph; + is_data_unset test eph + +(** test: ephemeron accessible from data but they are dangling *) +type t = + | No + | Ephe of (int ref, t) K1.t + +let rc = ref No + +let test7 () = + let test = "test7" in + Gc.minor (); + Gc.full_major (); + ra := ref 42; + let weak : t Weak.t = Weak.create 1 in + let eph : (int ref, t) K1.t ref = ref (K1.create ()) in + rc := Ephe !eph; + Weak.set weak 0 (Some !rc); + K1.set_key !eph !ra; + K1.set_data !eph !rc; + Gc.minor (); + is_true test "before" (Weak.check weak 0); + eph := K1.create (); + rc := No; + Gc.full_major (); + Gc.full_major (); + Gc.full_major (); + is_false test "after" (Weak.check weak 0) + +let run () = + (test1 [@inlined never]) (); + (test2 [@inlined never]) (); + (test3 [@inlined never]) (); + (test4 [@inlined never]) (); + (test5 [@inlined never]) (); + (test6 [@inlined never]) (); + (test7 [@inlined never]) (); + () +end + +let _ = + let module M1 = M() in + let module M2 = M() in + let d = Domain.spawn M2.run in + M1.run(); + Domain.join d diff --git a/testsuite/tests/misc/weaklifetime.reference b/testsuite/tests/weak-ephe-final/ephetest_par.reference index e69de29bb2..e69de29bb2 100644 --- a/testsuite/tests/misc/weaklifetime.reference +++ b/testsuite/tests/weak-ephe-final/ephetest_par.reference diff --git a/testsuite/tests/misc/finaliser.ml b/testsuite/tests/weak-ephe-final/finaliser.ml index 68cb7b2662..68cb7b2662 100644 --- a/testsuite/tests/misc/finaliser.ml +++ b/testsuite/tests/weak-ephe-final/finaliser.ml diff --git a/testsuite/tests/weak-ephe-final/finaliser.reference b/testsuite/tests/weak-ephe-final/finaliser.reference new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testsuite/tests/weak-ephe-final/finaliser.reference diff --git a/testsuite/tests/weak-ephe-final/finaliser2.ml b/testsuite/tests/weak-ephe-final/finaliser2.ml new file mode 100644 index 0000000000..c12d2cfd6b --- /dev/null +++ b/testsuite/tests/weak-ephe-final/finaliser2.ml @@ -0,0 +1,36 @@ +(* TEST *) + +let test1 = + let r' = ref 0 in + let rec foo () = + let r = ref 0 in + Gc.finalise_last (fun _ -> r' := 1; print_endline "test1") r + in + foo(); + Gc.minor(); + assert (!r' = 1) + +let test2 = + let r = ref 0 in + Gc.finalise (fun r -> assert (!r = 1); print_endline "test2: 1") r; + Gc.finalise (fun r -> assert (!r = 0); print_endline "test2: 2"; r := 1) r; + Gc.full_major() + +let test3 = + Gc.full_major (); + let rec foo () = + let r = ref 0 in + Gc.finalise (fun r -> print_endline "test3: parent.1") r; + in + foo (); + let d = Domain.spawn (fun _ -> + let r = ref 0 in + let r' = ref 0 in + Gc.full_major (); + Gc.finalise (fun r -> print_endline "test3: child.1") r; + Gc.finalise_last (fun r -> print_endline "test3: child.2") r') + in + Domain.join d; + print_endline "test3: joined"; + (* Now this domain takes over the finalisers from d *) + Gc.full_major() diff --git a/testsuite/tests/weak-ephe-final/finaliser2.reference b/testsuite/tests/weak-ephe-final/finaliser2.reference new file mode 100644 index 0000000000..0082f00781 --- /dev/null +++ b/testsuite/tests/weak-ephe-final/finaliser2.reference @@ -0,0 +1,7 @@ +test1 +test2: 2 +test2: 1 +test3: joined +test3: parent.1 +test3: child.1 +test3: child.2 diff --git a/testsuite/tests/misc/weaklifetime.ml b/testsuite/tests/weak-ephe-final/weaklifetime.ml index 49c701a94b..ea47d41eab 100644 --- a/testsuite/tests/misc/weaklifetime.ml +++ b/testsuite/tests/weak-ephe-final/weaklifetime.ml @@ -27,12 +27,16 @@ let data = ) ;; -let gccount () = (Gc.quick_stat ()).Gc.major_collections;; +let gccount () = + let res = (Gc.quick_stat ()).Gc.major_collections in + res (* Check the correctness condition on the data at (i,j): 1. if the block is present, the weak pointer must be full 2. if the block was removed at GC n, and the weak pointer is still - full, then the current GC must be at most n+1. + full, then the current GC must be at most n+2. + (could have promotion from minor during n+1 which keeps alive in n+1, + so will die at n+2) Then modify the data in one of the following ways: 1. if the block and weak pointer are absent, fill them @@ -42,7 +46,7 @@ let check_and_change i j = let gc1 = gccount () in match data.(i).objs.(j), Weak.check data.(i).wp j with | Present x, false -> assert false - | Absent n, true -> assert (gc1 <= n+1) + | Absent n, true -> assert (gc1 <= n+2) | Absent _, false -> let x = Array.make (1 + Random.int 10) 42 in data.(i).objs.(j) <- Present x; diff --git a/testsuite/tests/weak-ephe-final/weaklifetime.reference b/testsuite/tests/weak-ephe-final/weaklifetime.reference new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testsuite/tests/weak-ephe-final/weaklifetime.reference diff --git a/testsuite/tests/misc/weaklifetime2.ml b/testsuite/tests/weak-ephe-final/weaklifetime2.ml index 2c75b00bfe..2c75b00bfe 100644 --- a/testsuite/tests/misc/weaklifetime2.ml +++ b/testsuite/tests/weak-ephe-final/weaklifetime2.ml diff --git a/testsuite/tests/misc/weaklifetime2.reference b/testsuite/tests/weak-ephe-final/weaklifetime2.reference index cfb2161ccc..cfb2161ccc 100644 --- a/testsuite/tests/misc/weaklifetime2.reference +++ b/testsuite/tests/weak-ephe-final/weaklifetime2.reference diff --git a/testsuite/tests/misc/weaktest.ml b/testsuite/tests/weak-ephe-final/weaktest.ml index 292e76622c..292e76622c 100644 --- a/testsuite/tests/misc/weaktest.ml +++ b/testsuite/tests/weak-ephe-final/weaktest.ml diff --git a/testsuite/tests/misc/weaktest.reference b/testsuite/tests/weak-ephe-final/weaktest.reference index 2ae28399f5..2ae28399f5 100644 --- a/testsuite/tests/misc/weaktest.reference +++ b/testsuite/tests/weak-ephe-final/weaktest.reference diff --git a/testsuite/tools/asmgen_amd64.S b/testsuite/tools/asmgen_amd64.S index fb87307df0..4c4b3909b0 100644 --- a/testsuite/tools/asmgen_amd64.S +++ b/testsuite/tools/asmgen_amd64.S @@ -21,14 +21,8 @@ #ifdef SYS_macosx #define CALL_GEN_CODE _call_gen_code -#define CAML_C_CALL _caml_c_call -#define CAML_NEGF_MASK _caml_negf_mask -#define CAML_ABSF_MASK _caml_absf_mask #else #define CALL_GEN_CODE call_gen_code -#define CAML_C_CALL caml_c_call -#define CAML_NEGF_MASK caml_negf_mask -#define CAML_ABSF_MASK caml_absf_mask #endif .globl CALL_GEN_CODE @@ -54,30 +48,3 @@ CALL_GEN_CODE: popq %rbx ret - .globl CAML_C_CALL - .align ALIGN -CAML_C_CALL: - jmp *%rax - -#ifdef SYS_macosx - .literal16 -#elif defined(SYS_mingw64) || defined(SYS_cygwin) - .section .rodata.cst8 -#else - .section .rodata.cst8,"aM",@progbits,8 -#endif - .globl CAML_NEGF_MASK - .align ALIGN -CAML_NEGF_MASK: - .quad 0x8000000000000000, 0 - .globl CAML_ABSF_MASK - .align ALIGN -CAML_ABSF_MASK: - .quad 0x7FFFFFFFFFFFFFFF, 0 - - .comm young_limit, 8 - -#if defined(SYS_linux) - /* Mark stack as non-executable */ - .section .note.GNU-stack,"",%progbits -#endif diff --git a/testsuite/tools/lexcmm.mll b/testsuite/tools/lexcmm.mll index 026c2ed35d..c31317888a 100644 --- a/testsuite/tools/lexcmm.mll +++ b/testsuite/tools/lexcmm.mll @@ -64,8 +64,8 @@ let keyword_table = "mulh", MULH; "or", OR; "proj", PROJ; - "raise", RAISE Lambda.Raise_regular; - "reraise", RAISE Lambda.Raise_reraise; + "raise_regular", RAISE Lambda.Raise_regular; + "raise_reraise", RAISE Lambda.Raise_reraise; "raise_notrace", RAISE Lambda.Raise_notrace; "seq", SEQ; "signed", SIGNED; diff --git a/testsuite/tools/parsecmm.mly b/testsuite/tools/parsecmm.mly index 643ee9cb1f..9697c10148 100644 --- a/testsuite/tools/parsecmm.mly +++ b/testsuite/tools/parsecmm.mly @@ -255,19 +255,20 @@ expr: { unbind_ident $5; Ctrywith($3, $5, $6, debuginfo ()) } | LPAREN VAL expr expr RPAREN { let open Asttypes in - Cop(Cload (Word_val, Mutable), [access_array $3 $4 Arch.size_addr], + Cop(Cload {memory_chunk=Word_val; mutability=Mutable; is_atomic=false}, [access_array $3 $4 Arch.size_addr], debuginfo ()) } | LPAREN ADDRAREF expr expr RPAREN { let open Asttypes in - Cop(Cload (Word_val, Mutable), [access_array $3 $4 Arch.size_addr], + Cop(Cload {memory_chunk=Word_val; mutability=Mutable; is_atomic=false}, [access_array $3 $4 Arch.size_addr], Debuginfo.none) } | LPAREN INTAREF expr expr RPAREN { let open Asttypes in - Cop(Cload (Word_int, Mutable), [access_array $3 $4 Arch.size_int], + Cop(Cload {memory_chunk=Word_int; mutability=Mutable; is_atomic=false}, [access_array $3 $4 Arch.size_int], Debuginfo.none) } | LPAREN FLOATAREF expr expr RPAREN { let open Asttypes in - Cop(Cload (Double_u, Mutable), [access_array $3 $4 Arch.size_float], + Cop(Cload {memory_chunk=Double_u; mutability=Mutable; is_atomic=false}, [access_array $3 $4 Arch.size_float], + Debuginfo.none) } | LPAREN ADDRASET expr expr expr RPAREN { let open Lambda in @@ -323,7 +324,7 @@ chunk: | VAL { Word_val } ; unaryop: - LOAD chunk { Cload ($2, Asttypes.Mutable) } + LOAD chunk { Cload {memory_chunk=$2; mutability=Asttypes.Mutable; is_atomic=false} } | FLOATOFINT { Cfloatofint } | INTOFFLOAT { Cintoffloat } | RAISE { Craise $1 } diff --git a/tools/ci/actions/runner.sh b/tools/ci/actions/runner.sh new file mode 100644 index 0000000000..1e0712cc70 --- /dev/null +++ b/tools/ci/actions/runner.sh @@ -0,0 +1,124 @@ +#!/usr/bin/env bash +#************************************************************************** +#* * +#* OCaml * +#* * +#* Anil Madhavapeddy, OCaml Labs * +#* * +#* Copyright 2014 Institut National de Recherche en Informatique et * +#* en Automatique. * +#* * +#* All rights reserved. This file is distributed under the terms of * +#* the GNU Lesser General Public License version 2.1, with the * +#* special exception on linking described in the file LICENSE. * +#* * +#************************************************************************** + +set -xe + +PREFIX=~/local + +MAKE="make $MAKE_ARG" +SHELL=dash + +export PATH=$PREFIX/bin:$PATH + +Configure () { + mkdir -p $PREFIX + cat<<EOF +------------------------------------------------------------------------ +This test builds the OCaml compiler distribution with your pull request +and runs its testsuite. +Failing to build the compiler distribution, or testsuite failures are +critical errors that must be understood and fixed before your pull +request can be merged. +------------------------------------------------------------------------ +EOF + + configure_flags="\ + --prefix=$PREFIX \ + --enable-debug-runtime \ + $CONFIG_ARG" + + case $XARCH in + x64) + ./configure $configure_flags + ;; + i386) + ./configure --build=x86_64-pc-linux-gnu --host=i386-linux \ + CC='gcc -m32' AS='as --32' ASPP='gcc -m32 -c' \ + PARTIALLD='ld -r -melf_i386' \ + $configure_flags + ;; + *) + echo unknown arch + exit 1 + ;; + esac +} + +Build () { + $MAKE world.opt +} + +Test () { + echo Running the testsuite + $MAKE -C testsuite all-enabled + cd .. +} + +API_Docs () { + echo Ensuring that all library documentation compiles + $MAKE -C ocamldoc html_doc pdf_doc texi_doc +} + +Install () { + $MAKE install +} + +Checks () { + if fgrep 'SUPPORTS_SHARED_LIBRARIES=true' Makefile.config &>/dev/null ; then + echo Check the code examples in the manual + $MAKE manual-pregen + fi + # check_all_arches checks tries to compile all backends in place, + # we would need to redo (small parts of) world.opt afterwards to + # use the compiler again + $MAKE check_all_arches + # Ensure that .gitignore is up-to-date - this will fail if any untreacked or + # altered files exist. + test -z "$(git status --porcelain)" + # check that the 'clean' target also works + $MAKE clean + $MAKE -C manual clean + # check that the `distclean` target definitely cleans the tree + $MAKE distclean + # Check the working tree is clean + test -z "$(git status --porcelain)" + # Check that there are no ignored files + test -z "$(git ls-files --others -i --exclude-standard)" +} + +CheckManual () { + cat<<EOF +-------------------------------------------------------------------------- +This test checks the global structure of the reference manual +(e.g. missing chapters). +-------------------------------------------------------------------------- +EOF + # we need some of the configuration data provided by configure + ./configure + $MAKE check-stdlib check-case-collision -C manual/tests + +} + +case $1 in +configure) Configure;; +build) Build;; +test) Test;; +api-docs) API_Docs;; +install) Install;; +other-checks) Checks;; +*) echo "Unknown CI instruction: $1" + exit 1;; +esac diff --git a/tools/dumpobj.ml b/tools/dumpobj.ml index e2b8b4d10d..0efe236bfb 100644 --- a/tools/dumpobj.ml +++ b/tools/dumpobj.ml @@ -323,6 +323,11 @@ let op_shapes = [ opGETFIELD2, Nothing; opGETFIELD3, Nothing; opGETFIELD, Uint; + opGETMUTABLEFIELD0, Nothing; + opGETMUTABLEFIELD1, Nothing; + opGETMUTABLEFIELD2, Nothing; + opGETMUTABLEFIELD3, Nothing; + opGETMUTABLEFIELD, Uint; opGETFLOATFIELD, Uint; opSETFIELD0, Nothing; opSETFIELD1, Nothing; @@ -395,6 +400,10 @@ let op_shapes = [ opUGEINT, Nothing; opBULTINT, Uint_Disp; opBUGEINT, Uint_Disp; + opPERFORM, Nothing; + opRESUME, Nothing; + opRESUMETERM, Uint; + opREPERFORMTERM, Uint; opSTOP, Nothing; opEVENT, Nothing; opBREAK, Nothing; diff --git a/tools/eventlog_to_latencies.py b/tools/eventlog_to_latencies.py new file mode 100644 index 0000000000..6bdfc3b5aa --- /dev/null +++ b/tools/eventlog_to_latencies.py @@ -0,0 +1,107 @@ +from intervaltree import IntervalTree, Interval +import sys +import subprocess +import json +import os + +if len(sys.argv) < 2: + print ("Usage: %s EVENTLOG\n" % sys.argv[0]) + print ("Generate GC latency distribution report from eventlog") + sys.exit(1) + +json_file = sys.argv[1] + +percentages = [10,20,30,40,50,60,70,80,90,95,99,99.9] + +def distribution(l): + to_indices = [] + for p in percentages: + i = int(round(float(len(l))*float(p)/100.0-1,0)) + to_indices.append(i) + i = 0 + distr = [] + while (i < len(percentages)): + if (to_indices[i] == -1): + distr.append(0) + else: + distr.append(l[to_indices[i]]) + i+=1 + + return distr + +def main(): + trees = {} + with open(json_file) as f: + data = json.load(f) + stacks = {} + for event in data["traceEvents"]: + if (event["ph"] == "B"): + key = str(event["pid"])+":"+str(event["tid"]) + ts = int(float(event["ts"])*1000.0) + name = event["name"] + if key in stacks: + stacks[key].append((name,ts,0)) + else: + stacks[key] = [(name,ts,0)] + elif (event["ph"] == "E"): + key = str(event["pid"])+":"+str(event["tid"]) + ts = int(float(event["ts"])*1000.0) + name = event["name"] + (nameStart, startTs, overhead) = stacks[key].pop() + assert (nameStart == name) + if not key in trees: + trees[key] = IntervalTree() + trees[key].addi(startTs, ts, {'name': name, 'overhead': overhead, 'tid': event["tid"]}) + elif (event["ph"] == "C" and event["name"] == "overhead#"): + key = str(event["pid"])+":"+str(event["tid"]) + overhead = int(event["args"]["value"]) + l = [] + for e in stacks[key]: + (name,ts,o) = e + l.append((name,ts,o+overhead)) + stacks[key] = l + + latencies = [] + intervals = [] + + for t in trees.values(): + domain_terminate_intervals = IntervalTree((i for i in t if i.data['name'].startswith("major_gc/finish_"))) + t.merge_overlaps((lambda acc,v: {'name': acc['name'], 'overhead': acc['overhead'] + v['overhead'], 'tid': acc['tid']})) + latencies = latencies + list(map(lambda x: x.end - x.begin - x.data['overhead'], sorted(t - domain_terminate_intervals))) + intervals.extend(t) + sorted_latencies = sorted(latencies) + + if (len(sorted_latencies) > 0): + max_latency = sorted_latencies[len(sorted_latencies) - 1] + avg_latency = sum(sorted_latencies)/len(sorted_latencies) + else: + max_latency = 0 + avg_latency = 0 + + distr = distribution(sorted_latencies) + + out = {} + print ("Mean latency = " + str(avg_latency) + " ns") + print ("Max latency = " + str(max_latency) + " ns") + print ("") + print ("## Latency distribution") + print ("") + print ("Percentile, Latency(ns)") + for (p,l) in zip(percentages,distr): + print(str(p) + "," + str(l)) + + sorted_intervals = sorted(intervals, key=lambda i: -(i.end - i.begin)) + + print ("") + print ("## Top slowest events") + print ("") + print ("Latency(ns), Start Timestamp(ns), End TimeStamp(ns), Event, Overhead, Domain ID") + for interval in sorted_intervals[0:32]: + print(str(interval.end - interval.begin) + ", " + + str(interval.begin) + ", " + + str(interval.end) + ", " + + interval.data['name'] + ", " + + str(interval.data['overhead']) + ", " + + str(interval.data['tid'])) + +main() diff --git a/tools/gdb_ocamlrun.py b/tools/gdb_ocamlrun.py new file mode 100644 index 0000000000..7820de1e83 --- /dev/null +++ b/tools/gdb_ocamlrun.py @@ -0,0 +1,154 @@ +import gdb + +TAGS = { + 246: 'Lazy_tag', + 247: 'Closure_tag', + 248: 'Object_tag', + 249: 'Infix_tag', + 250: 'Forward_tag', + 251: 'Abstract_tag', + 252: 'String_tag', + 253: 'Double_tag', + 254: 'Double_array_tag', + 255: 'Custom_tag' +} + +No_scan_tag = 251 + + +debug_tags = { + 0x00: 'Debug_free_minor', + 0x01: 'Debug_free_major', + 0x03: 'Debug_free_shrink', + 0x04: 'Debug_free_truncat', + 0x10: 'Debug_uninit_minor', + 0x11: 'Debug_uninit_major', + 0x15: 'Debug_uninit_align', + 0x85: 'Debug_filler_align' +} + +class DoublePrinter: + def __init__(self, tag, length, p): + assert tag in ['Double_tag', 'Double_array_tag'] + self.tag = tag + self.length = length + self.p = p + + def children(self): + pass + + def to_string(self): + return '%s[%d]' % (self.tag, self.length) + +class ConstPrinter: + def __init__(self, rep): + self.rep = rep + def to_string(self): + return self.rep + +class BlockPrinter: + def __init__(self, val): + if val & 1 == 1: + self.tag = 1000 + self.tagname = 'I' + self.val = val + else: + self.p = val.cast(val.type.pointer()) + header = (self.p - 1).dereference() + self.length = int(header >> 10) + self.gc = int(header & (3 << 8)) + self.tag = int(header & 255) + self.tagname = TAGS.get(self.tag, 'Block') + + def children(self): +# if self.tag < No_scan_tag: +# fields = self.p.cast(gdb.lookup_type('value').pointer()) +# for i in range(self.length): +# yield '[%d]' % i, (fields + i).dereference() +# elif self.tagname == 'Double_array_tag': +# words_per_double = \ +# gdb.lookup_type('double').sizeof / gdb.lookup_type('value').sizeof +# fields = self.p.cast(gdb.lookup_type('double').pointer()) +# for i in range(int(self.length / words_per_double)): +# yield '[%d]' % i, (fields + i).dereference() +# + return [] + + def to_string(self): + if self.tag == 1000: + # it's an immediate value + if gdb.lookup_type('value').sizeof == 8: + debug_mask = 0xff00ffffff00ffff + debug_val = 0xD700D7D7D700D6D7 + else: + debug_mask = 0xff00ffff + debug_val = 0xD700D6D7 + n = self.val + if (n & debug_mask) == debug_val: + tag = int((n >> 16) & 0xff) + return debug_tags.get(tag, + "Debug_tag(0x%x)" % int(tag)) + else: + return "I(%d)" % int(n >> 1) + + # otherwise, it's a block + + if self.tagname == 'Double_tag': + d = self.p.cast(gdb.lookup_type('double').pointer()).dereference() + s = '%f, wosize=1' % d + elif self.tagname == 'String_tag': + char = gdb.lookup_type('unsigned char') + val_size = gdb.lookup_type('value').sizeof + lastbyte = ((self.p + self.length - 1).cast(char.pointer()) + val_size - 1).dereference() + length_bytes = self.length * val_size - (lastbyte + 1) + string = (self.p.cast(char.array(length_bytes).pointer()).dereference()) + s = str(string).strip() + elif self.tagname == 'Infix_tag': + s = 'offset=%d' % (-self.length) + elif self.tagname == 'Custom_tag': + ops = self.p.dereference().cast(gdb.lookup_type('struct custom_operations').pointer()) + s = '%s, wosize=%d' % (str(ops), self.length) + elif self.tagname == 'Block': + s = '%d, wosize=%d' % (self.tag,self.length) + else: + s = 'wosize=%d' % self.length + + markbits = gdb.lookup_symbol("global")[0].value() + gc = { + int(markbits['MARKED']): 'MARKED', + int(markbits['UNMARKED']): 'UNMARKED', + int(markbits['GARBAGE']): 'GARBAGE', + (3 << 8): 'NOT_MARKABLE' + } + return '%s(%s, %s)' % (self.tagname, s, gc[self.gc]) + + + def display_hint (self): + return 'array' + + + +class Fields(gdb.Function): + def __init__ (self): + super (Fields, self).__init__ ("F") + + def invoke (self, val): + assert str(val.type) == 'value' + p = val.cast(val.type.pointer()) + header = (p - 1).dereference() + length = int(header >> 10) + + return p.cast(val.type.array(length - 1).pointer()).dereference() + + +Fields() + + +def value_printer(val): + if str(val.type) != 'value': + return None + + + return BlockPrinter(val) + +gdb.pretty_printers = [value_printer] diff --git a/tools/list-globals b/tools/list-globals new file mode 100755 index 0000000000..d8b04f23bc --- /dev/null +++ b/tools/list-globals @@ -0,0 +1,9 @@ +#!/bin/bash + +[ -z "$@" ] && { echo "Usage: $0 <foo.[oa]>" > /dev/stderr; exit 2; } + +nm -A -f sysv "$@" |\ + awk ' + BEGIN {FS = " *[|] *"} + NF > 1 && $4 != "TLS" && $7 != ".text" && $7 != "*COM*" && $3 !~ /^[TtURr]$/ {print $3 " " $1} + ' diff --git a/tools/ocaml-update-c b/tools/ocaml-update-c new file mode 100755 index 0000000000..ebafade532 --- /dev/null +++ b/tools/ocaml-update-c @@ -0,0 +1,15 @@ +#!/bin/sh + +if [ -z "$@" ]; then + echo "Usage: $0 file.c" 1>&2 + exit 1 +fi + +sed -E -i.bak ' +# Field(x, i) = y ==> Init_field_small(x, i, y) +#s/^([ \t]*)Field\(([^;]*),[ \t]*([^;]*)\)[ \t]*=[ \t]*([^;]*);[ \t]*$/\1Init_field_small\(\2, \3, \4\);/ + +# caml_initialize(&Field(x, i), y) ==> caml_initialize_field(x, i, y) +# caml_modify(&Field(x, i), y) ==> caml_modify_field(x, i, y) +#s/^([ \t]*)caml_(initialize|modify)[ \t]*\([ \t]*&[ \t]*Field\([ \t]*([^,]*),[ \t]*([^,()]*)[ \t]*\)[ \t]*,/\1caml_\2_field\(\3, \4,/ +#' "$@" diff --git a/tools/travis b/tools/travis new file mode 100755 index 0000000000..8ea3fa25ea --- /dev/null +++ b/tools/travis @@ -0,0 +1,60 @@ +#!/bin/sh + +show_builds () { +curl -sL \ + -H 'User-Agent: build log downloader' \ + 'https://api.travis-ci.org/v3/repo/ocamllabs%2Focaml-multicore/builds?include=build.jobs' | \ +jq -r '.builds | reverse | .[] | + (if .pull_request_title then + "PR #\(.pull_request_number)%[2m\(.commit.message | split("\n")[0])" + else + "\(.branch.name)%[2m\(.commit.message | split("\n")[0])" + end) as $desc | + (if .duration != null then "(\(.duration/60 | floor)m)" else "" end) as $time | + (if .state == "passed" then + "[32m" + elif .state == "started" then + "[33m" + else + "[31m" + end) as $colour | + "[1m\($colour)\(.number) \(.state)%[0m\($desc) [2m\($time)[0m"' | \ +column -t -s '%' +} + +dump_log () { +curl -sL \ + -H 'User-Agent: build log downloader' \ + 'https://api.travis-ci.org/v3/repo/ocamllabs%2Focaml-multicore/builds?include=build.jobs' | \ +jq -r --arg key "$1" \ + '[.builds[] | .jobs[] as $job | + select($job.state != "passed") | + if $key != "" then + select([.number, $job.number, .branch.name] | any(.==$key)) + else . end | + $job] | + first | + "\(.number) \(.id)"' | {\ + read number id + echo "Fetching logs for build $number ..." 1>&2 + curl -Ls "https://api.travis-ci.org/v3/job/$id/log.txt" + } | less -r +G +} + +case "$1" in +"") show_builds ;; +log) dump_log "$2" ;; +*) cat <<EOF; exit +Displays recent Travis builds and build logs + + $0: + prints a list of recent builds and their status + + $0 log: + shows the log of the most recent non-passing build + + $0 log KEY: + shows the log of the most recent non-passing build + whose branch name or build ID matches KEY +EOF +esac diff --git a/typing/cmt2annot.ml b/typing/cmt2annot.ml index 40ee752e80..1922606e69 100644 --- a/typing/cmt2annot.ml +++ b/typing/cmt2annot.ml @@ -95,10 +95,13 @@ let rec iterator ~scope rebuild_env = bind_bindings exp.exp_loc bindings | Texp_let (Nonrecursive, bindings, body) -> bind_bindings body.exp_loc bindings - | Texp_match (_, f1, _) -> - bind_cases f1 - | Texp_function { cases = f; } - | Texp_try (_, f) -> + | Texp_match (_, f1, f2, _) -> + bind_cases f1; + bind_cases f2 + | Texp_try (_, f1, f2) -> + bind_cases f1; + bind_cases f2 + | Texp_function { cases = f; } -> bind_cases f | Texp_letmodule (_, modname, _, _, body ) -> Stypes.record (Stypes.An_ident diff --git a/typing/ctype.mli b/typing/ctype.mli index 997207e393..0482a3478c 100644 --- a/typing/ctype.mli +++ b/typing/ctype.mli @@ -253,6 +253,8 @@ val extract_concrete_typedecl: val enforce_constraints: Env.t -> type_expr -> unit +val get_new_abstract_name : string -> string + val unify: Env.t -> type_expr -> type_expr -> unit (* Unify the two types given. Raise [Unify] if not possible. *) val unify_gadt: diff --git a/typing/env.ml b/typing/env.ml index fd46348db8..dc77b54138 100644 --- a/typing/env.ml +++ b/typing/env.ml @@ -1163,7 +1163,7 @@ let find_type_expansion path env = | Some body when decl.type_private = Public || decl.type_kind <> Type_abstract || Btype.has_constr_row body -> - (decl.type_params, body, decl.type_expansion_scope) + (decl.type_params, body, decl.type_expansion_scope) (* The manifest type of Private abstract data types without private row are still considered unknown to the type system. Hence, this case is caught by the following clause that also handles diff --git a/typing/oprint.ml b/typing/oprint.ml index b28641c46d..398b4f6e16 100644 --- a/typing/oprint.ml +++ b/typing/oprint.ml @@ -584,6 +584,10 @@ and print_out_sig_item ppf = | Osig_typext (ext, Oext_exception) -> fprintf ppf "@[<2>exception %a@]" print_out_constr (ext.oext_name, ext.oext_args, ext.oext_ret_type) + | Osig_typext ({ oext_ret_type = Some (Otyp_constr(_, [ret]))} as ext, + Oext_effect) -> + fprintf ppf "@[<2>effect %a@]" + print_out_constr (ext.oext_name, ext.oext_args, Some ret) | Osig_typext (ext, _es) -> print_out_extension_constructor ppf ext | Osig_modtype (name, Omty_abstract) -> diff --git a/typing/outcometree.mli b/typing/outcometree.mli index 2ab89f464d..f3f9006240 100644 --- a/typing/outcometree.mli +++ b/typing/outcometree.mli @@ -143,6 +143,7 @@ and out_ext_status = | Oext_first | Oext_next | Oext_exception + | Oext_effect type out_phrase = | Ophr_eval of out_value * out_type diff --git a/typing/predef.ml b/typing/predef.ml index 786d1dc21f..aa8f47c197 100644 --- a/typing/predef.ml +++ b/typing/predef.ml @@ -35,6 +35,8 @@ and ident_float = ident_create "float" and ident_bool = ident_create "bool" and ident_unit = ident_create "unit" and ident_exn = ident_create "exn" +and ident_eff = ident_create "eff" +and ident_continuation = ident_create "continuation" and ident_array = ident_create "array" and ident_list = ident_create "list" and ident_option = ident_create "option" @@ -53,6 +55,8 @@ and path_float = Pident ident_float and path_bool = Pident ident_bool and path_unit = Pident ident_unit and path_exn = Pident ident_exn +and path_eff = Pident ident_eff +and path_continuation = Pident ident_continuation and path_array = Pident ident_array and path_list = Pident ident_list and path_option = Pident ident_option @@ -71,6 +75,9 @@ and type_float = newgenty (Tconstr(path_float, [], ref Mnil)) and type_bool = newgenty (Tconstr(path_bool, [], ref Mnil)) and type_unit = newgenty (Tconstr(path_unit, [], ref Mnil)) and type_exn = newgenty (Tconstr(path_exn, [], ref Mnil)) +and type_eff t = newgenty (Tconstr(path_eff, [t], ref Mnil)) +and type_continuation t1 t2 = + newgenty (Tconstr(path_continuation, [t1; t2], ref Mnil)) and type_array t = newgenty (Tconstr(path_array, [t], ref Mnil)) and type_list t = newgenty (Tconstr(path_list, [t], ref Mnil)) and type_option t = newgenty (Tconstr(path_option, [t], ref Mnil)) @@ -96,6 +103,8 @@ and ident_sys_blocked_io = ident_create "Sys_blocked_io" and ident_assert_failure = ident_create "Assert_failure" and ident_undefined_recursive_module = ident_create "Undefined_recursive_module" +and ident_unhandled = ident_create "Unhandled" +and ident_continuation_already_taken = ident_create "Continuation_already_taken" let all_predef_exns = [ ident_match_failure; @@ -110,6 +119,8 @@ let all_predef_exns = [ ident_sys_blocked_io; ident_assert_failure; ident_undefined_recursive_module; + ident_unhandled; + ident_continuation_already_taken; ] let path_match_failure = Pident ident_match_failure @@ -178,6 +189,28 @@ let common_initial_env add_type add_extension empty_env = } in add_type type_ident decl env + and add_continuation type_ident env = + let tvar1 = newgenvar() in + let tvar2 = newgenvar() in + let arity = 2 in + let decl = + {type_params = [tvar1; tvar2]; + type_arity = arity; + type_kind = Type_abstract; + type_loc = Location.none; + type_private = Asttypes.Public; + type_manifest = None; + type_variance = [Variance.contravariant; Variance.covariant]; + type_separability = Types.Separability.default_signature ~arity; + type_is_newtype = false; + type_expansion_scope = lowest_level; + type_attributes = []; + type_immediate = Unknown; + type_unboxed = unboxed_false_default_false; + type_uid = Uid.of_predef_id type_ident; + } + in + add_type type_ident decl env in let add_extension id l = add_extension id @@ -208,6 +241,8 @@ let common_initial_env add_type add_extension empty_env = [newgenty (Ttuple[type_string; type_int; type_int])] ( add_extension ident_undefined_recursive_module [newgenty (Ttuple[type_string; type_int; type_int])] ( + add_extension ident_unhandled [] ( + add_extension ident_continuation_already_taken [] ( add_type ident_int64 ( add_type ident_int32 ( add_type ident_nativeint ( @@ -225,6 +260,8 @@ let common_initial_env add_type add_extension empty_env = ) ( add_type1 ident_array ~variance:Variance.full ~separability:Separability.Ind ( add_type ident_exn ~kind:Type_open ( + add_type1 ident_eff ~variance:Variance.full ~separability:Separability.Ind ~kind:(fun _ -> Type_open) ( + add_continuation ident_continuation ( add_type ident_unit ~immediate:Always ~kind:(Type_variant([cstr ident_void []])) ( add_type ident_bool ~immediate:Always @@ -235,7 +272,7 @@ let common_initial_env add_type add_extension empty_env = add_type ident_int ~immediate:Always ( add_type ident_extension_constructor ( add_type ident_floatarray ( - empty_env)))))))))))))))))))))))))))) + empty_env)))))))))))))))))))))))))))))))) let build_initial_env add_type add_exception empty_env = let common = common_initial_env add_type add_exception empty_env in diff --git a/typing/predef.mli b/typing/predef.mli index 962a276a92..15b09b3d75 100644 --- a/typing/predef.mli +++ b/typing/predef.mli @@ -25,6 +25,8 @@ val type_float: type_expr val type_bool: type_expr val type_unit: type_expr val type_exn: type_expr +val type_eff: type_expr -> type_expr +val type_continuation: type_expr -> type_expr -> type_expr val type_array: type_expr -> type_expr val type_list: type_expr -> type_expr val type_option: type_expr -> type_expr @@ -43,6 +45,8 @@ val path_float: Path.t val path_bool: Path.t val path_unit: Path.t val path_exn: Path.t +val path_eff: Path.t +val path_continuation: Path.t val path_array: Path.t val path_list: Path.t val path_option: Path.t diff --git a/typing/printtyp.ml b/typing/printtyp.ml index cfb5015de5..f52f0c18e7 100644 --- a/typing/printtyp.ml +++ b/typing/printtyp.ml @@ -1369,6 +1369,7 @@ let tree_of_extension_constructor id ext es = Text_first -> Oext_first | Text_next -> Oext_next | Text_exception -> Oext_exception + | Text_effect -> Oext_effect in Osig_typext (ext, es) diff --git a/typing/printtyped.ml b/typing/printtyped.ml index 15aa097284..d2076f61ed 100644 --- a/typing/printtyped.ml +++ b/typing/printtyped.ml @@ -330,14 +330,16 @@ and expression i ppf x = line i ppf "Texp_apply\n"; expression i ppf e; list i label_x_expression ppf l; - | Texp_match (e, l, _partial) -> + | Texp_match (e, l1, l2, _partial) -> line i ppf "Texp_match\n"; expression i ppf e; - list i case ppf l; - | Texp_try (e, l) -> + list i case ppf l1; + list i case ppf l2; + | Texp_try (e, l1, l2) -> line i ppf "Texp_try\n"; expression i ppf e; - list i case ppf l; + list i case ppf l1; + list i case ppf l2; | Texp_tuple (l) -> line i ppf "Texp_tuple\n"; list i expression ppf l; @@ -714,6 +716,9 @@ and signature_item i ppf x = | Tsig_typext e -> line i ppf "Tsig_typext\n"; type_extension i ppf e; + | Tsig_effect ext -> + line i ppf "Psig_effect\n"; + extension_constructor i ppf ext | Tsig_exception ext -> line i ppf "Tsig_exception\n"; type_exception i ppf ext @@ -826,6 +831,9 @@ and structure_item i ppf x = | Tstr_typext te -> line i ppf "Tstr_typext\n"; type_extension i ppf te + | Tstr_effect ext -> + line i ppf "Pstr_effect\n"; + extension_constructor i ppf ext; | Tstr_exception ext -> line i ppf "Tstr_exception\n"; type_exception i ppf ext; diff --git a/typing/rec_check.ml b/typing/rec_check.ml index 1248484cfc..826e7f331b 100644 --- a/typing/rec_check.ml +++ b/typing/rec_check.ml @@ -528,8 +528,8 @@ let rec expression : Typedtree.expression -> term_judg = value_bindings rec_flag bindings >> expression body | Texp_letmodule (x, _, _, mexp, e) -> module_binding (x, mexp) >> expression e - | Texp_match (e, cases, _) -> - (* + | Texp_match (e, cases, eff_cases, _) -> + (* TODO: update comment below for eff_cases (Gi; mi |- pi -> ei : m)^i G |- e : sum(mi)^i ---------------------------------------------- @@ -539,7 +539,10 @@ let rec expression : Typedtree.expression -> term_judg = let pat_envs, pat_modes = List.split (List.map (fun c -> case c mode) cases) in let env_e = expression e (List.fold_left Mode.join Ignore pat_modes) in - Env.join_list (env_e :: pat_envs)) + let eff_envs, eff_modes = + List.split (List.map (fun c -> case c mode) eff_cases) in + let eff_e = expression e (List.fold_left Mode.join Ignore eff_modes) in + Env.join_list ((Env.join_list (env_e :: pat_envs)) :: (eff_e :: eff_envs))) | Texp_for (_, _, low, high, _, body) -> (* G1 |- low: m[Dereference] @@ -744,7 +747,7 @@ let rec expression : Typedtree.expression -> term_judg = modexp mexp | Texp_object (clsstrct, _) -> class_structure clsstrct - | Texp_try (e, cases) -> + | Texp_try (e, cases, eff_cases) -> (* G |- e: m (Gi; _ |- pi -> ei : m)^i -------------------------------------------- @@ -758,6 +761,7 @@ let rec expression : Typedtree.expression -> term_judg = join [ expression e; list case_env cases; + list case_env eff_cases; ] | Texp_override (pth, fields) -> (* @@ -960,6 +964,10 @@ and structure_item : Typedtree.structure_item -> bind_judg = Env.join (list extension_constructor exts m) (Env.remove_list ext_ids env) + | Tstr_effect ext -> + Env.join + (extension_constructor ext m) + (Env.remove ext.ext_id env) | Tstr_exception {tyexn_constructor = ext; _} -> Env.join (extension_constructor ext m) diff --git a/typing/tast_iterator.ml b/typing/tast_iterator.ml index db63fc0b74..7693c67922 100644 --- a/typing/tast_iterator.ml +++ b/typing/tast_iterator.ml @@ -92,6 +92,7 @@ let structure_item sub {str_desc; str_env; _} = | Tstr_primitive v -> sub.value_description sub v | Tstr_type (rec_flag, list) -> sub.type_declarations sub (rec_flag, list) | Tstr_typext te -> sub.type_extension sub te + | Tstr_effect ext -> sub.extension_constructor sub ext | Tstr_exception ext -> sub.type_exception sub ext | Tstr_module mb -> sub.module_binding sub mb | Tstr_recmodule list -> List.iter (sub.module_binding sub) list @@ -198,12 +199,14 @@ let expr sub {exp_extra; exp_desc; exp_env; _} = | Texp_apply (exp, list) -> sub.expr sub exp; List.iter (fun (_, o) -> Option.iter (sub.expr sub) o) list - | Texp_match (exp, cases, _) -> + | Texp_match (exp, cases, effs, _) -> sub.expr sub exp; - List.iter (sub.case sub) cases - | Texp_try (exp, cases) -> + List.iter (sub.case sub) cases; + List.iter (sub.case sub) effs + | Texp_try (exp, cases, effs) -> sub.expr sub exp; - List.iter (sub.case sub) cases + List.iter (sub.case sub) cases; + List.iter (sub.case sub) effs | Texp_tuple list -> List.iter (sub.expr sub) list | Texp_construct (_, _, args) -> List.iter (sub.expr sub) args | Texp_variant (_, expo) -> Option.iter (sub.expr sub) expo @@ -277,6 +280,7 @@ let signature_item sub {sig_desc; sig_env; _} = | Tsig_type (rf, tdl) -> sub.type_declarations sub (rf, tdl) | Tsig_typesubst list -> sub.type_declarations sub (Nonrecursive, list) | Tsig_typext te -> sub.type_extension sub te + | Tsig_effect ext -> sub.extension_constructor sub ext | Tsig_exception ext -> sub.type_exception sub ext | Tsig_module x -> sub.module_declaration sub x | Tsig_modsubst x -> sub.module_substitution sub x diff --git a/typing/tast_mapper.ml b/typing/tast_mapper.ml index d8ceee1d96..0e9ad3332e 100644 --- a/typing/tast_mapper.ml +++ b/typing/tast_mapper.ml @@ -117,6 +117,7 @@ let structure_item sub {str_desc; str_loc; str_env} = let (rec_flag, list) = sub.type_declarations sub (rec_flag, list) in Tstr_type (rec_flag, list) | Tstr_typext te -> Tstr_typext (sub.type_extension sub te) + | Tstr_effect ext -> Tstr_effect (sub.extension_constructor sub ext) | Tstr_exception ext -> Tstr_exception (sub.type_exception sub ext) | Tstr_module mb -> Tstr_module (sub.module_binding sub mb) | Tstr_recmodule list -> @@ -255,16 +256,18 @@ let expr sub x = sub.expr sub exp, List.map (tuple2 id (Option.map (sub.expr sub))) list ) - | Texp_match (exp, cases, p) -> + | Texp_match (exp, cases, eff_cases, p) -> Texp_match ( sub.expr sub exp, List.map (sub.case sub) cases, + List.map (sub.case sub) eff_cases, p ) - | Texp_try (exp, cases) -> + | Texp_try (exp, exn_cases, eff_cases) -> Texp_try ( sub.expr sub exp, - List.map (sub.case sub) cases + List.map (sub.case sub) exn_cases, + List.map (sub.case sub) eff_cases ) | Texp_tuple list -> Texp_tuple (List.map (sub.expr sub) list) @@ -274,7 +277,7 @@ let expr sub x = Texp_variant (l, Option.map (sub.expr sub) expo) | Texp_record { fields; representation; extended_expression } -> let fields = Array.map (function - | label, Kept t -> label, Kept t + | label, Kept (t, mut) -> label, Kept (t, mut) | label, Overridden (lid, exp) -> label, Overridden (lid, sub.expr sub exp)) fields @@ -405,6 +408,8 @@ let signature_item sub x = Tsig_typesubst list | Tsig_typext te -> Tsig_typext (sub.type_extension sub te) + | Tsig_effect ext -> + Tsig_effect (sub.extension_constructor sub ext) | Tsig_exception ext -> Tsig_exception (sub.type_exception sub ext) | Tsig_module x -> @@ -684,11 +689,12 @@ let value_bindings sub (rec_flag, list) = let case : type k . mapper -> k case -> k case - = fun sub {c_lhs; c_guard; c_rhs} -> + = fun sub {c_lhs; c_guard; c_rhs; c_cont} -> { c_lhs = sub.pat sub c_lhs; c_guard = Option.map (sub.expr sub) c_guard; c_rhs = sub.expr sub c_rhs; + c_cont } let value_binding sub x = diff --git a/typing/typeclass.ml b/typing/typeclass.ml index 5ede1151e0..09f5119fb0 100644 --- a/typing/typeclass.ml +++ b/typing/typeclass.ml @@ -1056,7 +1056,7 @@ and class_expr_aux cl_num val_env met_env scl = let partial = let dummy = type_exp val_env (Ast_helper.Exp.unreachable ()) in Typecore.check_partial val_env pat.pat_type pat.pat_loc - [{c_lhs = pat; c_guard = None; c_rhs = dummy}] + [{c_lhs = pat; c_cont = None; c_guard = None; c_rhs = dummy}] in Ctype.raise_nongen_level (); let cl = class_expr cl_num val_env' met_env scl' in diff --git a/typing/typecore.ml b/typing/typecore.ml index a49f53d5db..93291d06c6 100644 --- a/typing/typecore.ml +++ b/typing/typecore.ml @@ -116,6 +116,8 @@ type error = | No_value_clauses | Exception_pattern_disallowed | Mixed_value_and_exception_patterns_under_guard + | Effect_pattern_below_toplevel + | Invalid_continuation_pattern | Inlined_record_escape | Inlined_record_expected | Unrefuted_pattern of pattern @@ -193,7 +195,8 @@ type recarg = let mk_expected ?explanation ty = { ty; explanation; } let case lhs rhs = - {c_lhs = lhs; c_guard = None; c_rhs = rhs} + {c_lhs = lhs; c_cont = None; c_guard = None; c_rhs = rhs} + (* Typing of constants *) @@ -1041,6 +1044,23 @@ let unify_head_only ~refine loc env ty constr = (* Typing of patterns *) +(* Simplified patterns for effect continuations *) +let type_continuation_pat env expected_ty sp = + let loc = sp.ppat_loc in + match sp.ppat_desc with + | Ppat_any -> None + | Ppat_var name -> + let id = Ident.create_local name.txt in + let desc = + { val_type = expected_ty; val_kind = Val_reg; + Types.val_loc = loc; val_attributes = []; + val_uid = Uid.mk ~current_unit:(Env.get_unit_name ()); } + in + Some (id, desc) + | Ppat_extension ext -> + raise (Error_forward (Builtin_attributes.error_of_extension ext)) + | _ -> raise (Error (loc, env, Invalid_continuation_pattern)) + (* "half typed" cases are produced in [type_cases] when we've just typechecked the pattern but haven't type-checked the body yet. At this point we might have added some type equalities to the environment, @@ -1079,6 +1099,7 @@ let rec has_literal_pattern p = match p.ppat_desc with List.exists has_literal_pattern ps | Ppat_record (ps, _) -> List.exists (fun (_,p) -> has_literal_pattern p) ps + | Ppat_effect (p, q) | Ppat_or (p, q) -> has_literal_pattern p || has_literal_pattern q @@ -1866,14 +1887,16 @@ and type_pat_aux ) | Ppat_exception p -> type_pat Value p Predef.type_exn (fun p_exn -> - rcp k { - pat_desc = Tpat_exception p_exn; - pat_loc = sp.ppat_loc; - pat_extra = []; - pat_type = expected_ty; - pat_env = !env; - pat_attributes = sp.ppat_attributes; - }) + rcp k { + pat_desc = Tpat_exception p_exn; + pat_loc = sp.ppat_loc; + pat_extra = []; + pat_type = expected_ty; + pat_env = !env; + pat_attributes = sp.ppat_attributes; + }) + | Ppat_effect _ -> + raise (Error (loc, !env, Effect_pattern_below_toplevel)) | Ppat_extension ext -> raise (Error_forward (Builtin_attributes.error_of_extension ext)) @@ -2072,9 +2095,9 @@ let rec final_subexpression exp = match exp.exp_desc with Texp_let (_, _, e) | Texp_sequence (_, e) - | Texp_try (e, _) + | Texp_try (e, _, _) | Texp_ifthenelse (_, e, _) - | Texp_match (_, {c_rhs=e} :: _, _) + | Texp_match (_, {c_rhs=e} :: _, _, _) | Texp_letmodule (_, _, _, _, e) | Texp_letexception (_, e) | Texp_open (_, e) @@ -2095,7 +2118,7 @@ let rec is_nonexpansive exp = is_nonexpansive body | Texp_apply(e, (_,None)::el) -> is_nonexpansive e && List.for_all is_nonexpansive_opt (List.map snd el) - | Texp_match(e, cases, _) -> + | Texp_match(e, cases, _, _) -> (* Not sure this is necessary, if [e] is nonexpansive then we shouldn't care if there are exception patterns. But the previous version enforced that there be none, so... *) @@ -2204,6 +2227,10 @@ and is_nonexpansive_mod mexp = false (* true would be unsound *) | Tstr_exception {tyexn_constructor = {ext_kind = Text_rebind _}} -> true + | Tstr_effect {ext_kind = Text_decl _} -> + false (* true would be unsound *) + | Tstr_effect {ext_kind = Text_rebind _} -> + true | Tstr_typext te -> List.for_all (function {ext_kind = Text_decl _} -> false @@ -2388,10 +2415,13 @@ let check_partial_application statement exp = | Texp_extension_constructor _ | Texp_ifthenelse (_, _, None) | Texp_function _ -> check_statement () - | Texp_match (_, cases, _) -> - List.iter (fun {c_rhs; _} -> check c_rhs) cases - | Texp_try (e, cases) -> - check e; List.iter (fun {c_rhs; _} -> check c_rhs) cases + | Texp_match (_, cases, eff_cases, _) -> + List.iter (fun {c_rhs; _} -> check c_rhs) cases; + List.iter (fun {c_rhs; _} -> check c_rhs) eff_cases + | Texp_try (e, cases, eff_cases) -> + check e; + List.iter (fun {c_rhs; _} -> check c_rhs) cases; + List.iter (fun {c_rhs; _} -> check c_rhs) eff_cases | Texp_ifthenelse (_, e1, Some e2) -> check e1; check e2 | Texp_let (_, _, e) | Texp_sequence (_, e) | Texp_open (_, e) @@ -2464,7 +2494,7 @@ let shallow_iter_ppat f p = | Ppat_extension _ | Ppat_type _ | Ppat_unpack _ -> () | Ppat_array pats -> List.iter f pats - | Ppat_or (p1,p2) -> f p1; f p2 + | Ppat_or (p1,p2) | Ppat_effect(p1, p2) -> f p1; f p2 | Ppat_variant (_, arg) | Ppat_construct (_, arg) -> Option.iter f arg | Ppat_tuple lst -> List.iter f lst | Ppat_exception p | Ppat_alias (p,_) @@ -2792,20 +2822,54 @@ and type_expect_ end_def (); if maybe_expansive arg then lower_contravariant env arg.exp_type; generalize arg.exp_type; - let cases, partial = - type_cases Computation env arg.exp_type ty_expected true loc caselist in + let rec split_cases valc effc conts = function + | [] -> List.rev valc, List.rev effc, List.rev conts + | {pc_lhs = {ppat_desc=Ppat_effect(p1, p2)}} as c :: rest -> + split_cases valc + (({c with pc_lhs = p1}) :: effc) (p2 :: conts) rest + | c :: rest -> + split_cases (c :: valc) effc conts rest + in + let val_caselist, eff_caselist, eff_conts = + split_cases [] [] [] caselist + in + if val_caselist = [] && eff_caselist <> [] then + raise (Error (loc, env, No_value_clauses)); + let val_cases, partial = + type_cases Computation env arg.exp_type ty_expected true loc val_caselist in + let eff_cases = + match eff_caselist with + | [] -> [] + | eff_caselist -> + type_effect_cases Value env ty_expected loc eff_caselist eff_conts + in re { - exp_desc = Texp_match(arg, cases, partial); + exp_desc = Texp_match(arg, val_cases, eff_cases, partial); exp_loc = loc; exp_extra = []; exp_type = instance ty_expected; exp_attributes = sexp.pexp_attributes; exp_env = env } | Pexp_try(sbody, caselist) -> let body = type_expect env sbody ty_expected_explained in - let cases, _ = - type_cases Value env Predef.type_exn ty_expected false loc caselist in + let rec split_cases exnc effc conts = function + | [] -> List.rev exnc, List.rev effc, List.rev conts + | {pc_lhs = {ppat_desc=Ppat_effect(p1, p2)}} as c :: rest -> + split_cases exnc + (({c with pc_lhs = p1}) :: effc) (p2 :: conts) rest + | c :: rest -> + split_cases (c :: exnc) effc conts rest + in + let exn_caselist, eff_caselist, eff_conts = split_cases [] [] [] caselist in + let exn_cases, _ = + type_cases Value env Predef.type_exn ty_expected false loc exn_caselist in + let eff_cases = + match eff_caselist with + | [] -> [] + | eff_caselist -> + type_effect_cases Value env ty_expected loc eff_caselist eff_conts + in re { - exp_desc = Texp_try(body, cases); + exp_desc = Texp_try(body, exn_cases, eff_cases); exp_loc = loc; exp_extra = []; exp_type = body.exp_type; exp_attributes = sexp.pexp_attributes; @@ -2976,7 +3040,7 @@ and type_expect_ unify_exp_types loc env ty_arg1 ty_arg2; with_explanation (fun () -> unify_exp_types loc env (instance ty_expected) ty_res2); - Kept ty_arg1 + Kept (ty_arg1, lbl.lbl_mut) end in let label_definitions = Array.map unify_kept lbl.lbl_all in @@ -4588,9 +4652,9 @@ and type_unpacks ?in_function env unpacks sbody expected_ty = (* Typing of match cases *) and type_cases : type k . k pattern_category -> - ?in_function:_ -> _ -> _ -> _ -> _ -> _ -> Parsetree.case list -> + ?in_function:_ -> _ -> _ -> _ -> ?conts:_ -> _ -> _ -> Parsetree.case list -> k case list * partial - = fun category ?in_function env ty_arg ty_res partial_flag loc caselist -> + = fun category ?in_function env ty_arg ty_res ?conts partial_flag loc caselist -> (* ty_arg is _fully_ generalized *) let patterns = List.map (fun {pc_lhs=p} -> p) caselist in let contains_polyvars = List.exists contains_polymorphic_variant patterns in @@ -4698,11 +4762,17 @@ and type_cases ) half_typed_cases; (* type bodies *) let in_function = if List.length caselist = 1 then in_function else None in + let half_typed_cases_cont_list = + match conts with + | None -> List.map (fun x -> (x, None)) half_typed_cases + | Some conts -> + List.map2 (fun x cont -> (x, cont)) half_typed_cases conts + in let cases = List.map - (fun { typed_pat = pat; branch_env = ext_env; pat_vars = pvs; unpacks; + (fun ({ typed_pat = pat; branch_env = ext_env; pat_vars = pvs; unpacks; untyped_case = {pc_lhs = _; pc_guard; pc_rhs}; - contains_gadt; _ } -> + contains_gadt; _ }, cont) -> let ext_env = if contains_gadt then do_copy_types ext_env @@ -4714,6 +4784,16 @@ and type_cases ~check:(fun s -> Warnings.Unused_var_strict s) ~check_as:(fun s -> Warnings.Unused_var s) in + let cont, ext_env' = + match cont with + | Some (id, desc) -> + let ext_env = + Env.add_value ~check:(fun s -> Warnings.Unused_var_strict s) + id desc ext_env + in + Some id, ext_env + | None -> None, ext_env + in let unpacks = List.map (fun (name, loc) -> name, loc, Uid.mk ~current_unit:(Env.get_unit_name ()) @@ -4739,20 +4819,27 @@ and type_cases match pc_guard with | None -> None | Some scond -> + (* It is crucial that the continuation is not used in the + `when' expression as the extent of the continuation is + yet to be determined. We make the continuation + inaccessible by typing the `when' expression using the + environment `ext_env' which does not bind the + continuation variable. *) Some (type_unpacks ext_env unpacks scond (mk_expected ~explanation:When_guard Predef.type_bool)) in let exp = - type_unpacks ?in_function ext_env unpacks pc_rhs (mk_expected ty_res') + type_unpacks ?in_function ext_env' unpacks pc_rhs (mk_expected ty_res') in { c_lhs = pat; + c_cont = cont; c_guard = guard; c_rhs = {exp with exp_type = instance ty_res'} } ) - half_typed_cases + half_typed_cases_cont_list in if !Clflags.principal || does_contain_gadt then begin let ty_res' = instance ty_res in @@ -4800,6 +4887,45 @@ and type_cases end; cases, partial +and type_effect_cases + : type k . k pattern_category -> + _ -> _ -> _ -> Parsetree.case list -> _ + -> + k case list + = fun category env ty_res loc caselist conts -> + let _ = newvar () in + (* remember original level *) + begin_def (); + (* Create a fake abstract type declaration for effect type. *) + let decl = { + type_params = []; + type_arity = 0; + type_kind = Type_abstract; + type_private = Public; + type_manifest = None; + type_variance = []; + type_separability = []; + type_is_newtype = true; + type_expansion_scope = Btype.lowest_level; + type_loc = loc; + type_attributes = []; + type_immediate = Unknown; + type_unboxed = unboxed_false_default_false; + type_uid = Uid.mk ~current_unit:(Env.get_unit_name ()); + } + in + let name = Ctype.get_new_abstract_name "effect" in + let scope = create_scope () in + let id = Ident.create_scoped ~scope name in + let new_env = Env.add_type ~check:false id decl env in + let ty_eff = newgenty (Tconstr (Path.Pident id,[],ref Mnil)) in + let ty_arg = Predef.type_eff ty_eff in + let ty_cont = Predef.type_continuation ty_eff ty_res in + let conts = List.map (type_continuation_pat env ty_cont) conts in + let cases, _ = type_cases category new_env ty_arg ty_res ~conts false loc caselist in + end_def (); + cases + (* Typing of let bindings *) and type_let @@ -5534,6 +5660,12 @@ let report_error ~loc env = function Location.errorf ~loc "@[Mixing value and exception patterns under when-guards is not \ supported.@]" + | Effect_pattern_below_toplevel -> + Location.errorf ~loc + "@[Effect patterns must be at the top level of a match case.@]" + | Invalid_continuation_pattern -> + Location.errorf ~loc + "@[Invalid continuation pattern: only variables and _ are allowed .@]" | Inlined_record_escape -> Location.errorf ~loc "@[This form is not allowed as the type of the inlined record could \ diff --git a/typing/typecore.mli b/typing/typecore.mli index 2c8d177eb8..e42fff19e1 100644 --- a/typing/typecore.mli +++ b/typing/typecore.mli @@ -175,6 +175,8 @@ type error = | No_value_clauses | Exception_pattern_disallowed | Mixed_value_and_exception_patterns_under_guard + | Effect_pattern_below_toplevel + | Invalid_continuation_pattern | Inlined_record_escape | Inlined_record_expected | Unrefuted_pattern of Typedtree.pattern diff --git a/typing/typedecl.ml b/typing/typedecl.ml index 52fdca5131..7861891bdb 100644 --- a/typing/typedecl.ml +++ b/typing/typedecl.ml @@ -274,6 +274,25 @@ let make_constructor env type_path type_params sargs sret_type = widen z; targs, Some tret_type, args, Some ret_type +let make_effect_constructor env type_param sargs sret = + let type_path = Predef.path_eff in + let type_lid = Location.mknoloc (Longident.Lident "eff") in + let z = narrow () in + reset_type_variables (); + let targs = List.map (transl_simple_type env false) sargs in + let args = List.map (fun cty -> cty.ctyp_type) targs in + let tret = transl_simple_type env false sret in + Ctype.unify_var env (Ctype.instance type_param) tret.ctyp_type; + let ret_type = Ctype.newconstr type_path [tret.ctyp_type] in + let tret_type = + { ctyp_desc = Ttyp_constr (type_path, type_lid, targs); + ctyp_type = ret_type; ctyp_env = env; + ctyp_loc = {sret.ptyp_loc with Location.loc_ghost = true}; + ctyp_attributes = [] } + in + widen z; + targs, Some tret_type, args, Some ret_type + let transl_declaration env sdecl (id, uid) = (* Bind type parameters *) reset_type_variables(); @@ -944,6 +963,70 @@ let transl_type_decl env rec_flag sdecl_list = (final_decls, final_env) (* Translating type extensions *) +let transl_extension_rebind env type_path type_params typext_params priv lid = + let usage = if priv = Public then Env.Positive else Env.Privatize in + let cdescr = Env.lookup_constructor ~loc:lid.loc usage lid.txt env in + let (args, cstr_res) = Ctype.instance_constructor cdescr in + let res, ret_type = + if cdescr.cstr_generalized then + let params = Ctype.instance_list type_params in + let res = Ctype.newconstr type_path params in + let ret_type = Some (Ctype.newconstr type_path params) in + res, ret_type + else (Ctype.newconstr type_path typext_params), None + in + begin + try + Ctype.unify env cstr_res res + with Ctype.Unify trace -> + raise (Error(lid.loc, + Rebind_wrong_type(lid.txt, env, trace))) + end; + (* Remove "_" names from parameters used in the constructor *) + if not cdescr.cstr_generalized then begin + let vars = + Ctype.free_variables (Btype.newgenty (Ttuple args)) + in + List.iter + (function {desc = Tvar (Some "_")} as ty -> + if List.memq ty vars then ty.desc <- Tvar None + | _ -> ()) + typext_params + end; + (* Ensure that constructor's type matches the type being extended *) + let cstr_type_path, cstr_type_params = + match cdescr.cstr_res.desc with + Tconstr (p, _, _) -> + let decl = Env.find_type p env in + p, decl.type_params + | _ -> assert false + in + let cstr_types = + (Btype.newgenty + (Tconstr(cstr_type_path, cstr_type_params, ref Mnil))) + :: cstr_type_params + in + let ext_types = + (Btype.newgenty + (Tconstr(type_path, type_params, ref Mnil))) + :: type_params + in + if not (Ctype.equal env true cstr_types ext_types) then + raise (Error(lid.loc, + Rebind_mismatch(lid.txt, cstr_type_path, type_path))); + (* Disallow rebinding private constructors to non-private *) + begin + match cdescr.cstr_private, priv with + Private, Public -> + raise (Error(lid.loc, Rebind_private lid.txt)) + | _ -> () + end; + let path = + match cdescr.cstr_tag with + Cstr_extension(path, _) -> path + | _ -> assert false + in + args, ret_type, Text_rebind(path, lid) let transl_extension_constructor env type_path type_params typext_params priv sext = @@ -1179,6 +1262,7 @@ let transl_type_extension extend env loc styext = Builtin_attributes.warning_scope styext.ptyext_attributes (fun () -> transl_type_extension extend env loc styext) +(* Translate an exception declaration *) let transl_exception env sext = reset_type_variables(); Ctype.begin_def(); @@ -1215,6 +1299,63 @@ let transl_type_exception env t = tyexn_attributes = t.ptyexn_attributes}, newenv +(* Translate an effect declaration *) +let transl_effect env seff = + reset_type_variables(); + Ctype.begin_def(); + let type_decl = Env.find_type Predef.path_eff env in + let type_param = + match type_decl.type_params with + | [type_param] -> type_param + | _ -> assert false + in + let typext_param = Ctype.new_global_var () in + let id = Ident.create_local seff.peff_name.txt in + let args, ret_type, kind = + match seff.peff_kind with + | Peff_decl(sargs, sret) -> + let targs, tret_type, args, ret_type = + make_effect_constructor env type_param sargs sret + in + args, ret_type, Text_decl(Cstr_tuple targs, tret_type) + | Peff_rebind lid -> + transl_extension_rebind env Predef.path_eff + type_decl.type_params [typext_param] Asttypes.Public lid + in + let ext = + { ext_type_path = Predef.path_eff; + ext_type_params = [typext_param]; + ext_args = Cstr_tuple args; + ext_ret_type = ret_type; + ext_private = Asttypes.Public; + Types.ext_loc = seff.peff_loc; + Types.ext_attributes = seff.peff_attributes; + ext_uid = Uid.mk ~current_unit:(Env.get_unit_name ()); } + in + let text = + { ext_id = id; + ext_name = seff.peff_name; + ext_type = ext; + ext_kind = kind; + Typedtree.ext_loc = seff.peff_loc; + Typedtree.ext_attributes = seff.peff_attributes; } + in + Ctype.end_def(); + (* Generalize types *) + Btype.iter_type_expr_cstr_args Ctype.generalize ext.ext_args; + Option.iter Ctype.generalize ext.ext_ret_type; + (* Check that all type variable are closed *) + begin match Ctype.closed_extension_constructor ext with + Some ty -> + raise (Error(ext.ext_loc, Unbound_type_var_ext(ty, ext))) + | None -> () + end; + let rebind = is_rebind text in + let newenv = + Env.add_extension ~check:true ~rebind text.ext_id text.ext_type env + in + text, newenv + type native_repr_attribute = | Native_repr_attr_absent | Native_repr_attr_present of native_repr_kind diff --git a/typing/typedecl.mli b/typing/typedecl.mli index 88f5b2f14d..ae11406cf5 100644 --- a/typing/typedecl.mli +++ b/typing/typedecl.mli @@ -30,6 +30,10 @@ val transl_type_exception: Env.t -> Parsetree.type_exception -> Typedtree.type_exception * Env.t +val transl_effect: + Env.t -> + Parsetree.effect_constructor -> Typedtree.extension_constructor * Env.t + val transl_type_extension: bool -> Env.t -> Location.t -> Parsetree.type_extension -> Typedtree.type_extension * Env.t diff --git a/typing/typedtree.ml b/typing/typedtree.ml index 72eb1df3b3..8ec3ca25d3 100644 --- a/typing/typedtree.ml +++ b/typing/typedtree.ml @@ -102,8 +102,8 @@ and expression_desc = | Texp_function of { arg_label : arg_label; param : Ident.t; cases : value case list; partial : partial; } | Texp_apply of expression * (arg_label * expression option) list - | Texp_match of expression * computation case list * partial - | Texp_try of expression * value case list + | Texp_match of expression * computation case list * value case list * partial + | Texp_try of expression * value case list * value case list | Texp_tuple of expression list | Texp_construct of Longident.t loc * constructor_description * expression list @@ -154,12 +154,13 @@ and meth = and 'k case = { c_lhs: 'k general_pattern; + c_cont: Ident.t option; c_guard: expression option; c_rhs: expression; } and record_label_definition = - | Kept of Types.type_expr + | Kept of Types.type_expr * mutable_flag | Overridden of Longident.t loc * expression and binding_op = @@ -272,6 +273,7 @@ and structure_item_desc = | Tstr_primitive of value_description | Tstr_type of rec_flag * type_declaration list | Tstr_typext of type_extension + | Tstr_effect of extension_constructor | Tstr_exception of type_exception | Tstr_module of module_binding | Tstr_recmodule of module_binding list @@ -349,6 +351,7 @@ and signature_item_desc = | Tsig_type of rec_flag * type_declaration list | Tsig_typesubst of type_declaration list | Tsig_typext of type_extension + | Tsig_effect of extension_constructor | Tsig_exception of type_exception | Tsig_module of module_declaration | Tsig_modsubst of module_substitution diff --git a/typing/typedtree.mli b/typing/typedtree.mli index 87b29ad1b5..7fb95c3d4a 100644 --- a/typing/typedtree.mli +++ b/typing/typedtree.mli @@ -205,17 +205,23 @@ and expression_desc = (Labelled "y", Some (Texp_constant Const_int 3)) ]) *) - | Texp_match of expression * computation case list * partial + | Texp_match of expression * computation case list * value case list * partial (** match E0 with | P1 -> E1 | P2 | exception P3 -> E2 | exception P4 -> E3 + | effect P4 k -> E4 [Texp_match (E0, [(P1, E1); (P2 | exception P3, E2); - (exception P4, E3)], _)] + (exception P4, E3)], [(P4, E4)], _)] *) - | Texp_try of expression * value case list - (** try E with P1 -> E1 | ... | PN -> EN *) + | Texp_try of expression * value case list * value case list + (** try E with + | P1 -> E1 + | effect P2 k -> E2 + + [Texp_try (E, [(P1, E1)], [(P2, E2)])] + *) | Texp_tuple of expression list (** (E1, ..., EN) *) | Texp_construct of @@ -283,12 +289,13 @@ and meth = and 'k case = { c_lhs: 'k general_pattern; + c_cont: Ident.t option; c_guard: expression option; c_rhs: expression; } and record_label_definition = - | Kept of Types.type_expr + | Kept of Types.type_expr * mutable_flag | Overridden of Longident.t loc * expression and binding_op = @@ -409,6 +416,7 @@ and structure_item_desc = | Tstr_primitive of value_description | Tstr_type of rec_flag * type_declaration list | Tstr_typext of type_extension + | Tstr_effect of extension_constructor | Tstr_exception of type_exception | Tstr_module of module_binding | Tstr_recmodule of module_binding list @@ -485,6 +493,7 @@ and signature_item_desc = | Tsig_type of rec_flag * type_declaration list | Tsig_typesubst of type_declaration list | Tsig_typext of type_extension + | Tsig_effect of extension_constructor | Tsig_exception of type_exception | Tsig_module of module_declaration | Tsig_modsubst of module_substitution diff --git a/typing/typemod.ml b/typing/typemod.ml index 360867e253..c634729567 100644 --- a/typing/typemod.ml +++ b/typing/typemod.ml @@ -1285,6 +1285,16 @@ and transl_signature env sg = Text_exception, Exported) :: rem, final_env + | Psig_effect seff -> + let (ext, newenv) = Typedecl.transl_effect env seff in + let (trem, rem, final_env) = transl_sig newenv srem in + (* XXX KC: Should we care about Shadowed? *) + mksig (Tsig_effect ext) env loc :: trem, + Sig_typext(ext.ext_id, + ext.ext_type, + Text_effect, + Exported) :: rem, + final_env | Psig_module pmd -> let scope = Ctype.create_scope () in let tmty = @@ -2213,6 +2223,11 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope = Text_exception, Exported)], newenv + | Pstr_effect seff -> + let (ext, newenv) = Typedecl.transl_effect env seff in + Tstr_effect ext, + [Sig_typext(ext.ext_id, ext.ext_type, Text_effect, Exported)], + newenv | Pstr_module {pmb_name = name; pmb_expr = smodl; pmb_attributes = attrs; pmb_loc; } -> diff --git a/typing/types.ml b/typing/types.ml index 9d0817c09d..7dc4a850c5 100644 --- a/typing/types.ml +++ b/typing/types.ml @@ -182,6 +182,7 @@ module Variance = struct let unknown = 7 let full = 127 let covariant = single May_pos lor single Pos lor single Inj + let contravariant = single May_neg lor single Neg lor single Inj let swap f1 f2 v = let v' = set f1 (mem f2 v) v in set f2 (mem f1 v) v' let conjugate v = swap May_pos May_neg (swap Pos Neg v) @@ -394,7 +395,7 @@ and ext_status = Text_first (* first constructor of an extension *) | Text_next (* not first constructor of an extension *) | Text_exception (* an exception *) - + | Text_effect (* an effect *) (* Constructor and record label descriptions inserted held in typing environments *) diff --git a/typing/types.mli b/typing/types.mli index d36f26c2d2..25d54ba7a7 100644 --- a/typing/types.mli +++ b/typing/types.mli @@ -298,6 +298,7 @@ module Variance : sig val null : t (* no occurrence *) val full : t (* strictly invariant (all flags) *) val covariant : t (* strictly covariant (May_pos, Pos and Inj) *) + val contravariant : t (* strictly contravariant *) val unknown : t (* allow everything, guarantee nothing *) val union : t -> t -> t val inter : t -> t -> t @@ -526,7 +527,7 @@ and ext_status = Text_first (* first constructor in an extension *) | Text_next (* not first constructor in an extension *) | Text_exception - + | Text_effect (* Constructor and record label descriptions inserted held in typing environments *) diff --git a/typing/untypeast.ml b/typing/untypeast.ml index 7106da5b91..a11cbe2c0e 100644 --- a/typing/untypeast.ml +++ b/typing/untypeast.ml @@ -40,6 +40,8 @@ type mapper = { expr: mapper -> T.expression -> expression; extension_constructor: mapper -> T.extension_constructor -> extension_constructor; + effect_constructor: mapper -> T.extension_constructor + -> effect_constructor; include_declaration: mapper -> T.include_declaration -> include_declaration; include_description: mapper -> T.include_description -> include_description; label_declaration: mapper -> T.label_declaration -> label_declaration; @@ -177,6 +179,8 @@ let structure_item sub item = Pstr_type (rec_flag, List.map (sub.type_declaration sub) list) | Tstr_typext tyext -> Pstr_typext (sub.type_extension sub tyext) + | Tstr_effect ext -> + Pstr_effect (sub.effect_constructor sub ext) | Tstr_exception ext -> Pstr_exception (sub.type_exception sub ext) | Tstr_module mb -> @@ -289,6 +293,18 @@ let extension_constructor sub ext = | Text_rebind (_p, lid) -> Pext_rebind (map_loc sub lid) ) +let effect_constructor sub ext = + let loc = sub.location sub ext.ext_loc; in + let attrs = sub.attributes sub ext.ext_attributes in + Te.effect_constructor ~loc ~attrs + (map_loc sub ext.ext_name) + (match ext.ext_kind with + | Text_decl (Cstr_tuple l, Some ret) -> + Peff_decl (List.map (sub.typ sub) l, (sub.typ sub) ret) + | Text_rebind (_p, lid) -> Peff_rebind (map_loc sub lid) + | _ -> failwith "Untypast.effect_constructor" + ) + let pattern : type k . _ -> k T.general_pattern -> _ = fun sub pat -> let loc = sub.location sub pat.pat_loc in (* todo: fix attributes on extras *) @@ -418,10 +434,32 @@ let expression sub exp = None -> list | Some exp -> (label, sub.expr sub exp) :: list ) list []) - | Texp_match (exp, cases, _) -> - Pexp_match (sub.expr sub exp, List.map (sub.case sub) cases) - | Texp_try (exp, cases) -> - Pexp_try (sub.expr sub exp, List.map (sub.case sub) cases) + | Texp_match (exp, cases, eff_cases, _) -> + let merged_cases = List.map (sub.case sub) cases + @ List.map + (fun c -> + let uc = sub.case sub c in + let pat = { uc.pc_lhs + (* XXX KC: The 2nd argument of Ppat_effect is wrong *) + with ppat_desc = Ppat_effect (uc.pc_lhs, uc.pc_lhs) } + in + { uc with pc_lhs = pat }) + eff_cases + in + Pexp_match (sub.expr sub exp, merged_cases) + | Texp_try (exp, exn_cases, eff_cases) -> + let merged_cases = List.map (sub.case sub) exn_cases + @ List.map + (fun c -> + let uc = sub.case sub c in + let pat = { uc.pc_lhs + (* XXX KC: The 2nd argument of Ppat_effect is wrong *) + with ppat_desc = Ppat_effect (uc.pc_lhs, uc.pc_lhs) } + in + { uc with pc_lhs = pat }) + eff_cases + in + Pexp_try (sub.expr sub exp, merged_cases) | Texp_tuple list -> Pexp_tuple (List.map (sub.expr sub) list) | Texp_construct (lid, _, args) -> @@ -541,6 +579,8 @@ let signature_item sub item = Psig_typesubst (List.map (sub.type_declaration sub) list) | Tsig_typext tyext -> Psig_typext (sub.type_extension sub tyext) + | Tsig_effect ext -> + Psig_effect (sub.effect_constructor sub ext) | Tsig_exception ext -> Psig_exception (sub.type_exception sub ext) | Tsig_module md -> @@ -861,6 +901,7 @@ let default_mapper = type_extension = type_extension; type_exception = type_exception; extension_constructor = extension_constructor; + effect_constructor = effect_constructor; value_description = value_description; pat = pattern; expr = expression; diff --git a/typing/untypeast.mli b/typing/untypeast.mli index d8a01519f0..0b525c19a9 100644 --- a/typing/untypeast.mli +++ b/typing/untypeast.mli @@ -39,6 +39,8 @@ type mapper = { expr: mapper -> Typedtree.expression -> expression; extension_constructor: mapper -> Typedtree.extension_constructor -> extension_constructor; + effect_constructor: mapper -> Typedtree.extension_constructor + -> effect_constructor; include_declaration: mapper -> Typedtree.include_declaration -> include_declaration; include_description: diff --git a/utils/Makefile b/utils/Makefile index 56d67e4258..9ecf759f49 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -82,6 +82,7 @@ config.ml: config.mlp $(ROOTDIR)/Makefile.config Makefile $(call SUBST,SUPPORTS_SHARED_LIBRARIES) \ $(call SUBST,SYSTEM) \ $(call SUBST,SYSTHREAD_SUPPORT) \ + $(call SUBST,COLLECT_STATS) \ $(call SUBST,TARGET) \ $(call SUBST,WITH_FRAME_POINTERS) \ $(call SUBST,WITH_PROFINFO) \ diff --git a/utils/config.mli b/utils/config.mli index d50761cebe..49ec60abe5 100644 --- a/utils/config.mli +++ b/utils/config.mli @@ -191,6 +191,10 @@ val host : string val target : string (** Whether the compiler is a cross-compiler *) +val stats : bool + (* Whether the compiler records detailed statistics about the program. + Warning: Expect a substantial performance hit. *) + val flambda : bool (** Whether the compiler was configured for flambda *) diff --git a/utils/config.mlp b/utils/config.mlp index 8e4f79d2bf..29b5819414 100644 --- a/utils/config.mlp +++ b/utils/config.mlp @@ -107,14 +107,14 @@ and cmt_magic_number = "Caml1999T027" let interface_suffix = ref ".mli" -let max_tag = 245 +let max_tag = 243 (* This is normally the same as in obj.ml, but we have to define it separately because it can differ when we're in the middle of a bootstrapping phase. *) let lazy_tag = 246 let max_young_wosize = 256 -let stack_threshold = 256 (* see runtime/caml/config.h *) +let stack_threshold = 16 (* see runtime/caml/config.h *) let stack_safety_margin = 60 let architecture = "%%ARCH%%" @@ -148,6 +148,7 @@ let default_executable_name = let systhread_supported = %%SYSTHREAD_SUPPORT%%;; +let stats = %%COLLECT_STATS%%;; let flexdll_dirs = [%%FLEXDLL_DIR%%];; type configuration_value = @@ -191,6 +192,7 @@ let configuration_variables = p "os_type" Sys.os_type; p "default_executable_name" default_executable_name; p_bool "systhread_supported" systhread_supported; + p_bool "stats" stats; p "host" host; p "target" target; p_bool "flambda" flambda; diff --git a/utils/domainstate.ml.c b/utils/domainstate.ml.c index 7ece1ad851..6dbae1d07a 100644 --- a/utils/domainstate.ml.c +++ b/utils/domainstate.ml.c @@ -14,6 +14,10 @@ /* */ /**************************************************************************/ +#define CAML_CONFIG_H_NO_TYPEDEFS +#include "config.h" +let stack_ctx_words = Stack_ctx_words + type t = #define DOMAIN_STATE(type, name) | Domain_##name #include "domain_state.tbl" diff --git a/utils/domainstate.mli.c b/utils/domainstate.mli.c index 1da60c94aa..66a4750d4c 100644 --- a/utils/domainstate.mli.c +++ b/utils/domainstate.mli.c @@ -14,6 +14,8 @@ /* */ /**************************************************************************/ +val stack_ctx_words : int + type t = #define DOMAIN_STATE(type, name) | Domain_##name #include "domain_state.tbl" |