OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 if (thread_id == 0) { | 73 if (thread_id == 0) { |
74 thread_id = AllocateThreadId(); | 74 thread_id = AllocateThreadId(); |
75 Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id); | 75 Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id); |
76 } | 76 } |
77 return thread_id; | 77 return thread_id; |
78 } | 78 } |
79 | 79 |
80 | 80 |
81 ThreadLocalTop::ThreadLocalTop() { | 81 ThreadLocalTop::ThreadLocalTop() { |
82 InitializeInternal(); | 82 InitializeInternal(); |
| 83 // This flag may be set using v8::V8::IgnoreOutOfMemoryException() |
| 84 // before an isolate is initialized. The initialize methods below do |
| 85 // not touch it to preserve its value. |
| 86 ignore_out_of_memory_ = false; |
83 } | 87 } |
84 | 88 |
85 | 89 |
86 void ThreadLocalTop::InitializeInternal() { | 90 void ThreadLocalTop::InitializeInternal() { |
87 c_entry_fp_ = 0; | 91 c_entry_fp_ = 0; |
88 handler_ = 0; | 92 handler_ = 0; |
89 #ifdef USE_SIMULATOR | 93 #ifdef USE_SIMULATOR |
90 simulator_ = NULL; | 94 simulator_ = NULL; |
91 #endif | 95 #endif |
92 js_entry_sp_ = NULL; | 96 js_entry_sp_ = NULL; |
(...skipping 1169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1262 } | 1266 } |
1263 | 1267 |
1264 return true; | 1268 return true; |
1265 } | 1269 } |
1266 | 1270 |
1267 | 1271 |
1268 void Isolate::ReportPendingMessages() { | 1272 void Isolate::ReportPendingMessages() { |
1269 ASSERT(has_pending_exception()); | 1273 ASSERT(has_pending_exception()); |
1270 PropagatePendingExceptionToExternalTryCatch(); | 1274 PropagatePendingExceptionToExternalTryCatch(); |
1271 | 1275 |
| 1276 // If the pending exception is OutOfMemoryException set out_of_memory in |
| 1277 // the native context. Note: We have to mark the native context here |
| 1278 // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to |
| 1279 // set it. |
1272 HandleScope scope(this); | 1280 HandleScope scope(this); |
1273 if (thread_local_top_.pending_exception_ == | 1281 if (thread_local_top_.pending_exception_->IsOutOfMemory()) { |
| 1282 context()->mark_out_of_memory(); |
| 1283 } else if (thread_local_top_.pending_exception_ == |
1274 heap()->termination_exception()) { | 1284 heap()->termination_exception()) { |
1275 // Do nothing: if needed, the exception has been already propagated to | 1285 // Do nothing: if needed, the exception has been already propagated to |
1276 // v8::TryCatch. | 1286 // v8::TryCatch. |
1277 } else { | 1287 } else { |
1278 if (thread_local_top_.has_pending_message_) { | 1288 if (thread_local_top_.has_pending_message_) { |
1279 thread_local_top_.has_pending_message_ = false; | 1289 thread_local_top_.has_pending_message_ = false; |
1280 if (!thread_local_top_.pending_message_obj_->IsTheHole()) { | 1290 if (!thread_local_top_.pending_message_obj_->IsTheHole()) { |
1281 HandleScope scope(this); | 1291 HandleScope scope(this); |
1282 Handle<Object> message_obj(thread_local_top_.pending_message_obj_, | 1292 Handle<Object> message_obj(thread_local_top_.pending_message_obj_, |
1283 this); | 1293 this); |
(...skipping 10 matching lines...) Expand all Loading... |
1294 } | 1304 } |
1295 } | 1305 } |
1296 } | 1306 } |
1297 clear_pending_message(); | 1307 clear_pending_message(); |
1298 } | 1308 } |
1299 | 1309 |
1300 | 1310 |
1301 MessageLocation Isolate::GetMessageLocation() { | 1311 MessageLocation Isolate::GetMessageLocation() { |
1302 ASSERT(has_pending_exception()); | 1312 ASSERT(has_pending_exception()); |
1303 | 1313 |
1304 if (thread_local_top_.pending_exception_ != heap()->termination_exception() && | 1314 if (!thread_local_top_.pending_exception_->IsOutOfMemory() && |
| 1315 thread_local_top_.pending_exception_ != heap()->termination_exception() && |
1305 thread_local_top_.has_pending_message_ && | 1316 thread_local_top_.has_pending_message_ && |
1306 !thread_local_top_.pending_message_obj_->IsTheHole() && | 1317 !thread_local_top_.pending_message_obj_->IsTheHole() && |
1307 !thread_local_top_.pending_message_obj_->IsTheHole()) { | 1318 !thread_local_top_.pending_message_obj_->IsTheHole()) { |
1308 Handle<Script> script( | 1319 Handle<Script> script( |
1309 Script::cast(thread_local_top_.pending_message_script_)); | 1320 Script::cast(thread_local_top_.pending_message_script_)); |
1310 int start_pos = thread_local_top_.pending_message_start_pos_; | 1321 int start_pos = thread_local_top_.pending_message_start_pos_; |
1311 int end_pos = thread_local_top_.pending_message_end_pos_; | 1322 int end_pos = thread_local_top_.pending_message_end_pos_; |
1312 return MessageLocation(script, start_pos, end_pos); | 1323 return MessageLocation(script, start_pos, end_pos); |
1313 } | 1324 } |
1314 | 1325 |
1315 return MessageLocation(); | 1326 return MessageLocation(); |
1316 } | 1327 } |
1317 | 1328 |
1318 | 1329 |
1319 bool Isolate::OptionalRescheduleException(bool is_bottom_call) { | 1330 bool Isolate::OptionalRescheduleException(bool is_bottom_call) { |
1320 ASSERT(has_pending_exception()); | 1331 ASSERT(has_pending_exception()); |
1321 PropagatePendingExceptionToExternalTryCatch(); | 1332 PropagatePendingExceptionToExternalTryCatch(); |
1322 | 1333 |
1323 bool is_termination_exception = | 1334 // Always reschedule out of memory exceptions. |
1324 pending_exception() == heap_.termination_exception(); | 1335 if (!is_out_of_memory()) { |
| 1336 bool is_termination_exception = |
| 1337 pending_exception() == heap_.termination_exception(); |
1325 | 1338 |
1326 // Do not reschedule the exception if this is the bottom call. | 1339 // Do not reschedule the exception if this is the bottom call. |
1327 bool clear_exception = is_bottom_call; | 1340 bool clear_exception = is_bottom_call; |
1328 | 1341 |
1329 if (is_termination_exception) { | 1342 if (is_termination_exception) { |
1330 if (is_bottom_call) { | 1343 if (is_bottom_call) { |
| 1344 thread_local_top()->external_caught_exception_ = false; |
| 1345 clear_pending_exception(); |
| 1346 return false; |
| 1347 } |
| 1348 } else if (thread_local_top()->external_caught_exception_) { |
| 1349 // If the exception is externally caught, clear it if there are no |
| 1350 // JavaScript frames on the way to the C++ frame that has the |
| 1351 // external handler. |
| 1352 ASSERT(thread_local_top()->try_catch_handler_address() != NULL); |
| 1353 Address external_handler_address = |
| 1354 thread_local_top()->try_catch_handler_address(); |
| 1355 JavaScriptFrameIterator it(this); |
| 1356 if (it.done() || (it.frame()->sp() > external_handler_address)) { |
| 1357 clear_exception = true; |
| 1358 } |
| 1359 } |
| 1360 |
| 1361 // Clear the exception if needed. |
| 1362 if (clear_exception) { |
1331 thread_local_top()->external_caught_exception_ = false; | 1363 thread_local_top()->external_caught_exception_ = false; |
1332 clear_pending_exception(); | 1364 clear_pending_exception(); |
1333 return false; | 1365 return false; |
1334 } | 1366 } |
1335 } else if (thread_local_top()->external_caught_exception_) { | |
1336 // If the exception is externally caught, clear it if there are no | |
1337 // JavaScript frames on the way to the C++ frame that has the | |
1338 // external handler. | |
1339 ASSERT(thread_local_top()->try_catch_handler_address() != NULL); | |
1340 Address external_handler_address = | |
1341 thread_local_top()->try_catch_handler_address(); | |
1342 JavaScriptFrameIterator it(this); | |
1343 if (it.done() || (it.frame()->sp() > external_handler_address)) { | |
1344 clear_exception = true; | |
1345 } | |
1346 } | |
1347 | |
1348 // Clear the exception if needed. | |
1349 if (clear_exception) { | |
1350 thread_local_top()->external_caught_exception_ = false; | |
1351 clear_pending_exception(); | |
1352 return false; | |
1353 } | 1367 } |
1354 | 1368 |
1355 // Reschedule the exception. | 1369 // Reschedule the exception. |
1356 thread_local_top()->scheduled_exception_ = pending_exception(); | 1370 thread_local_top()->scheduled_exception_ = pending_exception(); |
1357 clear_pending_exception(); | 1371 clear_pending_exception(); |
1358 return true; | 1372 return true; |
1359 } | 1373 } |
1360 | 1374 |
1361 | 1375 |
1362 void Isolate::SetCaptureStackTraceForUncaughtExceptions( | 1376 void Isolate::SetCaptureStackTraceForUncaughtExceptions( |
1363 bool capture, | 1377 bool capture, |
1364 int frame_limit, | 1378 int frame_limit, |
1365 StackTrace::StackTraceOptions options) { | 1379 StackTrace::StackTraceOptions options) { |
1366 capture_stack_trace_for_uncaught_exceptions_ = capture; | 1380 capture_stack_trace_for_uncaught_exceptions_ = capture; |
1367 stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit; | 1381 stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit; |
1368 stack_trace_for_uncaught_exceptions_options_ = options; | 1382 stack_trace_for_uncaught_exceptions_options_ = options; |
1369 } | 1383 } |
1370 | 1384 |
1371 | 1385 |
| 1386 bool Isolate::is_out_of_memory() { |
| 1387 if (has_pending_exception()) { |
| 1388 MaybeObject* e = pending_exception(); |
| 1389 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { |
| 1390 return true; |
| 1391 } |
| 1392 } |
| 1393 if (has_scheduled_exception()) { |
| 1394 MaybeObject* e = scheduled_exception(); |
| 1395 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { |
| 1396 return true; |
| 1397 } |
| 1398 } |
| 1399 return false; |
| 1400 } |
| 1401 |
| 1402 |
1372 Handle<Context> Isolate::native_context() { | 1403 Handle<Context> Isolate::native_context() { |
1373 return Handle<Context>(context()->global_object()->native_context()); | 1404 return Handle<Context>(context()->global_object()->native_context()); |
1374 } | 1405 } |
1375 | 1406 |
1376 | 1407 |
1377 Handle<Context> Isolate::global_context() { | 1408 Handle<Context> Isolate::global_context() { |
1378 return Handle<Context>(context()->global_object()->global_context()); | 1409 return Handle<Context>(context()->global_object()->global_context()); |
1379 } | 1410 } |
1380 | 1411 |
1381 | 1412 |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1813 | 1844 |
1814 | 1845 |
1815 void Isolate::PropagatePendingExceptionToExternalTryCatch() { | 1846 void Isolate::PropagatePendingExceptionToExternalTryCatch() { |
1816 ASSERT(has_pending_exception()); | 1847 ASSERT(has_pending_exception()); |
1817 | 1848 |
1818 bool external_caught = IsExternallyCaught(); | 1849 bool external_caught = IsExternallyCaught(); |
1819 thread_local_top_.external_caught_exception_ = external_caught; | 1850 thread_local_top_.external_caught_exception_ = external_caught; |
1820 | 1851 |
1821 if (!external_caught) return; | 1852 if (!external_caught) return; |
1822 | 1853 |
1823 if (thread_local_top_.pending_exception_ == | 1854 if (thread_local_top_.pending_exception_->IsOutOfMemory()) { |
| 1855 // Do not propagate OOM exception: we should kill VM asap. |
| 1856 } else if (thread_local_top_.pending_exception_ == |
1824 heap()->termination_exception()) { | 1857 heap()->termination_exception()) { |
1825 try_catch_handler()->can_continue_ = false; | 1858 try_catch_handler()->can_continue_ = false; |
1826 try_catch_handler()->has_terminated_ = true; | 1859 try_catch_handler()->has_terminated_ = true; |
1827 try_catch_handler()->exception_ = heap()->null_value(); | 1860 try_catch_handler()->exception_ = heap()->null_value(); |
1828 } else { | 1861 } else { |
1829 v8::TryCatch* handler = try_catch_handler(); | 1862 v8::TryCatch* handler = try_catch_handler(); |
1830 // At this point all non-object (failure) exceptions have | 1863 // At this point all non-object (failure) exceptions have |
1831 // been dealt with so this shouldn't fail. | 1864 // been dealt with so this shouldn't fail. |
1832 ASSERT(!pending_exception()->IsFailure()); | 1865 ASSERT(!pending_exception()->IsFailure()); |
1833 ASSERT(thread_local_top_.pending_message_obj_->IsJSMessageObject() || | 1866 ASSERT(thread_local_top_.pending_message_obj_->IsJSMessageObject() || |
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2290 | 2323 |
2291 #ifdef DEBUG | 2324 #ifdef DEBUG |
2292 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ | 2325 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ |
2293 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); | 2326 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); |
2294 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) | 2327 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) |
2295 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) | 2328 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) |
2296 #undef ISOLATE_FIELD_OFFSET | 2329 #undef ISOLATE_FIELD_OFFSET |
2297 #endif | 2330 #endif |
2298 | 2331 |
2299 } } // namespace v8::internal | 2332 } } // namespace v8::internal |
OLD | NEW |