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