Chromium Code Reviews| 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 |