OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdlib.h> | 5 #include <stdlib.h> |
6 | 6 |
7 #include <fstream> // NOLINT(readability/streams) | 7 #include <fstream> // NOLINT(readability/streams) |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/v8.h" | 10 #include "src/v8.h" |
(...skipping 818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
829 | 829 |
830 Object* Isolate::StackOverflow() { | 830 Object* Isolate::StackOverflow() { |
831 HandleScope scope(this); | 831 HandleScope scope(this); |
832 // At this point we cannot create an Error object using its javascript | 832 // At this point we cannot create an Error object using its javascript |
833 // constructor. Instead, we copy the pre-constructed boilerplate and | 833 // constructor. Instead, we copy the pre-constructed boilerplate and |
834 // attach the stack trace as a hidden property. | 834 // attach the stack trace as a hidden property. |
835 Handle<String> key = factory()->stack_overflow_string(); | 835 Handle<String> key = factory()->stack_overflow_string(); |
836 Handle<JSObject> boilerplate = Handle<JSObject>::cast( | 836 Handle<JSObject> boilerplate = Handle<JSObject>::cast( |
837 Object::GetProperty(js_builtins_object(), key).ToHandleChecked()); | 837 Object::GetProperty(js_builtins_object(), key).ToHandleChecked()); |
838 Handle<JSObject> exception = factory()->CopyJSObject(boilerplate); | 838 Handle<JSObject> exception = factory()->CopyJSObject(boilerplate); |
839 DoThrow(*exception, NULL); | 839 Throw(*exception, nullptr); |
840 | 840 |
841 CaptureAndSetSimpleStackTrace(exception, factory()->undefined_value()); | 841 CaptureAndSetSimpleStackTrace(exception, factory()->undefined_value()); |
842 return heap()->exception(); | 842 return heap()->exception(); |
843 } | 843 } |
844 | 844 |
845 | 845 |
846 Object* Isolate::TerminateExecution() { | 846 Object* Isolate::TerminateExecution() { |
847 DoThrow(heap_.termination_exception(), NULL); | 847 return Throw(heap_.termination_exception(), nullptr); |
848 return heap()->exception(); | |
849 } | 848 } |
850 | 849 |
851 | 850 |
852 void Isolate::CancelTerminateExecution() { | 851 void Isolate::CancelTerminateExecution() { |
853 if (try_catch_handler()) { | 852 if (try_catch_handler()) { |
854 try_catch_handler()->has_terminated_ = false; | 853 try_catch_handler()->has_terminated_ = false; |
855 } | 854 } |
856 if (has_pending_exception() && | 855 if (has_pending_exception() && |
857 pending_exception() == heap_.termination_exception()) { | 856 pending_exception() == heap_.termination_exception()) { |
858 thread_local_top()->external_caught_exception_ = false; | 857 thread_local_top()->external_caught_exception_ = false; |
(...skipping 24 matching lines...) Expand all Loading... |
883 entry = api_interrupts_queue_.front(); | 882 entry = api_interrupts_queue_.front(); |
884 api_interrupts_queue_.pop(); | 883 api_interrupts_queue_.pop(); |
885 } | 884 } |
886 VMState<EXTERNAL> state(this); | 885 VMState<EXTERNAL> state(this); |
887 HandleScope handle_scope(this); | 886 HandleScope handle_scope(this); |
888 entry.first(reinterpret_cast<v8::Isolate*>(this), entry.second); | 887 entry.first(reinterpret_cast<v8::Isolate*>(this), entry.second); |
889 } | 888 } |
890 } | 889 } |
891 | 890 |
892 | 891 |
| 892 void ReportBootstrappingException(Handle<Object> exception, |
| 893 MessageLocation* location) { |
| 894 base::OS::PrintError("Exception thrown during bootstrapping\n"); |
| 895 if (location == NULL || location->script().is_null()) return; |
| 896 // We are bootstrapping and caught an error where the location is set |
| 897 // and we have a script for the location. |
| 898 // In this case we could have an extension (or an internal error |
| 899 // somewhere) and we print out the line number at which the error occured |
| 900 // to the console for easier debugging. |
| 901 int line_number = |
| 902 location->script()->GetLineNumber(location->start_pos()) + 1; |
| 903 if (exception->IsString() && location->script()->name()->IsString()) { |
| 904 base::OS::PrintError( |
| 905 "Extension or internal compilation error: %s in %s at line %d.\n", |
| 906 String::cast(*exception)->ToCString().get(), |
| 907 String::cast(location->script()->name())->ToCString().get(), |
| 908 line_number); |
| 909 } else if (location->script()->name()->IsString()) { |
| 910 base::OS::PrintError( |
| 911 "Extension or internal compilation error in %s at line %d.\n", |
| 912 String::cast(location->script()->name())->ToCString().get(), |
| 913 line_number); |
| 914 } else { |
| 915 base::OS::PrintError("Extension or internal compilation error.\n"); |
| 916 } |
| 917 #ifdef OBJECT_PRINT |
| 918 // Since comments and empty lines have been stripped from the source of |
| 919 // builtins, print the actual source here so that line numbers match. |
| 920 if (location->script()->source()->IsString()) { |
| 921 Handle<String> src(String::cast(location->script()->source())); |
| 922 PrintF("Failing script:\n"); |
| 923 int len = src->length(); |
| 924 int line_number = 1; |
| 925 PrintF("%5d: ", line_number); |
| 926 for (int i = 0; i < len; i++) { |
| 927 uint16_t character = src->Get(i); |
| 928 PrintF("%c", character); |
| 929 if (character == '\n' && i < len - 2) { |
| 930 PrintF("%5d: ", ++line_number); |
| 931 } |
| 932 } |
| 933 } |
| 934 #endif |
| 935 } |
| 936 |
| 937 |
| 938 namespace { |
| 939 |
| 940 // Only use by Isolate::Throw for --abort-on-uncaught-exception. |
| 941 int fatal_exception_depth = 0; |
| 942 |
| 943 } // namespace |
| 944 |
| 945 |
893 Object* Isolate::Throw(Object* exception, MessageLocation* location) { | 946 Object* Isolate::Throw(Object* exception, MessageLocation* location) { |
894 DoThrow(exception, location); | 947 DCHECK(!has_pending_exception()); |
| 948 |
| 949 HandleScope scope(this); |
| 950 Handle<Object> exception_handle(exception, this); |
| 951 |
| 952 // Determine reporting and whether the exception is caught externally. |
| 953 bool catchable_by_javascript = is_catchable_by_javascript(exception); |
| 954 bool can_be_caught_externally = false; |
| 955 bool should_report_exception = |
| 956 ShouldReportException(&can_be_caught_externally, catchable_by_javascript); |
| 957 bool report_exception = catchable_by_javascript && should_report_exception; |
| 958 bool try_catch_needs_message = |
| 959 can_be_caught_externally && try_catch_handler()->capture_message_; |
| 960 bool rethrowing_message = thread_local_top()->rethrowing_message_; |
| 961 |
| 962 thread_local_top()->rethrowing_message_ = false; |
| 963 |
| 964 // Notify debugger of exception. |
| 965 if (catchable_by_javascript) { |
| 966 debug()->OnThrow(exception_handle, report_exception); |
| 967 } |
| 968 |
| 969 // Generate the message if required. |
| 970 if (!rethrowing_message && (report_exception || try_catch_needs_message)) { |
| 971 MessageLocation potential_computed_location; |
| 972 if (location == NULL) { |
| 973 // If no location was specified we use a computed one instead. |
| 974 ComputeLocation(&potential_computed_location); |
| 975 location = &potential_computed_location; |
| 976 } |
| 977 |
| 978 if (bootstrapper()->IsActive()) { |
| 979 // It's not safe to try to make message objects or collect stack traces |
| 980 // while the bootstrapper is active since the infrastructure may not have |
| 981 // been properly initialized. |
| 982 ReportBootstrappingException(exception_handle, location); |
| 983 } else { |
| 984 Handle<Object> message_obj = CreateMessage(exception_handle, location); |
| 985 |
| 986 thread_local_top()->pending_message_obj_ = *message_obj; |
| 987 thread_local_top()->pending_message_script_ = *location->script(); |
| 988 thread_local_top()->pending_message_start_pos_ = location->start_pos(); |
| 989 thread_local_top()->pending_message_end_pos_ = location->end_pos(); |
| 990 |
| 991 // If the abort-on-uncaught-exception flag is specified, abort on any |
| 992 // exception not caught by JavaScript, even when an external handler is |
| 993 // present. This flag is intended for use by JavaScript developers, so |
| 994 // print a user-friendly stack trace (not an internal one). |
| 995 if (fatal_exception_depth == 0 && FLAG_abort_on_uncaught_exception && |
| 996 (report_exception || can_be_caught_externally)) { |
| 997 fatal_exception_depth++; |
| 998 PrintF(stderr, "%s\n\nFROM\n", |
| 999 MessageHandler::GetLocalizedMessage(this, message_obj).get()); |
| 1000 PrintCurrentStackTrace(stderr); |
| 1001 base::OS::Abort(); |
| 1002 } |
| 1003 } |
| 1004 } |
| 1005 |
| 1006 // Save the message for reporting if the the exception remains uncaught. |
| 1007 thread_local_top()->has_pending_message_ = report_exception; |
| 1008 |
| 1009 // Do not forget to clean catcher_ if currently thrown exception cannot |
| 1010 // be caught. If necessary, ReThrow will update the catcher. |
| 1011 thread_local_top()->catcher_ = |
| 1012 can_be_caught_externally ? try_catch_handler() : NULL; |
| 1013 |
| 1014 set_pending_exception(*exception_handle); |
895 return heap()->exception(); | 1015 return heap()->exception(); |
896 } | 1016 } |
897 | 1017 |
898 | 1018 |
899 Object* Isolate::ReThrow(Object* exception) { | 1019 Object* Isolate::ReThrow(Object* exception) { |
900 bool can_be_caught_externally = false; | 1020 bool can_be_caught_externally = false; |
901 bool catchable_by_javascript = is_catchable_by_javascript(exception); | 1021 bool catchable_by_javascript = is_catchable_by_javascript(exception); |
902 ShouldReportException(&can_be_caught_externally, catchable_by_javascript); | 1022 ShouldReportException(&can_be_caught_externally, catchable_by_javascript); |
903 | 1023 |
904 thread_local_top()->catcher_ = can_be_caught_externally ? | 1024 thread_local_top()->catcher_ = can_be_caught_externally ? |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1114 !iter.IsAtEnd(); iter.Advance()) { | 1234 !iter.IsAtEnd(); iter.Advance()) { |
1115 if (iter.GetCurrent()->IsJSProxy()) return false; | 1235 if (iter.GetCurrent()->IsJSProxy()) return false; |
1116 if (JSObject::cast(iter.GetCurrent())->map()->GetConstructor() == | 1236 if (JSObject::cast(iter.GetCurrent())->map()->GetConstructor() == |
1117 *error_constructor) { | 1237 *error_constructor) { |
1118 return true; | 1238 return true; |
1119 } | 1239 } |
1120 } | 1240 } |
1121 return false; | 1241 return false; |
1122 } | 1242 } |
1123 | 1243 |
1124 static int fatal_exception_depth = 0; | |
1125 | |
1126 | 1244 |
1127 Handle<JSMessageObject> Isolate::CreateMessage(Handle<Object> exception, | 1245 Handle<JSMessageObject> Isolate::CreateMessage(Handle<Object> exception, |
1128 MessageLocation* location) { | 1246 MessageLocation* location) { |
1129 Handle<JSArray> stack_trace_object; | 1247 Handle<JSArray> stack_trace_object; |
1130 MessageLocation potential_computed_location; | 1248 MessageLocation potential_computed_location; |
1131 if (capture_stack_trace_for_uncaught_exceptions_) { | 1249 if (capture_stack_trace_for_uncaught_exceptions_) { |
1132 if (IsErrorObject(exception)) { | 1250 if (IsErrorObject(exception)) { |
1133 // We fetch the stack trace that corresponds to this error object. | 1251 // We fetch the stack trace that corresponds to this error object. |
1134 // If the lookup fails, the exception is probably not a valid Error | 1252 // If the lookup fails, the exception is probably not a valid Error |
1135 // object. In that case, we fall through and capture the stack trace | 1253 // object. In that case, we fall through and capture the stack trace |
(...skipping 29 matching lines...) Expand all Loading... |
1165 exception = | 1283 exception = |
1166 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("exception")); | 1284 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("exception")); |
1167 } | 1285 } |
1168 } | 1286 } |
1169 return MessageHandler::MakeMessageObject(this, "uncaught_exception", location, | 1287 return MessageHandler::MakeMessageObject(this, "uncaught_exception", location, |
1170 HandleVector<Object>(&exception, 1), | 1288 HandleVector<Object>(&exception, 1), |
1171 stack_trace_object); | 1289 stack_trace_object); |
1172 } | 1290 } |
1173 | 1291 |
1174 | 1292 |
1175 void ReportBootstrappingException(Handle<Object> exception, | |
1176 MessageLocation* location) { | |
1177 base::OS::PrintError("Exception thrown during bootstrapping\n"); | |
1178 if (location == NULL || location->script().is_null()) return; | |
1179 // We are bootstrapping and caught an error where the location is set | |
1180 // and we have a script for the location. | |
1181 // In this case we could have an extension (or an internal error | |
1182 // somewhere) and we print out the line number at which the error occured | |
1183 // to the console for easier debugging. | |
1184 int line_number = | |
1185 location->script()->GetLineNumber(location->start_pos()) + 1; | |
1186 if (exception->IsString() && location->script()->name()->IsString()) { | |
1187 base::OS::PrintError( | |
1188 "Extension or internal compilation error: %s in %s at line %d.\n", | |
1189 String::cast(*exception)->ToCString().get(), | |
1190 String::cast(location->script()->name())->ToCString().get(), | |
1191 line_number); | |
1192 } else if (location->script()->name()->IsString()) { | |
1193 base::OS::PrintError( | |
1194 "Extension or internal compilation error in %s at line %d.\n", | |
1195 String::cast(location->script()->name())->ToCString().get(), | |
1196 line_number); | |
1197 } else { | |
1198 base::OS::PrintError("Extension or internal compilation error.\n"); | |
1199 } | |
1200 #ifdef OBJECT_PRINT | |
1201 // Since comments and empty lines have been stripped from the source of | |
1202 // builtins, print the actual source here so that line numbers match. | |
1203 if (location->script()->source()->IsString()) { | |
1204 Handle<String> src(String::cast(location->script()->source())); | |
1205 PrintF("Failing script:\n"); | |
1206 int len = src->length(); | |
1207 int line_number = 1; | |
1208 PrintF("%5d: ", line_number); | |
1209 for (int i = 0; i < len; i++) { | |
1210 uint16_t character = src->Get(i); | |
1211 PrintF("%c", character); | |
1212 if (character == '\n' && i < len - 2) { | |
1213 PrintF("%5d: ", ++line_number); | |
1214 } | |
1215 } | |
1216 } | |
1217 #endif | |
1218 } | |
1219 | |
1220 | |
1221 void Isolate::DoThrow(Object* exception, MessageLocation* location) { | |
1222 DCHECK(!has_pending_exception()); | |
1223 | |
1224 HandleScope scope(this); | |
1225 Handle<Object> exception_handle(exception, this); | |
1226 | |
1227 // Determine reporting and whether the exception is caught externally. | |
1228 bool catchable_by_javascript = is_catchable_by_javascript(exception); | |
1229 bool can_be_caught_externally = false; | |
1230 bool should_report_exception = | |
1231 ShouldReportException(&can_be_caught_externally, catchable_by_javascript); | |
1232 bool report_exception = catchable_by_javascript && should_report_exception; | |
1233 bool try_catch_needs_message = | |
1234 can_be_caught_externally && try_catch_handler()->capture_message_; | |
1235 bool rethrowing_message = thread_local_top()->rethrowing_message_; | |
1236 | |
1237 thread_local_top()->rethrowing_message_ = false; | |
1238 | |
1239 // Notify debugger of exception. | |
1240 if (catchable_by_javascript) { | |
1241 debug()->OnThrow(exception_handle, report_exception); | |
1242 } | |
1243 | |
1244 // Generate the message if required. | |
1245 if (!rethrowing_message && (report_exception || try_catch_needs_message)) { | |
1246 MessageLocation potential_computed_location; | |
1247 if (location == NULL) { | |
1248 // If no location was specified we use a computed one instead. | |
1249 ComputeLocation(&potential_computed_location); | |
1250 location = &potential_computed_location; | |
1251 } | |
1252 | |
1253 if (bootstrapper()->IsActive()) { | |
1254 // It's not safe to try to make message objects or collect stack traces | |
1255 // while the bootstrapper is active since the infrastructure may not have | |
1256 // been properly initialized. | |
1257 ReportBootstrappingException(exception_handle, location); | |
1258 } else { | |
1259 Handle<Object> message_obj = CreateMessage(exception_handle, location); | |
1260 | |
1261 thread_local_top()->pending_message_obj_ = *message_obj; | |
1262 thread_local_top()->pending_message_script_ = *location->script(); | |
1263 thread_local_top()->pending_message_start_pos_ = location->start_pos(); | |
1264 thread_local_top()->pending_message_end_pos_ = location->end_pos(); | |
1265 | |
1266 // If the abort-on-uncaught-exception flag is specified, abort on any | |
1267 // exception not caught by JavaScript, even when an external handler is | |
1268 // present. This flag is intended for use by JavaScript developers, so | |
1269 // print a user-friendly stack trace (not an internal one). | |
1270 if (fatal_exception_depth == 0 && FLAG_abort_on_uncaught_exception && | |
1271 (report_exception || can_be_caught_externally)) { | |
1272 fatal_exception_depth++; | |
1273 PrintF(stderr, "%s\n\nFROM\n", | |
1274 MessageHandler::GetLocalizedMessage(this, message_obj).get()); | |
1275 PrintCurrentStackTrace(stderr); | |
1276 base::OS::Abort(); | |
1277 } | |
1278 } | |
1279 } | |
1280 | |
1281 // Save the message for reporting if the the exception remains uncaught. | |
1282 thread_local_top()->has_pending_message_ = report_exception; | |
1283 | |
1284 // Do not forget to clean catcher_ if currently thrown exception cannot | |
1285 // be caught. If necessary, ReThrow will update the catcher. | |
1286 thread_local_top()->catcher_ = can_be_caught_externally ? | |
1287 try_catch_handler() : NULL; | |
1288 | |
1289 set_pending_exception(*exception_handle); | |
1290 } | |
1291 | |
1292 | |
1293 bool Isolate::HasExternalTryCatch() { | 1293 bool Isolate::HasExternalTryCatch() { |
1294 DCHECK(has_pending_exception()); | 1294 DCHECK(has_pending_exception()); |
1295 | 1295 |
1296 return (thread_local_top()->catcher_ != NULL) && | 1296 return (thread_local_top()->catcher_ != NULL) && |
1297 (try_catch_handler() == thread_local_top()->catcher_); | 1297 (try_catch_handler() == thread_local_top()->catcher_); |
1298 } | 1298 } |
1299 | 1299 |
1300 | 1300 |
1301 bool Isolate::IsFinallyOnTop() { | 1301 bool Isolate::IsFinallyOnTop() { |
1302 // Get the address of the external handler so we can compare the address to | 1302 // Get the address of the external handler so we can compare the address to |
(...skipping 1248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2551 if (prev_ && prev_->Intercept(flag)) return true; | 2551 if (prev_ && prev_->Intercept(flag)) return true; |
2552 // Then check whether this scope intercepts. | 2552 // Then check whether this scope intercepts. |
2553 if ((flag & intercept_mask_)) { | 2553 if ((flag & intercept_mask_)) { |
2554 intercepted_flags_ |= flag; | 2554 intercepted_flags_ |= flag; |
2555 return true; | 2555 return true; |
2556 } | 2556 } |
2557 return false; | 2557 return false; |
2558 } | 2558 } |
2559 | 2559 |
2560 } } // namespace v8::internal | 2560 } } // namespace v8::internal |
OLD | NEW |