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 1029 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1040 !(Script::cast(script)->source()->IsUndefined())) { | 1040 !(Script::cast(script)->source()->IsUndefined())) { |
1041 int pos = frame->LookupCode()->SourcePosition(frame->pc()); | 1041 int pos = frame->LookupCode()->SourcePosition(frame->pc()); |
1042 // Compute the location from the function and the reloc info. | 1042 // Compute the location from the function and the reloc info. |
1043 Handle<Script> casted_script(Script::cast(script)); | 1043 Handle<Script> casted_script(Script::cast(script)); |
1044 *target = MessageLocation(casted_script, pos, pos + 1); | 1044 *target = MessageLocation(casted_script, pos, pos + 1); |
1045 } | 1045 } |
1046 } | 1046 } |
1047 } | 1047 } |
1048 | 1048 |
1049 | 1049 |
1050 void Isolate::ComputeLocationFromStackTrace(MessageLocation* target, | |
1051 Handle<Object> exception) { | |
1052 *target = MessageLocation(Handle<Script>(heap_.empty_script()), -1, -1); | |
1053 | |
1054 Handle<Name> key = factory()->stack_trace_symbol(); | |
1055 Handle<Object> property = JSObject::GetDataProperty(exception, key); | |
1056 if (!property->IsJSArray()) return; | |
1057 Handle<JSArray> simple_stack_trace = Handle<JSArray>::cast(property); | |
1058 | |
1059 Handle<FixedArray> elements(FixedArray::cast(simple_stack_trace->elements())); | |
1060 int elements_limit = Smi::cast(simple_stack_trace->length())->value(); | |
1061 | |
1062 for (int i = 1; i < elements_limit; i += 4) { | |
1063 Handle<JSFunction> fun = | |
1064 handle(JSFunction::cast(elements->get(i + 1)), this); | |
1065 if (fun->IsFromNativeScript()) continue; | |
1066 Handle<Code> code = handle(Code::cast(elements->get(i + 2)), this); | |
1067 Handle<Smi> offset = handle(Smi::cast(elements->get(i + 3)), this); | |
1068 Address pc = code->address() + offset->value(); | |
1069 | |
1070 Object* script = fun->shared()->script(); | |
1071 if (script->IsScript() && | |
1072 !(Script::cast(script)->source()->IsUndefined())) { | |
1073 int pos = code->SourcePosition(pc); | |
1074 Handle<Script> casted_script(Script::cast(script)); | |
1075 *target = MessageLocation(casted_script, pos, pos + 1); | |
1076 break; | |
1077 } | |
1078 } | |
1079 } | |
1080 | |
1081 | |
1050 bool Isolate::ShouldReportException(bool* can_be_caught_externally, | 1082 bool Isolate::ShouldReportException(bool* can_be_caught_externally, |
1051 bool catchable_by_javascript) { | 1083 bool catchable_by_javascript) { |
1052 // Find the top-most try-catch handler. | 1084 // Find the top-most try-catch handler. |
1053 StackHandler* handler = | 1085 StackHandler* handler = |
1054 StackHandler::FromAddress(Isolate::handler(thread_local_top())); | 1086 StackHandler::FromAddress(Isolate::handler(thread_local_top())); |
1055 while (handler != NULL && !handler->is_catch()) { | 1087 while (handler != NULL && !handler->is_catch()) { |
1056 handler = handler->next(); | 1088 handler = handler->next(); |
1057 } | 1089 } |
1058 | 1090 |
1059 // Get the address of the external handler so we can compare the address to | 1091 // Get the address of the external handler so we can compare the address to |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1099 } | 1131 } |
1100 return false; | 1132 return false; |
1101 } | 1133 } |
1102 | 1134 |
1103 static int fatal_exception_depth = 0; | 1135 static int fatal_exception_depth = 0; |
1104 | 1136 |
1105 | 1137 |
1106 Handle<JSMessageObject> Isolate::CreateMessage(Handle<Object> exception, | 1138 Handle<JSMessageObject> Isolate::CreateMessage(Handle<Object> exception, |
1107 MessageLocation* location) { | 1139 MessageLocation* location) { |
1108 Handle<JSArray> stack_trace_object; | 1140 Handle<JSArray> stack_trace_object; |
1141 MessageLocation potential_computed_location; | |
1109 if (capture_stack_trace_for_uncaught_exceptions_) { | 1142 if (capture_stack_trace_for_uncaught_exceptions_) { |
1110 if (IsErrorObject(exception)) { | 1143 if (IsErrorObject(exception)) { |
1111 // We fetch the stack trace that corresponds to this error object. | 1144 // We fetch the stack trace that corresponds to this error object. |
1112 // If the lookup fails, the exception is probably not a valid Error | 1145 // If the lookup fails, the exception is probably not a valid Error |
1113 // object. In that case, we fall through and capture the stack trace | 1146 // object. In that case, we fall through and capture the stack trace |
1114 // at this throw site. | 1147 // at this throw site. |
1115 stack_trace_object = | 1148 stack_trace_object = |
1116 GetDetailedStackTrace(Handle<JSObject>::cast(exception)); | 1149 GetDetailedStackTrace(Handle<JSObject>::cast(exception)); |
1150 if (!location) { | |
1151 ComputeLocationFromStackTrace(&potential_computed_location, exception); | |
1152 location = &potential_computed_location; | |
1153 } | |
1117 } | 1154 } |
1118 if (stack_trace_object.is_null()) { | 1155 if (stack_trace_object.is_null()) { |
1119 // Not an error object, we capture at throw site. | 1156 // Not an error object, we capture stack and location at throw site. |
1120 stack_trace_object = CaptureCurrentStackTrace( | 1157 stack_trace_object = CaptureCurrentStackTrace( |
1121 stack_trace_for_uncaught_exceptions_frame_limit_, | 1158 stack_trace_for_uncaught_exceptions_frame_limit_, |
1122 stack_trace_for_uncaught_exceptions_options_); | 1159 stack_trace_for_uncaught_exceptions_options_); |
1123 } | 1160 } |
1124 } | 1161 } |
1162 if (!location) { | |
1163 ComputeLocation(&potential_computed_location); | |
1164 location = &potential_computed_location; | |
1165 } | |
1125 | 1166 |
1126 // If the exception argument is a custom object, turn it into a string | 1167 // If the exception argument is a custom object, turn it into a string |
1127 // before throwing as uncaught exception. Note that the pending | 1168 // before throwing as uncaught exception. Note that the pending |
1128 // exception object to be set later must not be turned into a string. | 1169 // exception object to be set later must not be turned into a string. |
1129 if (exception->IsJSObject() && !IsErrorObject(exception)) { | 1170 if (exception->IsJSObject() && !IsErrorObject(exception)) { |
1130 MaybeHandle<Object> maybe_exception = | 1171 MaybeHandle<Object> maybe_exception = |
1131 Execution::ToDetailString(this, exception); | 1172 Execution::ToDetailString(this, exception); |
1132 if (!maybe_exception.ToHandle(&exception)) { | 1173 if (!maybe_exception.ToHandle(&exception)) { |
1133 exception = | 1174 exception = |
1134 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("exception")); | 1175 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("exception")); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1207 // Notify debugger of exception. | 1248 // Notify debugger of exception. |
1208 if (catchable_by_javascript) { | 1249 if (catchable_by_javascript) { |
1209 debug()->OnThrow(exception_handle, report_exception); | 1250 debug()->OnThrow(exception_handle, report_exception); |
1210 } | 1251 } |
1211 | 1252 |
1212 // Generate the message if required. | 1253 // Generate the message if required. |
1213 if (!rethrowing_message && (report_exception || try_catch_needs_message)) { | 1254 if (!rethrowing_message && (report_exception || try_catch_needs_message)) { |
1214 MessageLocation potential_computed_location; | 1255 MessageLocation potential_computed_location; |
1215 if (location == NULL) { | 1256 if (location == NULL) { |
1216 // If no location was specified we use a computed one instead. | 1257 // If no location was specified we use a computed one instead. |
1217 ComputeLocation(&potential_computed_location); | 1258 ComputeLocation(&potential_computed_location); |
Yang
2014/10/30 12:32:38
If you are going to compute the location in Create
aandrey
2014/10/30 12:47:11
But we need it below also to assign pending_messag
| |
1218 location = &potential_computed_location; | 1259 location = &potential_computed_location; |
1219 } | 1260 } |
1220 | 1261 |
1221 if (bootstrapper()->IsActive()) { | 1262 if (bootstrapper()->IsActive()) { |
1222 // It's not safe to try to make message objects or collect stack traces | 1263 // It's not safe to try to make message objects or collect stack traces |
1223 // while the bootstrapper is active since the infrastructure may not have | 1264 // while the bootstrapper is active since the infrastructure may not have |
1224 // been properly initialized. | 1265 // been properly initialized. |
1225 ReportBootstrappingException(exception_handle, location); | 1266 ReportBootstrappingException(exception_handle, location); |
1226 } else { | 1267 } else { |
1227 Handle<Object> message_obj = CreateMessage(exception_handle, location); | 1268 Handle<Object> message_obj = CreateMessage(exception_handle, location); |
1228 | 1269 |
1229 thread_local_top()->pending_message_obj_ = *message_obj; | 1270 thread_local_top()->pending_message_obj_ = *message_obj; |
1230 if (location != NULL) { | 1271 thread_local_top()->pending_message_script_ = *location->script(); |
Yang
2014/10/30 12:32:38
This can't work, if the location is &potential_com
aandrey
2014/10/30 12:47:11
The "location" variable here is not changed by Cre
aandrey
2014/10/30 12:47:11
The "location" variable here is not altered by Cre
| |
1231 thread_local_top()->pending_message_script_ = *location->script(); | 1272 thread_local_top()->pending_message_start_pos_ = location->start_pos(); |
1232 thread_local_top()->pending_message_start_pos_ = location->start_pos(); | 1273 thread_local_top()->pending_message_end_pos_ = location->end_pos(); |
1233 thread_local_top()->pending_message_end_pos_ = location->end_pos(); | |
1234 } | |
1235 | 1274 |
1236 // If the abort-on-uncaught-exception flag is specified, abort on any | 1275 // If the abort-on-uncaught-exception flag is specified, abort on any |
1237 // exception not caught by JavaScript, even when an external handler is | 1276 // exception not caught by JavaScript, even when an external handler is |
1238 // present. This flag is intended for use by JavaScript developers, so | 1277 // present. This flag is intended for use by JavaScript developers, so |
1239 // print a user-friendly stack trace (not an internal one). | 1278 // print a user-friendly stack trace (not an internal one). |
1240 if (fatal_exception_depth == 0 && FLAG_abort_on_uncaught_exception && | 1279 if (fatal_exception_depth == 0 && FLAG_abort_on_uncaught_exception && |
1241 (report_exception || can_be_caught_externally)) { | 1280 (report_exception || can_be_caught_externally)) { |
1242 fatal_exception_depth++; | 1281 fatal_exception_depth++; |
1243 PrintF(stderr, "%s\n\nFROM\n", | 1282 PrintF(stderr, "%s\n\nFROM\n", |
1244 MessageHandler::GetLocalizedMessage(this, message_obj).get()); | 1283 MessageHandler::GetLocalizedMessage(this, message_obj).get()); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1327 } | 1366 } |
1328 if (can_clear_message) clear_pending_message(); | 1367 if (can_clear_message) clear_pending_message(); |
1329 } | 1368 } |
1330 | 1369 |
1331 | 1370 |
1332 MessageLocation Isolate::GetMessageLocation() { | 1371 MessageLocation Isolate::GetMessageLocation() { |
1333 DCHECK(has_pending_exception()); | 1372 DCHECK(has_pending_exception()); |
1334 | 1373 |
1335 if (thread_local_top_.pending_exception_ != heap()->termination_exception() && | 1374 if (thread_local_top_.pending_exception_ != heap()->termination_exception() && |
1336 thread_local_top_.has_pending_message_ && | 1375 thread_local_top_.has_pending_message_ && |
1337 !thread_local_top_.pending_message_obj_->IsTheHole() && | |
1338 !thread_local_top_.pending_message_obj_->IsTheHole()) { | 1376 !thread_local_top_.pending_message_obj_->IsTheHole()) { |
1339 Handle<Script> script( | 1377 Handle<Script> script( |
1340 Script::cast(thread_local_top_.pending_message_script_)); | 1378 Script::cast(thread_local_top_.pending_message_script_)); |
1341 int start_pos = thread_local_top_.pending_message_start_pos_; | 1379 int start_pos = thread_local_top_.pending_message_start_pos_; |
1342 int end_pos = thread_local_top_.pending_message_end_pos_; | 1380 int end_pos = thread_local_top_.pending_message_end_pos_; |
1343 return MessageLocation(script, start_pos, end_pos); | 1381 return MessageLocation(script, start_pos, end_pos); |
1344 } | 1382 } |
1345 | 1383 |
1346 return MessageLocation(); | 1384 return MessageLocation(); |
1347 } | 1385 } |
(...skipping 1148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2496 if (prev_ && prev_->Intercept(flag)) return true; | 2534 if (prev_ && prev_->Intercept(flag)) return true; |
2497 // Then check whether this scope intercepts. | 2535 // Then check whether this scope intercepts. |
2498 if ((flag & intercept_mask_)) { | 2536 if ((flag & intercept_mask_)) { |
2499 intercepted_flags_ |= flag; | 2537 intercepted_flags_ |= flag; |
2500 return true; | 2538 return true; |
2501 } | 2539 } |
2502 return false; | 2540 return false; |
2503 } | 2541 } |
2504 | 2542 |
2505 } } // namespace v8::internal | 2543 } } // namespace v8::internal |
OLD | NEW |