1 #ifndef INTERPRET_H__
2 #define INTERPRET_H__ 1
3 
4 #include <setjmp.h>
5 #ifdef HAVE_SYS_TIME_H
6 #include <sys/time.h>
7 #endif
8 #include <time.h>
9 #include <sys/types.h>
10 
11 #include "driver.h"
12 #include "typedefs.h"
13 
14 #include "backend.h"
15 #include "bytecode.h"
16 #include "svalue.h"
17 
18 /* --- Types --- */
19 
20 /* --- struct control_stack: one control stack element
21  *
22  * Every structure describes the previous function call levels, the
23  * current function call data is kept in interpret's global variables..
24  * 'prog' is usually the same as ob->prog, except when
25  * executing inherited functions.
26  *
27  * TODO: The frames should have special flags to mark stuff like
28  * TODO:: sefun closures, closures, etc.
29  */
30 
31 struct control_stack {
32     object_t   *ob;         /* Current object */
33     object_t   *prev_ob;    /* Save previous object */
34     program_t  *prog;       /* Current program, NULL in the bottom entry */
35     svalue_t    lambda;     /* Current lambda, counted, or svalue-0 if none */
36     bytecode_p  pc;         /* Program counter, points to next bytecode */
37     svalue_t   *fp;         /* Frame pointer: first arg on stack */
38 #ifdef USE_NEW_INLINES
39     svalue_t   *context;    /* Context pointer */
40 #endif /* USE_NEW_INLINES */
41     bytecode_p  funstart;
42       /* Start of the function code.
43        * Two magic values (SIMUL_EFUN_FUNSTART and EFUN_FUNSTART) mark
44        * entries for simul-efun and efun closures.
45        */
46     int num_local_variables;    /* Number of local vars + arguments */
47     int function_index_offset;
48       /* Index of current program's function block within the functions of the
49        * current objects program (needed for inheritance).
50        */
51     svalue_t *current_variables;        /* Same */
52     int   extern_call;
53       /* TRUE if the call came from outside the object (call_others to
54        * oneself are a special case of this). Only entries with this flag
55        * set save the .ob and .prev_ob for the flagged and all previous
56        * unflagged entries.
57        * If the current this_object was changed, the 'imposter' object is
58        * stored in .pretend_to_be and this flag is or'ed with CS_PRETEND.
59        */
60 #   define CS_PRETEND 0x80
61     Bool  catch_call;
62       /* This is the 'faked' call context for the code inside a catch().
63        * Since the interpreter fakes a subroutine call for this, F_RETURN
64        * must be able to tell the contexts apart.
65        * (Right now the LPC compiler prohibits the use of 'return' inside
66        * of a catch, but providing it on this level already doesn't hurt).
67        */
68     int   instruction;
69       /* For EFUN_FUNSTART entries, this is the efun executed.
70        */
71 
72     bytecode_p *break_sp;
73       /* Points to address to branch to at next F_BREAK, which is also
74        * the actual bottom of the break stack.
75        */
76     object_t *pretend_to_be;
77       /* After set_this_object(), the this_object imposter.
78        * TODO: This should be mirrored in the current_object global variable,
79        * TODO:: to avoid accesses to wrong functions/variables.
80        */
81 #ifdef EVAL_COST_TRACE
82     int32 eval_cost;
83       /* The eval cost at that moment. */
84 #endif
85 };
86 
87 /* a general error handler structure. head is assigned as payload to an
88  * T_LVALUE svalue of type T_ERROR_HANDLER and pushed onto the value stack.
89  * If the stack is unrolled during runtime errors the error_handler function
90  * is called and frees buff. */
91 typedef struct errorhandler_s {
92   svalue_t head;        /* The T_ERROR_HANDLER structure */
93   char     * buff;      /* The allocated buffer to free. */
94 } errorhandler_t;
95 
96 
97 /* --- Constants --- */
98 
99 static const short MAX_SHIFT = (sizeof(p_int) << 3) - 1;
100   /* The maximally useful shift (left or right) of a number in LPC.
101    */
102 
103 /* --- Variables --- */
104 
105 extern program_t *current_prog;
106 extern int tracedepth;
107 extern int trace_level;
108 extern bytecode_p inter_pc;
109 extern struct control_stack *csp;
110 extern svalue_t * inter_sp;
111 extern int function_index_offset;
112 extern svalue_t *current_variables;
113 extern int32  eval_cost;
114 extern int32  assigned_eval_cost;
115 extern svalue_t apply_return_value;
116 extern svalue_t last_indexing_protector;
117 
118 #ifdef APPLY_CACHE_STAT
119 extern p_uint apply_cache_hit;
120 extern p_uint apply_cache_miss;
121 #endif
122 
123 extern p_uint eval_number;
124 extern unsigned long total_evalcost;
125 extern unsigned long last_total_evalcost;
126 extern struct timeval last_eval_duration;
127 extern statistic_t stat_total_evalcost;
128 extern statistic_t stat_eval_duration;
129 
130 /* --- Prototypes --- */
131 
132 extern void assign_eval_cost(void);
133 extern void mark_start_evaluation (void);
134 extern void mark_end_evaluation(void);
135 
136 extern Bool eval_instruction(bytecode_p first_instruction, svalue_t *initial_sp);
137 extern void free_string_svalue(svalue_t *v);
138 #ifdef USE_NEW_INLINES
139 extern void push_control_stack(svalue_t *sp, bytecode_p pc, svalue_t *fp, svalue_t *context);
140 #else
141 extern void push_control_stack(svalue_t *sp, bytecode_p pc, svalue_t *fp);
142 #endif /* USE_NEW_INLINES */
143 extern void pop_control_stack(void);
144 extern struct longjump_s *push_error_context(svalue_t *sp, int catch_flags);
145 extern void pop_error_context (void);
146 extern svalue_t *pull_error_context (svalue_t *sp, svalue_t *msg);
147 extern void transfer_error_message (svalue_t *v, rt_context_t *rt);
148 extern Bool destructed_object_ref (svalue_t *svp);
149 extern void free_object_svalue(svalue_t *v);
150 extern void zero_object_svalue(svalue_t *v);
151 extern void free_svalue(svalue_t *v);
152 extern void assign_svalue_no_free(svalue_t *to, svalue_t *from);
153 extern void assign_svalue(svalue_t *dest, svalue_t *v);
154 extern void copy_svalue_no_free (svalue_t *to, svalue_t *from);
155 extern void transfer_svalue_no_free(svalue_t *dest, svalue_t *v);
156 extern void transfer_svalue(svalue_t *dest, svalue_t *v);
157 
158 extern void put_c_string (svalue_t *sp, const char *p);
159 extern void put_c_n_string (svalue_t *sp, const char *p, size_t len);
160 
161 extern void push_svalue(svalue_t *v);
162 extern void push_svalue_block(int num, svalue_t *v);
163 extern svalue_t *pop_n_elems (int n, svalue_t *sp);
164 extern void pop_stack(void);
165 extern void push_apply_value(void);
166 extern void pop_apply_value (void);
167 extern void push_referenced_mapping(mapping_t *m);
168 extern svalue_t *push_error_handler(void (*errorhandler)(svalue_t *), svalue_t *arg);
169 extern void *xalloc_with_error_handler(size_t size);
170 
171 extern void init_interpret(void);
172 extern const char *typename(int type);
173 extern const char *efun_arg_typename (long type);
174 extern void vefun_bad_arg (int arg, svalue_t *sp) NORETURN;
175 extern void efun_gen_arg_error (int arg, int got, svalue_t *sp) NORETURN;
176 extern void vefun_gen_arg_error (int arg, int got, svalue_t *sp) NORETURN;
177 extern void efun_arg_error (int arg, int expected, int got, svalue_t *sp) NORETURN;
178 extern void efun_exp_arg_error (int arg, long expected, int got, svalue_t *sp) NORETURN;
179 extern void vefun_arg_error (int arg, int expected, int got, svalue_t *sp) NORETURN;
180 extern void vefun_exp_arg_error (int arg, long expected, int got, svalue_t *sp) NORETURN;
181 extern Bool privilege_violation(string_t *what, svalue_t *arg, svalue_t *sp);
182 extern Bool privilege_violation2(string_t *what, svalue_t *arg, svalue_t *arg2, svalue_t *sp);
183 extern Bool privilege_violation4(string_t *what, object_t *whom, string_t *how_str, int how_num, svalue_t *sp);
184 extern Bool privilege_violation_n(string_t *what, object_t *whom, svalue_t *sp, int num_arg);
185 
186 extern svalue_t *sapply_int(string_t *fun, object_t *ob, int num_arg, Bool b_ign_prot, Bool b_use_default);
187 #define sapply(f,o,n) sapply_int(f,o,n, MY_FALSE, MY_TRUE)
188 #define sapply_ign_prot(f,o,n) sapply_int(f,o,n, MY_TRUE, MY_TRUE)
189 extern svalue_t *apply(string_t *fun, object_t *ob, int num_arg);
190 extern void call_function(program_t *progp, int fx);
191 extern int get_line_number(bytecode_p p, program_t *progp, string_t **namep);
192 extern string_t *collect_trace(strbuf_t * sbuf, vector_t ** rvec);
193 extern string_t *dump_trace(Bool how, vector_t **rvec);
194 extern int get_line_number_if_any(string_t **name);
195 extern void reset_machine(Bool first);
196 extern void secure_apply_error(svalue_t *save_sp, struct control_stack *save_csp, Bool clear_costs);
197 extern svalue_t *secure_apply_ob(string_t *fun, object_t *ob, int num_arg, Bool external);
198 #define secure_apply(fun, ob, num_arg) secure_apply_ob(fun, ob, num_arg, MY_FALSE)
199 #define secure_callback(fun, ob, num_arg) secure_apply_ob(fun, ob, num_arg, MY_TRUE)
200 
201 extern svalue_t *apply_master_ob(string_t *fun, int num_arg, Bool external);
202 #define apply_master(fun, num_arg) apply_master_ob(fun, num_arg, MY_FALSE)
203 #define callback_master(fun, num_arg) apply_master_ob(fun, num_arg, MY_TRUE)
204 
205 extern void assert_master_ob_loaded(void);
206 extern svalue_t *secure_call_lambda(svalue_t *closure, int num_arg, Bool external);
207 #define secure_apply_lambda(fun, num_arg) secure_call_lambda(fun, num_arg, MY_FALSE)
208 #define secure_callback_lambda(fun, num_arg) secure_call_lambda(fun, num_arg, MY_TRUE)
209 
210 extern void remove_object_from_stack(object_t *ob);
211 extern void int_call_lambda(svalue_t *lsvp, int num_arg, Bool allowRefs, Bool external);
212 #define call_lambda(lsvp, num_arg) int_call_lambda(lsvp, num_arg, MY_FALSE, MY_TRUE)
213 extern inherit_t *adjust_variable_offsets(const inherit_t *inheritp, const program_t *prog, const object_t *obj);
214 extern void free_interpreter_temporaries(void);
215 extern void invalidate_apply_low_cache(void);
216 extern void m_indices_filter (svalue_t *key, svalue_t *data, void *extra);
217 extern void m_values_filter (svalue_t *key, svalue_t *data, void *extra);
218 extern void m_unmake_filter ( svalue_t *key, svalue_t *data, void *extra);
219 extern svalue_t *v_apply (svalue_t *sp, int num_arg);
220 extern svalue_t *v_funcall (svalue_t *sp, int num_arg);
221 extern svalue_t *v_call_direct_resolved (svalue_t *sp, int num_arg);
222 extern svalue_t *v_call_resolved (svalue_t *sp, int num_arg);
223 extern svalue_t *f_caller_stack_depth (svalue_t *sp);
224 extern svalue_t *f_caller_stack (svalue_t *sp);
225 extern svalue_t *f_get_eval_cost (svalue_t *sp);
226 extern svalue_t *f_previous_object (svalue_t *sp);
227 extern svalue_t *f_set_this_object (svalue_t *sp);
228 extern svalue_t *f_trace(svalue_t *sp);
229 extern svalue_t *f_traceprefix(svalue_t *sp);
230 
231 #ifdef OPCPROF
232 extern Bool opcdump(string_t *fname);
233 #endif
234 
235 #ifdef TRACE_CODE
236 extern svalue_t *f_last_instructions(svalue_t *sp);
237 extern int last_instructions(int length, Bool verbose, svalue_t **svpp);
238 #endif
239 
240 #ifdef DEBUG
241 extern int check_state(void);
242 extern void count_inherits(program_t *progp);
243 extern void count_extra_ref_in_object(object_t *ob);
244 extern void count_extra_ref_in_vector(svalue_t *svp, size_t num);
245 extern void check_a_lot_ref_counts(program_t *search_prog);
246 #endif
247 
248 extern size_t interpreter_overhead(void);
249 
250 #ifdef GC_SUPPORT
251 extern void clear_interpreter_refs(void);
252 extern void count_interpreter_refs(void);
253 #endif
254 
255 extern int  control_stack_depth(void);
256 
257 #endif /* INTERPRET_H__ */
258