1/* Copyright JS Foundation and other contributors, http://js.foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16/**
17 * Implementation of exit with specified status code.
18 */
19
20#include "jmem.h"
21#include "jrt.h"
22#include "jrt-libc-includes.h"
23
24#ifdef _WIN32
25#  ifdef _WIN64
26#    define PRI_SIZET "lu"
27#    define MSG_SIZE_TYPE unsigned long
28#  else
29#    define PRI_SIZET "zu"
30#    define MSG_SIZE_TYPE size_t
31#  endif
32#else
33#  define PRI_SIZET "zu"
34#  define MSG_SIZE_TYPE size_t
35#endif
36
37#if defined (_WIN32) || defined (_WIN64) || !defined (JERRY_NDEBUG) || defined (__APPLE__)
38#if ENABLED (JERRY_MEM_STATS)
39static void
40jerry_dump_memstats_on_error (void)
41{
42  /* Dump memory stats */
43  jmem_heap_stats_t jmem_heap_stats;
44  jmem_heap_get_stats (&jmem_heap_stats);
45
46  JERRY_ERROR_MSG ("\tMemory info:\n");
47  JERRY_ERROR_MSG ("\theap total size: %"PRI_SIZET"\n", (MSG_SIZE_TYPE)(jmem_heap_stats.size));
48
49  JERRY_ERROR_MSG ("\tcurrently allocated bytes: %"PRI_SIZET"\n", (MSG_SIZE_TYPE)(jmem_heap_stats.allocated_bytes));
50  JERRY_ERROR_MSG ("\tpeak allocated bytes: %"PRI_SIZET"\n", (MSG_SIZE_TYPE)(jmem_heap_stats.peak_allocated_bytes));
51
52  JERRY_ERROR_MSG ("\tbytes waste due to blocks filled partially: %"PRI_SIZET"\n", (MSG_SIZE_TYPE)(jmem_heap_stats.waste_bytes));
53  JERRY_ERROR_MSG ("\tpeak wasted bytes: %"PRI_SIZET"\n", (MSG_SIZE_TYPE)(jmem_heap_stats.peak_waste_bytes));
54
55  JERRY_ERROR_MSG ("\tallocated memory for byte code: %"PRI_SIZET"\n", (MSG_SIZE_TYPE)(jmem_heap_stats.byte_code_bytes));
56  JERRY_ERROR_MSG ("\tpeak allocated memory for byte code: %"PRI_SIZET"\n", (MSG_SIZE_TYPE)(jmem_heap_stats.peak_byte_code_bytes));
57
58  JERRY_ERROR_MSG ("\tallocated memory for strings: %"PRI_SIZET"\n", (MSG_SIZE_TYPE)(jmem_heap_stats.string_bytes));
59  JERRY_ERROR_MSG ("\tpeak allocated memory for strings: %"PRI_SIZET"\n", (MSG_SIZE_TYPE)(jmem_heap_stats.peak_string_bytes));
60
61  JERRY_ERROR_MSG ("\tallocated memory for objects: %"PRI_SIZET"\n", (MSG_SIZE_TYPE)(jmem_heap_stats.object_bytes));
62  JERRY_ERROR_MSG ("\tpeak allocated memory for objects: %"PRI_SIZET"\n", (MSG_SIZE_TYPE)(jmem_heap_stats.peak_object_bytes));
63
64  JERRY_ERROR_MSG ("\tallocated memory for properties: %"PRI_SIZET"\n", (MSG_SIZE_TYPE)(jmem_heap_stats.property_bytes));
65  JERRY_ERROR_MSG ("\tpeak allocated memory for properties: %"PRI_SIZET"\n", (MSG_SIZE_TYPE)(jmem_heap_stats.peak_property_bytes));
66}
67#endif
68#endif /* Windows/Mac Or !defined (JERRY_NDEBUG) */
69
70/*
71 * Exit with specified status code.
72 *
73 * If !JERRY_NDEBUG and code != 0, print status code with description
74 * and call assertion fail handler.
75 */
76void JERRY_ATTR_NORETURN
77jerry_fatal (jerry_fatal_code_t code) /**< status code */
78{
79#if defined (_WIN32) || defined (_WIN64) || !defined (JERRY_NDEBUG) || defined (__APPLE__)
80  switch (code)
81  {
82    case ERR_OUT_OF_MEMORY:
83    {
84      JERRY_ERROR_MSG ("Error: ERR_OUT_OF_MEMORY\n");
85      break;
86    }
87    case ERR_REF_COUNT_LIMIT:
88    {
89      JERRY_ERROR_MSG ("Error: ERR_REF_COUNT_LIMIT\n");
90      break;
91    }
92    case ERR_UNTERMINATED_GC_LOOPS:
93    {
94      JERRY_ERROR_MSG ("Error: ERR_UNTERMINATED_GC_LOOPS\n");
95      break;
96    }
97    case ERR_DISABLED_BYTE_CODE:
98    {
99      JERRY_ERROR_MSG ("Error: ERR_DISABLED_BYTE_CODE\n");
100      break;
101    }
102    case ERR_FAILED_INTERNAL_ASSERTION:
103    {
104      JERRY_ERROR_MSG ("Error: ERR_FAILED_INTERNAL_ASSERTION\n");
105      break;
106    }
107    default:
108    {
109      JERRY_ERROR_MSG ("Error: ERR_UNKNOWN_FATAL\n");
110      break;
111    }
112  }
113
114#if ENABLED (JERRY_MEM_STATS)
115  jerry_dump_memstats_on_error ();
116#endif
117#endif /* Windows/Mac Or !defined (JERRY_NDEBUG) */
118
119  jerry_port_fatal (code);
120
121  /* to make compiler happy for some RTOS: 'control reaches end of non-void function' */
122  while (true)
123  {
124  }
125} /* jerry_fatal */
126
127#ifndef JERRY_NDEBUG
128/**
129 * Handle failed assertion
130 */
131void JERRY_ATTR_NORETURN
132jerry_assert_fail (const char *assertion, /**< assertion condition string */
133                   const char *file, /**< file name */
134                   const char *function, /**< function name */
135                   const uint32_t line) /**< line */
136{
137  JERRY_ERROR_MSG ("ICE: Assertion '%s' failed at %s(%s):%lu.\n",
138                   assertion,
139                   file,
140                   function,
141                   (unsigned long) line);
142
143  jerry_fatal (ERR_FAILED_INTERNAL_ASSERTION);
144} /* jerry_assert_fail */
145
146/**
147 * Handle execution of control path that should be unreachable
148 */
149void JERRY_ATTR_NORETURN
150jerry_unreachable (const char *file, /**< file name */
151                   const char *function, /**< function name */
152                   const uint32_t line) /**< line */
153{
154  JERRY_ERROR_MSG ("ICE: Unreachable control path at %s(%s):%lu was executed.\n",
155                   file,
156                   function,
157                   (unsigned long) line);
158
159  jerry_fatal (ERR_FAILED_INTERNAL_ASSERTION);
160} /* jerry_unreachable */
161#endif /* !JERRY_NDEBUG */
162