1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 11:50:28 +02:00
Commit graph

65 commits

Author SHA1 Message Date
Andy Wingo
67b699cc77 refactor vm application of non-programs; boot continuation refactor
* libguile/frames.c (scm_frame_instruction_pointer):
* module/system/vm/frame.scm (frame-bindings):
  (frame-next-source, frame-call-representation): Fix a few locations
  that thought that the frame-procedure will always be a VM
  procedure.  This will not not be the case when traversing the stack of
  an application of a non-procedure.

* libguile/vm-i-system.c (call, tail-call, mv-call): Instead of
  special-casing structs and smobs at these call sites, just set up the
  stack, and jump to a generic apply loop if the proc is not a program.

* libguile/vm-engine.c: The generic apply loop is here.  Also, the boot
  program is now simply a boot continuation, and can handle any number
  of arguments.

* libguile/vm.c (make_boot_program): Update the code that makes the boot
  continuation.
2012-05-10 12:59:45 +02:00
Andy Wingo
53bdfcf034 push error handlers out of line in the vm
* libguile/vm.c:
  (vm_error):
  (vm_error_bad_instruction):
  (vm_error_unbound):
  (vm_error_unbound_fluid):
  (vm_error_not_a_variable):
  (vm_error_not_a_thunk):
  (vm_error_apply_to_non_list):
  (vm_error_kwargs_length_not_even):
  (vm_error_kwargs_invalid_keyword):
  (vm_error_kwargs_unrecognized_keyword):
  (vm_error_too_many_args):
  (vm_error_wrong_num_args):
  (vm_error_wrong_type_apply):
  (vm_error_stack_overflow):
  (vm_error_stack_underflow):
  (vm_error_improper_list):
  (vm_error_not_a_pair):
  (vm_error_not_a_bytevector):
  (vm_error_not_a_struct):
  (vm_error_no_values):
  (vm_error_not_enough_values):
  (vm_error_continuation_not_rewindable):
  (vm_error_bad_wide_string_length):
  (vm_error_invalid_address):
  (vm_error_object):
  (vm_error_free_variable): New internal helpers, implementing VM error
  handling.

* libguile/vm-engine.h (VM_ASSERT): New helper macro.
  (ASSERT, CHECK_OBJECT, CHECK_FREE_VARIABLE):
  (PRE_CHECK_UNDERFLOW, PUSH_LIST): Use the new helper.

* libguile/vm-i-loader.c:
* libguile/vm-i-scheme.c:
* libguile/vm-i-system.c: Use VM_ASSERT and the out-of-line error
  handlers.

* libguile/vm-engine.c (vm_engine): Remove inline error handlers, and
  remove a couple of local vars.  Use VM_ASSERT.  Have halt handle the
  return itself.
2012-04-30 21:29:11 +02:00
Ludovic Courtès
37a5970c19 VM: Keep jump table address in a register.
* libguile/vm-engine.c (VM_NAME)[HAVE_LABELS_AS_VALUES]: Rename
  `jump_table' to `jump_table_pointer'.  Add `jump_table' as a local
  variable, initialize it.

* libguile/vm-engine.h (JT_REG): New macro.
2011-07-06 12:50:32 +02:00
Andy Wingo
b2b33168b1 more care regarding SCM_PACK and SCM_UNPACK
* libguile/control.c (reify_partial_continuation):
* libguile/eval.c (RETURN_BOOT_CLOSURE):
* libguile/frames.c (scm_frame_num_locals, scm_frame_local_ref)
  (scm_frame_local_set_x)
* libguile/frames.h (SCM_FRAME_SET_RETURN_ADDRESS):
  (SCM_FRAME_SET_MV_RETURN_ADDRESS, SCM_FRAME_SET_DYNAMIC_LINK):
* libguile/goops.c (scm_class_of, scm_primitive_generic_generic)
  (scm_c_extend_primitive_generic, compute_getters_n_setters)
  (scm_sys_initialize_object):
* libguile/guardians.c (finalize_guarded):
* libguile/list.c (SCM_I_CONS):
* libguile/macros.c (scm_i_make_primitive_macro)
  (scm_make_syntax_transformer):
* libguile/memoize.c (MAKMEMO, SCM_MAKE_MEMOIZER)
  (SCM_MAKE_REST_MEMOIZER):
* libguile/modules.c (scm_module_reverse_lookup)
* libguile/print.c (iprin1):
* libguile/promises.c (scm_make_promise)
* libguile/srcprop.c (scm_make_srcprops):
* libguile/vectors.c (scm_c_vector_ref):
* libguile/vm-engine.c (vm_engine)
* libguile/vm-i-scheme.c (REL, add1, sub1):
* libguile/vm-i-system.c (new_frame, call_cc)
* libguile/weaks.h (SCM_WEAK_PAIR_WORD_DELETED_P): Be more careful about
  SCM_PACK / SCM_UNPACK.
2011-05-13 15:28:08 +02:00
Andy Wingo
a2a6c0e319 avoid tls gets when handling interrupts in the vm
* libguile/__scm.h (SCM_ASYNC_TICK_WITH_CODE): Redefine to take a
  scm_i_thread* as well.  OK to do because it's within a
  BUILDING_LIBGUILE block.

* libguile/vm-engine.c (vm_engine): Cache the scm_i_thread* instead of
  the dynstate, so we can use the thread for ticks.

* libguile/vm-engine.h (VM_HANDLE_INTERRUPTS): Tick with the
  scm_i_thread* local var, to avoid excessive tls calls.

* libguile/vm-i-system.c: Fix dynstate users to use
  current_thread->dynamic_state.
2011-05-06 00:17:35 +02:00
Andy Wingo
eae2438d2b VM tweaks
* libguile/vm-engine.c (VM_CHECK_OBJECT, VM_CHECK_FREE_VARIABLES): Set
  to 0 for both engines.  These are really internal debugging variables,
  which don't affect user-visible features, provided that the compiler
  is correct of course.
  (VM_CHECK_UNDERFLOW): New var, also off by default: whether to check
  for stack underflow when popping values.
  (vm_engine): Don't declare object_count if we are not checking object
  table accesses.

* libguile/vm-engine.h (CACHE_PROGRAM): Don't muck with object_count
  if we are not checking object table accesses.
  (CHECK_UNDERFLOW, PRE_CHECK_UNDERFLOW): Nop out if we are not checking
  underflow.
  (POP2, POP3): New macros which check for underflow before popping more
  than one value.

* libguile/vm-i-loader.c (load_array):
* libguile/vm-i-scheme.c (set_car, set_cdr, vector_set, slot_set)
  (BV_SET_WITH_ENDIANNESS, BV_FIXABLE_INT_SET, BV_INT_SET)
  (BV_FLOAT_SET):
* libguile/vm-i-system.c (partial_cont_call, fix_closure, prompt)
  (fluid_set): Use POP2 / POP3.
  (local_set, long_local_set): Pop to locals instead of using values on
  the stack then dropping; allows for underflow to be checked before the
  value is accessed.
  (BR): Don't NULLSTACK or DROP after the operation.
  (br_if, br_if_not, br_if_eq, br_if_not_eq, br_if_null)
  (br_if_not_null): Pop to locals before doing the compare and jump.
2011-05-05 14:04:23 +02:00
Andy Wingo
501cf7d607 latin1 strings in vm error messages
* libguile/vm-engine.c: Use latin1 strings here for the string
  literals.
2011-04-29 11:07:25 +02:00
Andy Wingo
9b709b0fe1 fix frame dynamic linkage in the face of partial continuation application
* libguile/vm-i-system.c (new-frame): Though it was appealing to set the
  dynamic link here on the incomplete frame, we no longer do that, for
  the reasons mentioned in the code.
  (call, mv-call): Adapt to set the frame's dynamic link.

* libguile/vm-engine.c (vm_engine): Don't set dynamic link here, even
  for boot program.

* libguile/frames.c (scm_frame_num_locals, scm_frame_local_ref)
  (scm_frame_local_set_x): Fix up not-yet-active frame detection.
2011-03-15 23:45:58 +01:00
Andy Wingo
dce0252bf2 fix error handling in variable-ref family of instructions
* libguile/vm-i-system.c (variable-ref, variable-set, variable-bound?):
  Check that the argument is actually a variable.  Thanks to Kevin
  Holmes for the report.

* libguile/vm-engine.c (vm_engine): Error handling down here.

* THANKS: Update.
2011-01-27 10:49:51 +01:00
Andy Wingo
1cc0b6adde fix error-handling of apply to non-list
* libguile/vm-engine.c (vm_error_apply_to_non_list): Sync registers
  before erroring. Fix type of finish_args.  Thanks to Hans Aberg for
  the report.
2011-01-26 21:44:12 +01:00
Brian Templeton
ef94624eaf unbound fluids
* libguile/fluids.c (scm_make_undefined_fluid, scm_fluid_unset_x)
  (scm_fluid_bound_p): New functions.

  (fluid_ref): New function; like scm_fluid_ref, but will not throw an
  error for unbound fluids.
  (scm_fluid_ref, swap_fluid): Use `fluid_ref'.

* libguile/fluids.h (scm_make_undefined_fluid, scm_fluid_unset_x)
  (scm_fluid_bound_p): New prototypes.

* libguile/vm-i-system.c (fluid_ref): If fluid is unbound, jump to
  `vm_error_unbound_fluid'.
* libguile/vm-engine.c (VM_NAME)[vm_error_unbound_fluid]: New error
  message.

* test-suite/tests/fluids.test ("unbound fluids")["fluid-ref of unbound
  fluid", "fluid-bound? of bound fluid", "fluid-bound? of unbound
  fluid", "unbound fluids can be set", "bound fluids can be unset"]: New
  tests.
2010-12-07 13:21:01 +01:00
Andy Wingo
d107921794 better unbound variable errors in the vm
* libguile/vm-i-system.c (variable-ref, toplevel-ref)
  (long-toplevel-ref): Fixup callers.

* libguile/vm-engine.c (vm_error_unbound): Don't use vm-error for
  unbound vars, use misc-error. Don't include VM: in the string. Take
  the name directly in finish_args, not as a list.
2010-12-07 13:21:01 +01:00
Andy Wingo
c45d4d775d trim our set of vm hooks
* libguile/vm.h (SCM_VM_PUSH_CONTINUATION_HOOK)
  (SCM_VM_POP_CONTINUATION_HOOK): New hooks, to replace
  enter/exit/return.
  (SCM_VM_BOOT_HOOK, SCM_VM_HALT_HOOK, SCM_VM_BREAK_HOOK): Remove these
  useless hooks.

* libguile/vm.c (scm_vm_push_continuation_hook)
  (scm_vm_pop_continuation_hook): New accessors.

* libguile/vm-i-system.c: Remove boot, halt, break, enter, exit, and
  return hooks. Also remove the break instruction. Instead now when we
  push a new continuation onto the stack we call PUSH_CONTINUATION_HOOK,
  and when we pop via a return we call POP_CONTINUATION_HOOK. APPLY_HOOK
  is now decoupled from continuation pushes and pops.

* libguile/vm-engine.h:
* libguile/vm-engine.c: Adapt for hooks.

* module/system/vm/trace.scm (vm-trace): Adapt for hooks. Also revive
  the #:instructions? #t mode.

* module/system/vm/vm.scm: Adapt exports for new set of hooks.
2010-09-16 12:16:02 +02:00
Ludovic Courtès
1af772303b Import unbound variable reports in the VM.
* libguile/vm-engine.c (VM_NAME)[vm_error_unbound]: Add comment.

* libguile/vm-i-system.c (variable_ref): Attempt provide the name of X
  in FINISH_ARGS.
2010-07-26 19:38:52 +02:00
Andy Wingo
41e49280f3 better error reporting from the vm
* libguile/vm-engine.c: Add func_name local, for error reporting.
  (vm_error_apply_to_non_list): New error case.
  (vm_error_wrong_type_arg): Remove this generic error case.
  (vm_error_wrong_type_apply): Remove FUNC_NAME -- no sense in seeing
  "vm-debug-engine" in the error report.
  (vm_error_not_a_pair, vm_error_not_a_bytevector)
  (vm_error_not_a_struct, vm_error_not_a_thunk): Use func_name instead
  of FUNC_NAME, so we can indicate what caused the error.

* libguile/vm-i-scheme.c (VM_VALIDATE_CONS, car, cdr, set-car!)
  (set-cdr!): Indicate provenance of errors.
  (VM_VALIDATE_STRUCT, struct-vtable):
  (VM_VALIDATE_BYTEVECTOR, BV_FIXABLE_INT_REF, BV_INT_REF)
  (BV_FLOAT_REF, BV_FIXABLE_INT_SET, BV_INT_SET, BV_FLOAT_SET): Same.

* libguile/vm-i-system.c (apply, tail-apply): Use
  vm_error_apply_to_non_list.
2010-07-15 12:44:15 +02:00
Ludovic Courtès
f1046e6b78 Raise an exception upon VM stack overflows (fixes bug #29574).
* libguile/vm-engine.c (VM_NAME)[vm_error_stack_overflow]: Increase
  `vp->stack_limit' when possible.

* libguile/vm.c (VM_STACK_RESERVE_SIZE): New macro.

* test-suite/lib.scm (exception:vm-error): New variable.

* test-suite/tests/eval.test ("stack overflow"): New test prefix.
2010-05-26 23:41:23 +02:00
Andy Wingo
b3950ad6d8 error if given an unrewindable partial continuation
* libguile/vm-engine.c (vm_error_continuation_not_rewindable):
* libguile/vm-i-system.c (partial-cont-call):
* libguile/vm.h (SCM_VM_CONT_PARTIAL_P):
  (SCM_VM_CONT_REWINDABLE_P): Fix a bug in which we weren't checking if
  a partial continuation was actually rewindable.
2010-02-25 00:43:51 +01:00
Andy Wingo
2d026f04cc abort always dispatches to VM bytecode, to detect same-invocation aborts
* libguile/control.h:
* libguile/control.c (scm_c_make_prompt): Take an extra arg, a cookie.
  Continuations will be rewindable only if the abort has the same cookie
  as the prompt.
  (scm_at_abort): Redefine from scm_abort, and instead of taking rest
  args, take the abort values as a list directly. Also, don't allow
  rewinding, because we won't support rewinding the C stack with
  delimited continuations.

* libguile/eval.c (eval): Adapt to scm_c_make_prompt change.

* libguile/vm-engine.c (vm_engine): Use vp->cookie to get a unique value
  corresponding to this VM invocation.
* libguile/vm-i-system.c (prompt): Pass the cookie to scm_c_make_prompt.
  (abort): Take an additional tail arg.
* libguile/vm.c (vm_abort): Parse out the abort tail arg. This is for
  the @abort case, or the (apply abort ...) case.
  (make_vm): Initialize the cookie to 0.
* libguile/vm.h (struct scm_vm): Add cookie.

* module/ice-9/boot-9.scm (abort): Define here as a trampoline to
  @abort. Needed to make sure that a call to abort dispatches to a VM
  opcode, so the cookie will be the same.

* module/language/tree-il.scm (<tree-il>): Add a "tail" field to
  <abort>, for the (apply abort ...) case, or (@abort tag args). Should
  be #<const ()> in the normal case. Add support throughout.
* module/language/tree-il/analyze.scm (analyze-lexicals): Add abort-tail
  support here too.

* module/language/tree-il/compile-glil.scm (flatten): Compile the tail
  argument appropriately.
* module/language/tree-il/primitives.scm (*primitive-expand-table*): Fix
  @abort and abort cases to pass the tail arg to make-abort.
2010-02-22 21:54:06 +01:00
Andy Wingo
26e6f99fc3 vm caches the dynamic state in a local var
* libguile/vm-engine.c (vm_engine): Cache the dynamic state in a local
  var when we enter the VM.
* libguile/vm-i-system.c (wind-fluids, unwind-fluids): Use the cached
  dynamic state instead of going through SCM_I_CURRENT_THREAD.
2010-02-19 12:10:11 +01:00
Andy Wingo
4f66bcdeff initial VM support for delimited continuations and dynamic-wind
* libguile/vm-i-system.c (prompt, wind, throw, unwind):
  New instructions, for implementing dynamic-wind and delimited
  continuations.
* libguile/vm.c: Add some stub support for the new instructions.
* libguile/vm-engine.c: Some new error conditions.
2010-01-31 20:40:21 +01:00
Andy Wingo
6f16379e9a allocate free variables inline to closures
* libguile/_scm.h (SCM_OBJCODE_MINOR_VERSION): Bump.

* libguile/programs.h (SCM_PROGRAM_FREE_VARIABLES)
  (SCM_PROGRAM_FREE_VARIABLE_REF, SCM_PROGRAM_FREE_VARIABLE_SET)
  (SCM_PROGRAM_NUM_FREE_VARIABLES):
* libguile/programs.c (scm_make_program, scm_program_num_free_variables)
  (scm_program_free_variable_ref, scm_program_free_variable_set_x):
  Allocate free variables inline with programs, instead of being in a
  vect. Should improve locality, and require fewer local variables in
  the VM.

* libguile/vm-engine.c (vm_engine): Remove free_vars and free_vars_count
  variables.

* libguile/vm-engine.h (CACHE_PROGRAM): No need to muck with free_vars
  and free_vars_count.
  (CHECK_FREE_VARIABLE): Update for inline free vars.

* libguile/vm-i-system.c (FREE_VARIABLE_REF): Update for inline free
  vars.
  (make-closure, fix-closure): Take the closure vals as separate stack
  args, and copy or fix them inline into the appropriate closure.

* module/language/objcode/spec.scm (program-free-variables): Define a
  local version of this removed function.

* module/language/tree-il/compile-glil.scm (flatten): Adjust to not make
  a vector when making closures.

* module/system/vm/program.scm: Export program-num-free-variables,
  program-free-variable-ref, program-free-variable-set!, and remove
  program-free-variables.

* test-suite/tests/tree-il.test ("lambda"): Update to not make vectors
  when making closures.
2010-01-09 16:43:26 +01:00
Andy Wingo
f6a8e79197 keyword arg errors throw to 'keyword-argument-error
* libguile/vm-engine.c (VM_NAME): Keyword arg errors are now thrown to
  'keyword-argument-error.

* libguile/vm.c: Define sym_keyword_argument_error, and statically
  allocate some other symbols.

* module/ice-9/optargs.scm (parse-lambda-case): Throw to
  'keyword-argument-error in kwarg error cases.

* module/ice-9/psyntax.scm (build-lambda-case): Remove a couple
  workarounds for the old memoizer. Throw to 'wrong-number-of-args if
  the lambda-case fails to parse.

* module/ice-9/psyntax-pp.scm: Regenerated.

* test-suite/tests/optargs.test: Update expected exceptions.
2009-12-23 22:59:12 +01:00
Andy Wingo
7656f19446 rework vm tracing
* libguile/vm-engine.c (VM_NAME): Engines take the VM itself (not the
  vp), so they can pass the VM to hooks. No more hook args, we dispatch
  without them.

* libguile/vm-engine.h (RUN_HOOK): Dispatch the hook if the trace level
  is positive (instead of if the hook is there). Don't cache registers
  on return from the dispatch.

* libguile/vm.h:
* libguile/vm.c (vm_dispatch_hook): Don't bother with a dynwind; instead
  decrement the trace level when going into a hook, and if we have a
  nonlocal exit, the trace level never gets incremented again. Worse is
  better.
  (make_vm, scm_vm_trace_level, scm_set_vm_trace_level_x): New concept,
  trace level. If positive, we run the hooks, otherwise we don't. Should
  work. Removed scm_vm_trace_frame, I don't think that was the right way
  to do it.

* module/system/vm/vm.scm: Replace vm-trace-frame with vm-trace-level
  and set-vm-trace-level!; the hooks actually get the frame as an
  argument now.
2009-12-21 21:57:20 +01:00
Ludovic Courtès
3dbbe28dfd Don't use GCC zero-length arrays.
* libguile/frames.c, libguile/objcodes.c, libguile/programs.c,
  libguile/vm-engine.c, libguile/vm-i-system.c, libguile/vm.c: Use
  `SCM_C_OBJCODE_BASE ()' instead of accessing the `base' field of
  `struct scm_objcode'.

* libguile/objcodes.h (struct scm_objcode)[base]: Remove.
2009-12-15 01:01:16 +01:00
Ludovic Courtès
bd91ecce14 Add opcodes for struct?', struct-vtable', and `make-struct'.
* libguile/vm-engine.c (VM_NAME)[vm_error_not_a_struct]: New label.

* libguile/vm-i-scheme.c (VM_VALIDATE_STRUCT): New macro.
  (struct_p, struct_vtable, make_struct): New instructions.

* module/language/tree-il/compile-glil.scm (*primcall-ops*): Add
  `struct?', `struct-vtable', and `make-struct'.

* module/language/tree-il/primitives.scm (*interesting-primitive-names*,
  *effect-free-primitives*): Likewise.
2009-12-11 13:03:45 +01:00
Andy Wingo
6c20a0b34b vm no longer measures bogoclock or times, relies on os for that
* libguile/vm.h (struct scm_vm): Remove "time" and "clock" members. The
  time was bogusly measured, and the "clock" measured instructions
  retired, which is not a very useful measurement, and it was causing
  lots of memory accesses. Not that I have done a proper profile,
  though...
  (scm_vm_stats): Remove this procedure, which provided access to "time"
  and "clock".

* libguile/vm.c:
* libguile/vm-engine.h:
* libguile/vm-engine.c:
* libguile/vm-i-system.c: Adapt to scm_vm changes and scm_vm_stats
  removal.

* module/system/repl/command.scm:
* module/system/vm/vm.scm: Adapt to vm-stats removal by removing
  vm-stats from <repl>.
2009-12-11 12:39:02 +01:00
Andy Wingo
14aa25e410 remove debug frames
* libguile/debug.h (scm_t_debug_frame): Remove this type, as it was
  internal to the old evaluator.
  (SCM_EVALFRAME, SCM_APPLYFRAME, SCM_VOIDFRAME, SCM_MACROEXPF)
  (SCM_TAILREC, SCM_TRACED_FRAME, SCM_ARGS_READY, SCM_DOVERFLOW)
  (SCM_MAX_FRAME_SIZE, SCM_FRAMETYPE)
  (SCM_EVALFRAMEP, SCM_APPLYFRAMEP, SCM_VOIDFRAMEP, SCM_MACROEXPFP)
  (SCM_TAILRECP, SCM_TRACED_FRAME_P, SCM_ARGS_READY_P, SCM_OVERFLOWP)
  (SCM_SET_MACROEXP, SCM_SET_TAILREC, SCM_SET_TRACED_FRAME)
  (SCM_SET_ARGSREADY, SCM_SET_OVERFLOW)
  (SCM_CLEAR_MACROEXP, SCM_CLEAR_TRACED_FRAME, SCM_CLEAR_ARGSREADY):
  Remove macro accessors to scm_t_debug_frame.
  (SCM_DEBUGOBJP, SCM_DEBUGOBJ_FRAME, SCM_SET_DEBUGOBJ_FRAME):
  (scm_debug_object_p, scm_make_debugobj): Remove debugobj accessors.
  (scm_i_unmemoize_expr): Remove unused declaration.

* libguile/debug.c (scm_debug_options): No more max limit on frame
  sizes.
  (scm_start_stack): Just call out to scm_vm_call_with_new_stack.
  (scm_debug_object_p, scm_make_debugobj, scm_init_debug): No more
  debugobj smob type.

* libguile/deprecated.h:
* libguile/deprecated.c (scm_i_deprecated_last_debug_frame)
  (scm_last_debug_frame): Remove deprecated debug-frame bits.

* libguile/stacks.c (scm_make_stack): Rework this function and its
  dependents to only walk VM frames.
  (scm_stack_id): Call out to the holder of the VM frame in question,
  which should be a VM or a VM continuation, for the stack ID. Currently
  this bit is stubbed out.
  (scm_last_stack_frame): Removed. It seems this is mainly useful for a
  debugger, and we need to rewrite the debugger to work on the Scheme
  level.

* test-suite/tests/continuations.test ("continuations"): Remove test for
  last-stack-frame.

* libguile/continuations.h (struct scm_t_contregs):
* libguile/continuations.c (scm_make_continuation):
  (copy_stack_and_call, scm_i_with_continuation_barrier): No need to
  save and restore debug frames.

* libguile/threads.h (scm_i_thread): Don't track debug frames.
  (scm_i_last_debug_frame, scm_i_set_last_debug_frame): Remove macro
  accessors.

* libguile/threads.c (guilify_self_1): Don't track debug frames.

* libguile/throw.c: No need to track debug frames in a jmpbuf.

* libguile/vm-engine.c (vm_engine, VM_PUSH_DEBUG_FRAMES): Don't push
  debug frames.

* libguile/vm.h:
* libguile/vm.c (scm_vm_call_with_new_stack): New function. Currently
  stubbed out though.
2009-12-03 11:03:39 +01:00
Andy Wingo
5f1611640a really boot primitive-eval from scheme.
* libguile/eval.c (scm_primitive_eval, scm_c_primitive_eval):
  (scm_init_eval): Rework so that scm_primitive_eval always calls out to
  the primitive-eval variable. The previous definition is the default
  value, which is probably overridden by scm_init_eval_in_scheme.

* libguile/init.c (scm_i_init_guile): Move ports and load-path up, so we
  can debug when initing eval. Call scm_init_eval_in_scheme. Awesome.

* libguile/load.h:
* libguile/load.c (scm_init_eval_in_scheme): New procedure, loads up
  ice-9/eval.scm to replace the primitive-eval definition, if everything
  is there and up-to-date.

* libguile/modules.c (scm_module_transformer): Export to Scheme, so it's
  there for eval.go.

* module/ice-9/boot-9.scm: No need to define module-transformer.

* module/ice-9/eval.scm (capture-env): Only reference the-root-module if
  modules are booted.
  (primitive-eval): Inline a definition for identity. Throw a more
  standard error for "wrong number of arguments".

* module/ice-9/psyntax.scm (chi-install-global): The macro binding for a
  syncase macro is now a pair: the transformer, and the module that was
  current when the transformer was installed. The latter is used for
  hygiene purposes, replacing the use of procedure-module, which didn't
  work with the interpreter's shared-code closures.
  (chi-macro): Adapt for the binding being a pair, and get the hygiene
  from the cdr.
  (eval-local-transformer): Adapt to new form of macro bindings.

* module/ice-9/psyntax-pp.scm: Regenerated.

* .gitignore: Ignore eval.go.stamp.

* module/Makefile.am: Reorder for fastest serial compilation, now that
  there are no ordering constraints. I did a number of experiments here
  and this seems to be the best; but the bulk of the time is compiling
  psyntax-pp.scm with eval.scm. Not so great.

* libguile/vm-engine.c (vm-engine): Throw a more standard error for
  "wrong type to apply".

* test-suite/tests/gc.test ("gc"): Remove a hack that shouldn't affect
  the new evaluator, and throw in another (gc) for good measure.

* test-suite/tests/goops.test ("defining classes"):
* test-suite/tests/hooks.test (proc1): We can't currently check what the
  arity is of a closure made by eval.scm -- or more accurately all
  closures have 0 required args and no rest args. So punt for now.

* test-suite/tests/syntax.test ("letrec"): The scheme evaluator can't
  check that a variable is unbound, currently; perhaps the full "fixing
  letrec" expansion could fix this. But barring that, punt.
2009-12-03 00:00:38 +01:00
Ludovic Courtès
56a3dcd431 Remove references to undefined macros.
The intent is to allow compilation with `-Wundef', which in turn should
make it easier to catch erroneous uses of nonexistent macros.

* libguile/__scm.h: Don't assume `BUILDING_LIBGUILE' is defined.

* libguile/conv-uinteger.i.c (SCM_TO_TYPE_PROTO): Remove unneeded CPP
  conditional on `TYPE_MIN == 0'.

* libguile/fports.c: Check for the definition of `HAVE_CHSIZE' and
  `HAVE_FTRUNCATE', not for their value.

* libguile/ports.c: Likewise.

* libguile/numbers.c (guile_ieee_init): Likewise with `HAVE_DINFINITY'
  and `HAVE_DQNAN'.

* test-suite/standalone/test-conversion.c (ieee_init): Likewise.

* libguile/strings.c: Likewise with `SCM_STRING_LENGTH_HISTOGRAM'.

* libguile/strings.h: Likewise.

* libguile/tags.h: Likewise with `HAVE_INTTYPES_H' and `HAVE_STDINT_H'.

* libguile/threads.c: Likewise with `HAVE_PTHREAD_GET_STACKADDR_NP'.

* libguile/vm-engine.c (VM_NAME): Likewise with `VM_CHECK_IP'.

* libguile/gen-scmconfig.c (main): Use "#ifdef HAVE_", not "#if HAVE_".

* libguile/socket.c (scm_setsockopt): Likewise.
2009-11-17 23:42:22 +01:00
Andy Wingo
7e01997e88 finish support for optional & keyword args; update ecmascript compiler
* libguile/_scm.h (SCM_OBJCODE_MINOR_VERSION): Bump.
* libguile/vm-i-system.c (br-if-nargs-ne, br-if-args-lt)
  (br-if-nargs-gt): New instructions, for use by different lambda cases.
  (bind-optionals, bind-optionals/shuffle, bind-kwargs): New
  instructions, for binding optional and keyword arguments. Renumber
  other ops.

* module/language/ecmascript/compile-tree-il.scm (comp, comp-body):
  Update for new tree-il. Use the new optional argument mechanism
  instead of emulating it with rest arguments.

* module/language/glil/compile-assembly.scm (glil->assembly): Tweaks for
  optional and keyword argument compilation.

* module/language/tree-il.scm (parse-tree-il, unparse-tree-il): Make the
  else case optional, in the s-expression serialization of tree-il.

* module/language/tree-il/compile-glil.scm (flatten): Handle all of the
  lambda-case capabilities.
2009-10-23 15:10:25 +02:00
Andy Wingo
a6f15a1eba callees now check their args, cons rest list, reserve locals
* gdbinit: Ignore SIGPWR and SIGXCPU, which the BDW GC seems to use.

* libguile/vm-engine.h (FETCH_WIDTH): Remove unused macro.
  (INIT_ARGS, INIT_FRAME): Remove; callees now check their args and
  reserve space for their locals.

* libguile/vm-engine.c:
* libguile/vm-i-system.c: Turn on callee arg checking and local
  reservation. Seems to work!
2009-10-23 14:51:18 +02:00
Andy Wingo
6c6a44390b runtime and debugging support for callee-parsed procedure args
* libguile/objcodes.h: Bump for metadata format change.

* libguile/frames.h: Rework so we don't frob the program's nargs, nlocs,
  etc at runtime. Instead we don't really know what's a local var, an
  argument, or an intermediate value. It's a little unfortunate, but
  this will allow for case-lambda, and eventually for good polymorphic
  generic dispatch; and the nlocs etc can be heuristically
  reconstructed. Such a reconstruction would be better done at the
  Scheme level, though.
  (SCM_FRAME_STACK_ADDRESS): New macro, the pointer to the base of the
  stack elements (not counting the program).
  (SCM_FRAME_UPPER_ADDRESS): Repurpose to be the address of the last
  element in the bookkeeping part of the stack -- i.e. to point to the
  return address.

* libguile/vm-engine.h:
* libguile/vm-i-system.c: Adapt to removal of stack_base. Though we
  still detect stack-smashing underflow, we don't do so as precisely as
  we did before, because now we only detect overwriting of the frame
  metadata.

* libguile/vm-engine.c (vm_engine): Remove the stack_base variable. It
  is unnecessary, and difficult to keep track of in the face of
  case-lambda. Also fix miscommented "ra" and "mvra" pushes. Push the
  vp->ip as the first ra...
* libguile/vm-i-system.c (halt): ...because here we can restore the
  vp->ip instead of setting ip to 0. Allows us to introspect ips all
  down the stack, including in recursive VM invocations.

* libguile/frames.h:
* libguile/frames.c (scm_vm_frame_stack): Removed, because it's getting
  more difficult to tell what's an argument and what's a temporary stack
  element.
  (scm_vm_frame_num_locals): New accessor.
  (scm_vm_frame_instruction_pointer): New accessor.
  (scm_vm_frame_arguments): Defer to an implementation in Scheme.
  (scm_vm_frame_num_locals scm_vm_frame_local_ref)
  (scm_vm_frame_local_set_x): Since we can get not-yet-active frames on
  the stack now, with our current calling convention, we have to add a
  heuristic here to jump over those frames -- because frames have
  pointers in them, not Scheme values.

* libguile/programs.h:
* libguile/programs.c (scm_program_arity): Remove, in favor of..
  (scm_program_arities): ...this, which a list of arities, in a new
  format, occupying a slot in the metadata.

* module/language/assembly/decompile-bytecode.scm (decode-load-program):
  Fix mv-call decompilation.

* module/system/vm/frame.scm (vm-frame-bindings, vm-frame-binding-ref)
  (vm-frame-binding-set!): New functions, to access bindings by name in
  a frame.
  (vm-frame-arguments): Function now implemented in Scheme. Commented
  fairly extensively.

* module/system/vm/program.scm (program-bindings-by-index)
  (program-bindings-for-ip): New accessors, parsing the program bindings
  metadata into something more useful.
  (program-arities, program-arguments): In a case-lambda world, we have
  to assume that programs can have multiple arities. But it's tough to
  detect this algorithmically; instead we're going to require that the
  program metadata include information about the arities, and the parts
  of the program that that metadata applies to.
  (program-lambda-list): New accessor.
  (write-program): Show multiple arities.

* module/language/glil/compile-assembly.scm (glil->assembly): Add
  "arities" to the state of the compiler, and add arities entries as
  appropriate.
2009-10-23 14:51:17 +02:00
Andy Wingo
2fb924f64f programs have their own tc7 now
* libguile/tags.h (scm_tc7_program):
* libguile/programs.h: Programs now have their own tc7 code. Fix up the
  macros appropriately.

* libguile/programs.c: Remove smobby bits, leaving marking, printing,
  and application for other parts of Guile.

* libguile/debug.c (scm_procedure_source):
* libguile/eval.c (scm_trampoline_0, scm_trampoline_1)
  (scm_trampoline_2): Add cases for tc7_program.
* libguile/eval.i.c (CEVAL, SCM_APPLY):
* libguile/evalext.c (scm_self_evaluating_p):
* libguile/gc-card.c (scm_i_sweep_card, scm_i_tag_name):
* libguile/gc-mark.c (1):
* libguile/print.c (iprin1):
* libguile/procs.c (scm_procedure_p, scm_thunk_p)
* libguile/vm-i-system.c (make-closure): Adapt to new procedure
  representation.

* libguile/procprop.c (scm_i_procedure_arity): Do the right thing for
  programs.
* test-suite/tests/procprop.test ("procedure-arity"): Arity test now
  succeeds.

* libguile/goops.c (scm_class_of): Programs now belong to the class
  <procedure>, not a smob class.

* libguile/vm.h (struct vm, struct vm_cont):
* libguile/vm-engine.c (vm_engine):
* libguile/frames.h (SCM_FRAME_BYTE_CAST, struct vm_frame):
* libguile/frames.c (scm_c_make_vm_frame): Fix usages of scm_byte_t,
  changing them to scm_t_uint8.
2009-08-20 18:52:51 +02:00
Andy Wingo
7ea9a0a764 better VM error messages
* libguile/vm-engine.c: Attempt to make error messages more friendly
  and uniform with historical expectation.
2009-08-20 18:52:50 +02:00
Andy Wingo
b7946e9ec6 push new frame on stack before procedure & args
* libguile/_scm.h (SCM_OBJCODE_MINOR_VERSION): Bump

* libguile/vm-engine.c (vm_engine): Push a frame corresponding to the
  mv-call.

* libguile/vm-i-system.c: Renumber ops.
  (new-frame): New op, pushes a frame.
  (call, mv-call): No need to shuffle args, though we do need to pop the
  frame in the non-vm call case.
  (goto/args): Inconsequential tweaks.
  (call/cc): Push a frame if needed.

* module/language/tree-il/compile-glil.scm (flatten): Emit `new-frame'
  as appropriate.

* test-suite/tests/tree-il.test: Fix to expect new-frame.
2009-08-20 18:52:50 +02:00
Andy Wingo
03e6c16596 reorder frame layout
* libguile/frames.h: Reorder the frame layout so the return address
  comes below the arguments.working
  (SCM_FRAME_SET_RETURN_ADDRESS, SCM_FRAME_SET_MV_RETURN_ADDRESS): New
  macros.

* libguile/frames.c (scm_vm_frame_arguments): Use the macros to access
  the arguments.

* libguile/vm-engine.c (vm_engine): Fix for new calling convention.

* libguile/vm-engine.h (INIT_FRAME): New macro. Does part of what
  NEW_FRAME used to do.

* libguile/vm-i-system.c (call, mv-call): Shuffle args up to make room
  for the stack, and adapt to new calling convention.
  (goto/args): Shuffling down is easier now.
  (return, return/args): Adapt to new frame layout.

* libguile/vm.c (vm_mark_stack): Adapt to new frame layout, and the
  possibility of there being crap on the stack.
  (really_make_boot_program): Remove extraneous comment.
2009-08-20 18:52:49 +02:00
Andy Wingo
94ff26b96b rework the vm support for wide strings
* libguile/_scm.h (SCM_OBJCODE_MINOR_VERSION): Bump.

* libguile/vm-engine.c (vm_error_bad_wide_string_length): New error
  case.

* libguile/vm-i-loader.c (load-unsigned-integer, load-integer)
  (load-keyword): Remove these instructions. The former two are
  obsoleted by make-int64/make-uint64, the latter via make-keyword.
  (load-string): Only handle narrow strings.
  (load-symbol): Only handle narrow symbols. The wide case is handled
  via make-symbol.
  (load-wide-string): New instruction, for wide strings.

* libguile/vm-i-system.c (define): Move here from loaders.c, as now it
  just takes a sym on the stack.
  (make-keyword, make-symbol): New instructions.

* module/language/assembly.scm: Remove removed instructions. No more
  width byte in load-string etc.

* module/language/assembly/compile-bytecode.scm (write-bytecode): Adapt
  to change in instruction set.

* module/language/glil/compile-assembly.scm (glil->assembly): Compile
  define by pushing the sym then emitting (define).
  (dump-object): Dump narrow and wide strings differently. Use
  make-keyword and make-symbol as appropriate.

* module/language/tree-il/compile-glil.scm (flatten): When compiling a
  ref to a primitive (not a call), first see if the primitive is
  actually bound in the root module. (That's not the case with e.g.
  bytevector-u8-ref).

* module/system/xref.scm (program-callee-rev-vars): Don't parse out
  "nexts".

* test-suite/tests/asm-to-bytecode.test ("compiler"): Adapt to bytecode
  format change.
2009-08-12 16:34:05 +02:00
Andy Wingo
57ab0671d7 rename "closure-ref" to "free-ref"; s/vars/variables/ in some names
* libguile/programs.h:
* libguile/programs.c: (SCM_PROGRAM_FREE_VARIABLES): Rename from
  SCM_PROGRAM_FREE_VARS. Callers changed.
* libguile/programs.c (scm_make_program): Rename arg to
  "free_variables".
  (scm_program_free_variables): Rename from program-free-vars.

* libguile/vm-engine.h:
* libguile/vm-engine.c (VM_CHECK_FREE_VARIABLES): Rename from
  VM_CHECK_CLOSURE.
  (vm_engine, CACHE_PROGRAM): Rename closure and closure_count to free_vars and
  free_vars_vount.

* libguile/vm-i-system.c (FREE_VARIABLE_REF): Rename from CLOSURE_REF.
  (free-ref, free-boxed-ref, free-boxed-set): Rename from closure-ref,
  closure-boxed-ref, closure-boxed-set.
  (make-closure): Renamed from make-closure2.

* module/language/glil/compile-assembly.scm (glil->assembly): Hack to
  never write out the the old "make-closure" instruction. Will fix
  better later. Change to emit free-ref etc instead of closure-ref.

* module/language/tree-il/compile-glil.scm (flatten): Emit make-closure
  instead of make-closure2, now that the old make-closure is gone.

* module/system/vm/program.scm (system): Rename program-free-vars to
  program-free-variables.

* test-suite/tests/tree-il.test ("lambda"): Update for make-closure.
2009-07-23 17:15:17 +02:00
Andy Wingo
20d47c3915 remove "externals" from the vm
* libguile/frames.c (scm_frame_external_link): Removed.
* libguile/frames.h: No need to have the "external link" in the stack
  frame -- update macros to take the new situation into account.

* libguile/objcodes.h (struct scm_objcode): Rename the nexts field to
  "unused". In the future we can use it for nlocs, I think.
  (SCM_OBJCODE_NEXTS): removed.

* libguile/programs.h:
* libguile/programs.c (scm_make_program): Expect the third argument to
  be a vector of free variables, not a list of free variables.
  SCM_BOOL_F indicates no free variables, not SCM_EOL.
  (program_mark): Adapt.
  (scm_program_arity): No more nexts.
  (scm_program_free_vars): Replaces scm_program_externals.

* libguile/vm-engine.c (VM_CHECK_EXTERNAL)
  (vm_engine): No need for the "external" var.
* libguile/vm-engine.h (CACHE_PROGRAM): Update for SCM_PROGRAM_FREE_VARS
  instead of SCM_PROGRAM_EXTERNALS.
  (NEW_FRAME): Update for new frame size, and no need to cons up
  externals. Yay :)

* libguile/vm-i-loader.c (load-program): Update for scm_make_program.

* libguile/vm-i-system.c (external-ref, external-set): No more.
  (make-closure): No more.
  (goto/args): No need to re-cons externals here. Update for new stack
  frame size.
  (mv-call, return, return/values): Update for new frame size. No need
  to reinstate externals on return.

* libguile/vm.c (really_make_boot_program, scm_load_compiled_with_vm):
  Update for scm_make_program.
* module/language/objcode/spec.scm (objcode-env-externals): Treat '() as
  #f, for the externals. Need to clean this up later...
* module/system/vm/program.scm (arity:nexts): Remove. Rename
  program-external to program-free-vars.
2009-07-23 17:15:13 +02:00
Andy Wingo
8d90b35656 vm support for display closures
* libguile/vm-i-system.c (box, empty-box): Boxing values and storing
  them in local variables.
  (local-boxed-ref, local-boxed-set): A combination of local-ref then
  variable-ref/set.
  (make-closure2, closure-ref, closure-boxed-ref, closure-boxed-set):
  New ops. The idea is to migrate Guile over to using flat dispay
  closures. See the paper "Three Implementation Models for Scheme" by
  Kent Dybvig for more details; this is the "stack-based" model.

* libguile/vm-engine.c:
* libguile/vm-engine.h: Add the necessary infrastructure to keep track
  of a "closure" variable, like our "externals" in semantics, but
  minimal, flat, and O(1) in implementation.
2009-07-22 00:13:52 +02:00
Andy Wingo
e6eb246716 add bytevector ops to the vm
* libguile/instructions.h (SCM_VM_NUM_INSTRUCTIONS): Enlarge to 255. Not
  sure what performance effects this will have.

* libguile/vm-engine.c: Add new error case, vm_error_not_a_bytevector.

* libguile/vm-engine.h: Don't assign specific registers for i386. Having
  added the new VM vector ops, GCC 4.4 is erroring for me now.

* libguile/vm-i-scheme.c: Add bytevector-specific ops to the VM.
  We don't actually use them yet, though.
2009-06-26 12:42:10 +02:00
Neil Jerram
53befeb700 Change Guile license to LGPLv3+
(Not quite finished, the following will be done tomorrow.
   module/srfi/*.scm
   module/rnrs/*.scm
   module/scripts/*.scm
   testsuite/*.scm
   guile-readline/*
)
2009-06-17 00:22:09 +01:00
Andy Wingo
b7393ea123 refactoring for toplevel-ref, toplevel-set, link-now
* libguile/vm-i-system.c (toplevel-ref, toplevel-set)
* libguile/vm-i-loader.c (link-now):
* libguile/vm.c (resolve_variable): Factor out common code to a static
  method. The compiler can still inline it, so it shouldn't have a
  significant performance effect.

* libguile/vm-engine.c (vm_error_no_such_module): Remove now-unused
  label.
2009-06-05 11:47:19 +02:00
Andy Wingo
560b9c256d adjust VM copyright notices to LGPL, use SCM_INTERNAL/API properly
* libguile/frames.c:
* libguile/frames.h:
* libguile/instructions.c:
* libguile/instructions.h:
* libguile/objcodes.c:
* libguile/objcodes.h:
* libguile/programs.c:
* libguile/programs.h:
* libguile/vm-bootstrap.h:
* libguile/vm-engine.c:
* libguile/vm-engine.h:
* libguile/vm-expand.h:
* libguile/vm-i-scheme.c:
* libguile/vm.c:
* libguile/vm.h: Update to use SCM_API and SCM_INTERNAL correctly. Adjust
  copyright to be the same as the copyright of Guile itself, which should
  be fine given that the FSF holds the whole thing.
2009-05-26 22:23:44 +02:00
Ludovic Courtès
da8b47478e Avoid uses of deprecated forms in the VM code.
Reported by Daniel Kraft <d@domob.eu>.

* libguile/frames.c, libguile/vm.c: Include <stdlib.h>, use `size_t'
  instead of `scm_sizet'.

* libguile/objcodes.c, libguile/programs.c, libguile/vm-engine.c,
  libguile/vm-i-loader.c, libguile/vm-i-system.c: Use `scm_list_X ()'
  instead of the deprecated `SCM_LISTX ()'.
2009-04-05 20:15:11 +02:00
Andy Wingo
aeeff258c6 non-srcdir build fixes
* guile-tools.in: Fix the checks to account for non-srcdir builds.

* libguile/frames.c:
* libguile/objcodes.c:
* libguile/programs.c:
* libguile/instructions.c:
* libguile/vm.c: Fix snarf-includes to cope with non-srcdir builds.

* libguile/instructions.h:
* libguile/instructions.c: Fix the stubs inclusion to be non-srcdir
  compatible.

* libguile/vm-expand.h (VM_DEFINE_INSTRUCTION): Fix some things so as not
  to require the instructions.h defintitions, since we have the codes
  already. Not important tho :)

* pre-inst-guile-env.in: Minor tweak that should have no effect.

* test-suite/standalone/Makefile.am (all-local): Remove a chmod +x step,
  the configure.ac rule should do that if necessary.
2009-03-17 16:47:55 +01:00
Andy Wingo
2f9769b60c fix the ping-pong between evaluator and vm stacks in make-stack
* libguile/frames.c (vm_frame_print): Add a frame printer.

* libguile/stacks.c (stack_depth, read_frames): Only switch the VM stack
  for boot program dframes.

* libguile/vm-engine.c (VM_NAME): Push one debug frame per invocation,
  unconditionally. (If we push them at all, of course.)
2009-02-05 18:13:27 +01:00
Andy Wingo
e06e857c8d in debug mode, make sure that calls to the vm can be captured via make-stack
* libguile/vm-engine.c (VM_PUSH_DEBUG_FRAMES): New knob, if true we much
  with the scm_i_last_debug_frame when entering the VM, because sometimes
  the evaluator doesn't do it for us.
  (VM_ENGINE): Plug through debug frame fondling. Now, program exit comes
  back to the main text. Rename err_args to finish_args, and reuse for
  the return value.

* libguile/vm-engine.h (PUSH_LIST):
* libguile/vm-i-loader.c:
* libguile/vm-i-scheme.c:
* libguile/vm-i-system.c: Update for finish_args.
  (halt): goto vm_done, now, instead of returning directly.
2009-02-05 12:28:19 +01:00
Andy Wingo
6d14383e86 enable multiple vm engines (regular, debug, ...)
* libguile/vm-engine.c (VM_USE_HOOKS, VM_USE_CLOCK, VM_CHECK_EXTERNAL)
  (VM_CHECK_OBJECT): Update to define these here, before including
  vm-engine.h.
  (vm_run): Change so that we can make different engines. Also, we take
  an array of arguments, and the struct scm_vm directly, so as to avoid
  any need to cons.

* libguile/vm-engine.h (CHECK_EXTERNAL, CHECK_OBJECT): Add some UNLIKELY
  bits; don't seem to help.

* libguile/vm.c (vm_dispatch_hook): Change to not pass the VP. This needs
  some love, and perhaps we revert to the old way.
  (VM_ENGINE): Actually make two engines, vm_regular_engine and
  vm_debug_engine. Probably there is room for improvement here. Actually
  their speeds are the same at the moment.
  (make_vm): Choose which engine to run; currently the debug engine by
  default.
  (scm_c_vm_run): A thin wrapper to invoke a VM without consing.
  (scm_vm_apply): Use scm_c_vm_run.
  (scm_load_compiled_with_vm): Use scm_c_vm_run.
2009-02-04 23:47:56 +01:00
Andy Wingo
747a163532 make catch cache and restore vm regs, not the vm itself -- speedy speedy
* libguile/throw.c (scm_c_catch): Stash away the current vm's regs, and
  restore them if there's a nonlocal exit. There is a terrible case we
  have to handle if we catch from when the vm smob type isn't registered
  but the throw has the vm registered, but I think we handle this fine.

* libguile/vm-engine.c (vm_run):
* libguile/vm-i-system.c (halt): Don't make a dynwind context, so that
  entering the VM doesn't cons at all, except for the arg list. Maybe we
  can fix that bit too.

* libguile/vm.c (vm_reset_stack): Remove, as there is no more dynwind.
  (make_vm): Return #f if the tc16 hasn't yet been registered.
2009-02-04 00:09:38 +01:00