]> gitweb.factorcode.org Git - factor.git/blob - vm/errors.cpp
e1266cf60892f70dc881c34f83ad913a4a86142e
[factor.git] / vm / errors.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 /* Global variables used to pass fault handler state from signal handler to
7 user-space */
8 cell signal_number;
9 cell signal_fault_addr;
10 unsigned int signal_fpu_status;
11 stack_frame *signal_callstack_top;
12
13 void factorvm::out_of_memory()
14 {
15         print_string("Out of memory\n\n");
16         dump_generations();
17         exit(1);
18 }
19
20 void out_of_memory()
21 {
22         return vm->out_of_memory();
23 }
24
25 void factorvm::fatal_error(const char* msg, cell tagged)
26 {
27         print_string("fatal_error: "); print_string(msg);
28         print_string(": "); print_cell_hex(tagged); nl();
29         exit(1);
30 }
31
32 void fatal_error(const char* msg, cell tagged)
33 {
34         return vm->fatal_error(msg,tagged);
35 }
36
37 void factorvm::critical_error(const char* msg, cell tagged)
38 {
39         print_string("You have triggered a bug in Factor. Please report.\n");
40         print_string("critical_error: "); print_string(msg);
41         print_string(": "); print_cell_hex(tagged); nl();
42         factorbug();
43 }
44
45 void critical_error(const char* msg, cell tagged)
46 {
47         return vm->critical_error(msg,tagged);
48 }
49
50 void factorvm::throw_error(cell error, stack_frame *callstack_top)
51 {
52         /* If the error handler is set, we rewind any C stack frames and
53         pass the error to user-space. */
54         if(userenv[BREAK_ENV] != F)
55         {
56                 /* If error was thrown during heap scan, we re-enable the GC */
57                 gc_off = false;
58
59                 /* Reset local roots */
60                 gc_locals.clear();
61                 gc_bignums.clear();
62
63                 /* If we had an underflow or overflow, stack pointers might be
64                 out of bounds */
65                 fix_stacks();
66
67                 dpush(error);
68
69                 /* Errors thrown from C code pass NULL for this parameter.
70                 Errors thrown from Factor code, or signal handlers, pass the
71                 actual stack pointer at the time, since the saved pointer is
72                 not necessarily up to date at that point. */
73                 if(callstack_top)
74                 {
75                         callstack_top = fix_callstack_top(callstack_top,
76                                 stack_chain->callstack_bottom);
77                 }
78                 else
79                         callstack_top = stack_chain->callstack_top;
80
81                 throw_impl(userenv[BREAK_ENV],callstack_top,this);
82         }
83         /* Error was thrown in early startup before error handler is set, just
84         crash. */
85         else
86         {
87                 print_string("You have triggered a bug in Factor. Please report.\n");
88                 print_string("early_error: ");
89                 print_obj(error);
90                 nl();
91                 factorbug();
92         }
93 }
94
95 void factorvm::general_error(vm_error_type error, cell arg1, cell arg2, stack_frame *callstack_top)
96 {
97         throw_error(allot_array_4(userenv[ERROR_ENV],
98                 tag_fixnum(error),arg1,arg2),callstack_top);
99 }
100
101 void general_error(vm_error_type error, cell arg1, cell arg2, stack_frame *callstack_top)
102 {
103         return vm->general_error(error,arg1,arg2,callstack_top);
104 }
105
106 void factorvm::type_error(cell type, cell tagged)
107 {
108         general_error(ERROR_TYPE,tag_fixnum(type),tagged,NULL);
109 }
110
111 void factorvm::not_implemented_error()
112 {
113         general_error(ERROR_NOT_IMPLEMENTED,F,F,NULL);
114 }
115
116 void not_implemented_error()
117 {
118         return vm->not_implemented_error();
119 }
120
121 /* Test if 'fault' is in the guard page at the top or bottom (depending on
122 offset being 0 or -1) of area+area_size */
123 bool factorvm::in_page(cell fault, cell area, cell area_size, int offset)
124 {
125         int pagesize = getpagesize();
126         area += area_size;
127         area += offset * pagesize;
128
129         return fault >= area && fault <= area + pagesize;
130 }
131
132 void factorvm::memory_protection_error(cell addr, stack_frame *native_stack)
133 {
134         if(in_page(addr, ds_bot, 0, -1))
135                 general_error(ERROR_DS_UNDERFLOW,F,F,native_stack);
136         else if(in_page(addr, ds_bot, ds_size, 0))
137                 general_error(ERROR_DS_OVERFLOW,F,F,native_stack);
138         else if(in_page(addr, rs_bot, 0, -1))
139                 general_error(ERROR_RS_UNDERFLOW,F,F,native_stack);
140         else if(in_page(addr, rs_bot, rs_size, 0))
141                 general_error(ERROR_RS_OVERFLOW,F,F,native_stack);
142         else if(in_page(addr, nursery.end, 0, 0))
143                 critical_error("allot_object() missed GC check",0);
144         else
145                 general_error(ERROR_MEMORY,allot_cell(addr),F,native_stack);
146 }
147
148 void factorvm::signal_error(int signal, stack_frame *native_stack)
149 {
150         general_error(ERROR_SIGNAL,tag_fixnum(signal),F,native_stack);
151 }
152
153 void factorvm::divide_by_zero_error()
154 {
155         general_error(ERROR_DIVIDE_BY_ZERO,F,F,NULL);
156 }
157
158 void divide_by_zero_error()
159 {
160         return vm->divide_by_zero_error();
161 }
162
163 void factorvm::fp_trap_error(unsigned int fpu_status, stack_frame *signal_callstack_top)
164 {
165         general_error(ERROR_FP_TRAP,tag_fixnum(fpu_status),F,signal_callstack_top);
166 }
167
168 inline void factorvm::vmprim_call_clear()
169 {
170         throw_impl(dpop(),stack_chain->callstack_bottom,this);
171 }
172
173 PRIMITIVE(call_clear)
174 {
175         PRIMITIVE_GETVM()->vmprim_call_clear();
176 }
177
178 /* For testing purposes */
179 inline void factorvm::vmprim_unimplemented()
180 {
181         not_implemented_error();
182 }
183
184 PRIMITIVE(unimplemented)
185 {
186         PRIMITIVE_GETVM()->vmprim_unimplemented();
187 }
188
189 void factorvm::memory_signal_handler_impl()
190 {
191         memory_protection_error(signal_fault_addr,signal_callstack_top);
192 }
193
194 void memory_signal_handler_impl()
195 {
196         return vm->memory_signal_handler_impl();
197 }
198
199 void factorvm::misc_signal_handler_impl()
200 {
201         signal_error(signal_number,signal_callstack_top);
202 }
203
204 void misc_signal_handler_impl()
205 {
206         vm->misc_signal_handler_impl();
207 }
208
209 void factorvm::fp_signal_handler_impl()
210 {
211         fp_trap_error(signal_fpu_status,signal_callstack_top);
212 }
213
214 void fp_signal_handler_impl()
215 {
216         vm->fp_signal_handler_impl();
217 }
218
219 }