|
@@ -62,7 +62,7 @@ open EvalJitContext
|
|
|
let rec op_assign ctx jit e1 e2 = match e1.eexpr with
|
|
|
| TLocal var ->
|
|
|
let exec = jit_expr jit false e2 in
|
|
|
- if var.v_capture then emit_capture_write (get_capture_slot jit var.v_id) exec
|
|
|
+ if var.v_capture then emit_capture_write (get_capture_slot jit var) exec
|
|
|
else emit_local_write (get_slot jit var.v_id e1.epos) exec
|
|
|
| TField(ef,fa) ->
|
|
|
let name = hash (field_name fa) in
|
|
@@ -111,7 +111,7 @@ let rec op_assign ctx jit e1 e2 = match e1.eexpr with
|
|
|
and op_assign_op jit op e1 e2 prefix = match e1.eexpr with
|
|
|
| TLocal var ->
|
|
|
let exec = jit_expr jit false e2 in
|
|
|
- if var.v_capture then emit_capture_read_write (get_capture_slot jit var.v_id) exec op prefix
|
|
|
+ if var.v_capture then emit_capture_read_write (get_capture_slot jit var) exec op prefix
|
|
|
else emit_local_read_write (get_slot jit var.v_id e1.epos) exec op prefix
|
|
|
| TField(ef,fa) ->
|
|
|
let name = hash (field_name fa) in
|
|
@@ -221,14 +221,20 @@ and jit_expr jit return e =
|
|
|
emit_type_expr proto
|
|
|
| TFunction tf ->
|
|
|
let jit_closure = EvalJitContext.create ctx in
|
|
|
- jit_closure.captures <- jit.captures;
|
|
|
- jit_closure.capture_infos <- jit.capture_infos;
|
|
|
jit.num_closures <- jit.num_closures + 1;
|
|
|
- let exec = jit_tfunction jit_closure true e.epos tf in
|
|
|
- let num_captures = Hashtbl.length jit.captures in
|
|
|
+ let fl,exec = jit_tfunction jit_closure true e.epos tf in
|
|
|
let hasret = jit_closure.has_nonfinal_return in
|
|
|
- let get_env = get_env jit_closure false tf.tf_expr.epos.pfile (EKLocalFunction jit.num_closures) in
|
|
|
- emit_closure ctx num_captures get_env hasret exec
|
|
|
+ let eci = get_env_creation jit_closure false tf.tf_expr.epos.pfile (EKLocalFunction jit.num_closures) in
|
|
|
+ let captures = Hashtbl.fold (fun vid (i,declared) acc -> (i,vid,declared) :: acc) jit_closure.captures [] in
|
|
|
+ let captures = List.sort (fun (i1,_,_) (i2,_,_) -> Pervasives.compare i1 i2) captures in
|
|
|
+ (* Check if the out-of-scope var is in the outer scope because otherwise we have to promote outwards. *)
|
|
|
+ List.iter (fun var -> ignore(get_capture_slot jit var)) jit_closure.captures_outside_scope;
|
|
|
+ let captures = ExtList.List.filter_map (fun (i,vid,declared) ->
|
|
|
+ if declared then None
|
|
|
+ else Some (i,fst (try Hashtbl.find jit.captures vid with Not_found -> Error.error "Something went wrong" e.epos))
|
|
|
+ ) captures in
|
|
|
+ let mapping = Array.of_list captures in
|
|
|
+ emit_closure ctx mapping eci hasret exec fl
|
|
|
(* branching *)
|
|
|
| TIf(e1,e2,eo) ->
|
|
|
let exec_cond = jit_expr jit false e1 in
|
|
@@ -511,7 +517,7 @@ and jit_expr jit return e =
|
|
|
end
|
|
|
(* read *)
|
|
|
| TLocal var ->
|
|
|
- if var.v_capture then emit_capture_read (get_capture_slot jit var.v_id)
|
|
|
+ if var.v_capture then emit_capture_read (get_capture_slot jit var)
|
|
|
else emit_local_read (get_slot jit var.v_id e.epos)
|
|
|
| TField(e1,fa) ->
|
|
|
let name = hash (field_name fa) in
|
|
@@ -651,10 +657,13 @@ and jit_tfunction jit static pos tf =
|
|
|
push_scope jit pos;
|
|
|
(* Declare `this` (if not static) and function arguments as local variables. *)
|
|
|
if not static then ignore(declare_local_this jit);
|
|
|
- let varaccs = ExtList.List.filter_map (fun (var,_) ->
|
|
|
- let slot = add_local jit var in
|
|
|
- if var.v_capture then Some (slot,add_capture jit var) else None
|
|
|
+ let fl = List.map (fun (var,_) ->
|
|
|
+ let varacc = declare_local jit var in
|
|
|
+ match varacc with
|
|
|
+ | Env slot -> execute_set_capture slot
|
|
|
+ | Local slot -> execute_set_local slot
|
|
|
) tf.tf_args in
|
|
|
+ let fl = if static then fl else (execute_set_local 0) :: fl in
|
|
|
(* Add conditionals for default values. *)
|
|
|
let e = List.fold_left (fun e (v,cto) -> match cto with
|
|
|
| None -> e
|
|
@@ -672,33 +681,25 @@ and jit_tfunction jit static pos tf =
|
|
|
in
|
|
|
(* Jit the function expression. *)
|
|
|
let exec = jit_expr jit true e in
|
|
|
- (* Deal with captured arguments, if necessary. *)
|
|
|
- let exec = match varaccs with
|
|
|
- | [] -> exec
|
|
|
- | _ -> handle_capture_arguments exec varaccs
|
|
|
- in
|
|
|
pop_scope jit;
|
|
|
- exec
|
|
|
+ fl,exec
|
|
|
|
|
|
-and get_env jit static file info =
|
|
|
- let ctx = jit.ctx in
|
|
|
- let num_locals = jit.max_num_locals in
|
|
|
- let num_captures = Hashtbl.length jit.captures in
|
|
|
- let info = create_env_info static file info jit.capture_infos in
|
|
|
- match info.kind with
|
|
|
- | EKLocalFunction _ -> get_closure_env ctx info num_locals num_captures
|
|
|
- | _ -> get_normal_env ctx info num_locals num_captures
|
|
|
+and get_env_creation jit static file info = {
|
|
|
+ ec_info = create_env_info static file info jit.capture_infos;
|
|
|
+ ec_num_locals = jit.max_num_locals;
|
|
|
+ ec_num_captures = Hashtbl.length jit.captures;
|
|
|
+}
|
|
|
|
|
|
(* Creates a [EvalValue.vfunc] of function [tf], which can be [static] or not. *)
|
|
|
let jit_tfunction ctx key_type key_field tf static pos =
|
|
|
let t = Timer.timer [(if ctx.is_macro then "macro" else "interp");"jit"] in
|
|
|
(* Create a new JitContext with an initial scope *)
|
|
|
let jit = EvalJitContext.create ctx in
|
|
|
- let exec = jit_tfunction jit static pos tf in
|
|
|
+ let fl,exec = jit_tfunction jit static pos tf in
|
|
|
(* Create the [vfunc] instance depending on the number of arguments. *)
|
|
|
let hasret = jit.has_nonfinal_return in
|
|
|
- let get_env = get_env jit static tf.tf_expr.epos.pfile (EKMethod(key_type,key_field)) in
|
|
|
- let f = create_function ctx get_env hasret empty_array exec in
|
|
|
+ let eci = get_env_creation jit static tf.tf_expr.epos.pfile (EKMethod(key_type,key_field)) in
|
|
|
+ let f = if hasret then create_function ctx eci exec fl else create_function_noret ctx eci exec fl in
|
|
|
t();
|
|
|
f
|
|
|
|