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