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; | |
87 } | 83 } |
88 | 84 |
89 | 85 |
90 void ThreadLocalTop::InitializeInternal() { | 86 void ThreadLocalTop::InitializeInternal() { |
91 c_entry_fp_ = 0; | 87 c_entry_fp_ = 0; |
92 handler_ = 0; | 88 handler_ = 0; |
93 #ifdef USE_SIMULATOR | 89 #ifdef USE_SIMULATOR |
94 simulator_ = NULL; | 90 simulator_ = NULL; |
95 #endif | 91 #endif |
96 js_entry_sp_ = NULL; | 92 js_entry_sp_ = NULL; |
(...skipping 1169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 } | 1262 } |
1267 | 1263 |
1268 return true; | 1264 return true; |
1269 } | 1265 } |
1270 | 1266 |
1271 | 1267 |
1272 void Isolate::ReportPendingMessages() { | 1268 void Isolate::ReportPendingMessages() { |
1273 ASSERT(has_pending_exception()); | 1269 ASSERT(has_pending_exception()); |
1274 PropagatePendingExceptionToExternalTryCatch(); | 1270 PropagatePendingExceptionToExternalTryCatch(); |
1275 | 1271 |
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. | |
1280 HandleScope scope(this); | 1272 HandleScope scope(this); |
1281 if (thread_local_top_.pending_exception_->IsOutOfMemory()) { | 1273 if (thread_local_top_.pending_exception_ == |
1282 context()->mark_out_of_memory(); | |
1283 } else if (thread_local_top_.pending_exception_ == | |
1284 heap()->termination_exception()) { | 1274 heap()->termination_exception()) { |
1285 // Do nothing: if needed, the exception has been already propagated to | 1275 // Do nothing: if needed, the exception has been already propagated to |
1286 // v8::TryCatch. | 1276 // v8::TryCatch. |
1287 } else { | 1277 } else { |
1288 if (thread_local_top_.has_pending_message_) { | 1278 if (thread_local_top_.has_pending_message_) { |
1289 thread_local_top_.has_pending_message_ = false; | 1279 thread_local_top_.has_pending_message_ = false; |
1290 if (!thread_local_top_.pending_message_obj_->IsTheHole()) { | 1280 if (!thread_local_top_.pending_message_obj_->IsTheHole()) { |
1291 HandleScope scope(this); | 1281 HandleScope scope(this); |
1292 Handle<Object> message_obj(thread_local_top_.pending_message_obj_, | 1282 Handle<Object> message_obj(thread_local_top_.pending_message_obj_, |
1293 this); | 1283 this); |
(...skipping 10 matching lines...) Expand all Loading... |
1304 } | 1294 } |
1305 } | 1295 } |
1306 } | 1296 } |
1307 clear_pending_message(); | 1297 clear_pending_message(); |
1308 } | 1298 } |
1309 | 1299 |
1310 | 1300 |
1311 MessageLocation Isolate::GetMessageLocation() { | 1301 MessageLocation Isolate::GetMessageLocation() { |
1312 ASSERT(has_pending_exception()); | 1302 ASSERT(has_pending_exception()); |
1313 | 1303 |
1314 if (!thread_local_top_.pending_exception_->IsOutOfMemory() && | 1304 if (thread_local_top_.pending_exception_ != heap()->termination_exception() && |
1315 thread_local_top_.pending_exception_ != heap()->termination_exception() && | |
1316 thread_local_top_.has_pending_message_ && | 1305 thread_local_top_.has_pending_message_ && |
1317 !thread_local_top_.pending_message_obj_->IsTheHole() && | 1306 !thread_local_top_.pending_message_obj_->IsTheHole() && |
1318 !thread_local_top_.pending_message_obj_->IsTheHole()) { | 1307 !thread_local_top_.pending_message_obj_->IsTheHole()) { |
1319 Handle<Script> script( | 1308 Handle<Script> script( |
1320 Script::cast(thread_local_top_.pending_message_script_)); | 1309 Script::cast(thread_local_top_.pending_message_script_)); |
1321 int start_pos = thread_local_top_.pending_message_start_pos_; | 1310 int start_pos = thread_local_top_.pending_message_start_pos_; |
1322 int end_pos = thread_local_top_.pending_message_end_pos_; | 1311 int end_pos = thread_local_top_.pending_message_end_pos_; |
1323 return MessageLocation(script, start_pos, end_pos); | 1312 return MessageLocation(script, start_pos, end_pos); |
1324 } | 1313 } |
1325 | 1314 |
1326 return MessageLocation(); | 1315 return MessageLocation(); |
1327 } | 1316 } |
1328 | 1317 |
1329 | 1318 |
1330 bool Isolate::OptionalRescheduleException(bool is_bottom_call) { | 1319 bool Isolate::OptionalRescheduleException(bool is_bottom_call) { |
1331 ASSERT(has_pending_exception()); | 1320 ASSERT(has_pending_exception()); |
1332 PropagatePendingExceptionToExternalTryCatch(); | 1321 PropagatePendingExceptionToExternalTryCatch(); |
1333 | 1322 |
1334 // Always reschedule out of memory exceptions. | 1323 bool is_termination_exception = |
1335 if (!is_out_of_memory()) { | 1324 pending_exception() == heap_.termination_exception(); |
1336 bool is_termination_exception = | |
1337 pending_exception() == heap_.termination_exception(); | |
1338 | 1325 |
1339 // Do not reschedule the exception if this is the bottom call. | 1326 // Do not reschedule the exception if this is the bottom call. |
1340 bool clear_exception = is_bottom_call; | 1327 bool clear_exception = is_bottom_call; |
1341 | 1328 |
1342 if (is_termination_exception) { | 1329 if (is_termination_exception) { |
1343 if (is_bottom_call) { | 1330 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) { | |
1363 thread_local_top()->external_caught_exception_ = false; | 1331 thread_local_top()->external_caught_exception_ = false; |
1364 clear_pending_exception(); | 1332 clear_pending_exception(); |
1365 return false; | 1333 return false; |
1366 } | 1334 } |
| 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; |
1367 } | 1353 } |
1368 | 1354 |
1369 // Reschedule the exception. | 1355 // Reschedule the exception. |
1370 thread_local_top()->scheduled_exception_ = pending_exception(); | 1356 thread_local_top()->scheduled_exception_ = pending_exception(); |
1371 clear_pending_exception(); | 1357 clear_pending_exception(); |
1372 return true; | 1358 return true; |
1373 } | 1359 } |
1374 | 1360 |
1375 | 1361 |
1376 void Isolate::SetCaptureStackTraceForUncaughtExceptions( | 1362 void Isolate::SetCaptureStackTraceForUncaughtExceptions( |
1377 bool capture, | 1363 bool capture, |
1378 int frame_limit, | 1364 int frame_limit, |
1379 StackTrace::StackTraceOptions options) { | 1365 StackTrace::StackTraceOptions options) { |
1380 capture_stack_trace_for_uncaught_exceptions_ = capture; | 1366 capture_stack_trace_for_uncaught_exceptions_ = capture; |
1381 stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit; | 1367 stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit; |
1382 stack_trace_for_uncaught_exceptions_options_ = options; | 1368 stack_trace_for_uncaught_exceptions_options_ = options; |
1383 } | 1369 } |
1384 | 1370 |
1385 | 1371 |
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 | |
1403 Handle<Context> Isolate::native_context() { | 1372 Handle<Context> Isolate::native_context() { |
1404 return Handle<Context>(context()->global_object()->native_context()); | 1373 return Handle<Context>(context()->global_object()->native_context()); |
1405 } | 1374 } |
1406 | 1375 |
1407 | 1376 |
1408 Handle<Context> Isolate::global_context() { | 1377 Handle<Context> Isolate::global_context() { |
1409 return Handle<Context>(context()->global_object()->global_context()); | 1378 return Handle<Context>(context()->global_object()->global_context()); |
1410 } | 1379 } |
1411 | 1380 |
1412 | 1381 |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1844 | 1813 |
1845 | 1814 |
1846 void Isolate::PropagatePendingExceptionToExternalTryCatch() { | 1815 void Isolate::PropagatePendingExceptionToExternalTryCatch() { |
1847 ASSERT(has_pending_exception()); | 1816 ASSERT(has_pending_exception()); |
1848 | 1817 |
1849 bool external_caught = IsExternallyCaught(); | 1818 bool external_caught = IsExternallyCaught(); |
1850 thread_local_top_.external_caught_exception_ = external_caught; | 1819 thread_local_top_.external_caught_exception_ = external_caught; |
1851 | 1820 |
1852 if (!external_caught) return; | 1821 if (!external_caught) return; |
1853 | 1822 |
1854 if (thread_local_top_.pending_exception_->IsOutOfMemory()) { | 1823 if (thread_local_top_.pending_exception_ == |
1855 // Do not propagate OOM exception: we should kill VM asap. | |
1856 } else if (thread_local_top_.pending_exception_ == | |
1857 heap()->termination_exception()) { | 1824 heap()->termination_exception()) { |
1858 try_catch_handler()->can_continue_ = false; | 1825 try_catch_handler()->can_continue_ = false; |
1859 try_catch_handler()->has_terminated_ = true; | 1826 try_catch_handler()->has_terminated_ = true; |
1860 try_catch_handler()->exception_ = heap()->null_value(); | 1827 try_catch_handler()->exception_ = heap()->null_value(); |
1861 } else { | 1828 } else { |
1862 v8::TryCatch* handler = try_catch_handler(); | 1829 v8::TryCatch* handler = try_catch_handler(); |
1863 // At this point all non-object (failure) exceptions have | 1830 // At this point all non-object (failure) exceptions have |
1864 // been dealt with so this shouldn't fail. | 1831 // been dealt with so this shouldn't fail. |
1865 ASSERT(!pending_exception()->IsFailure()); | 1832 ASSERT(!pending_exception()->IsFailure()); |
1866 ASSERT(thread_local_top_.pending_message_obj_->IsJSMessageObject() || | 1833 ASSERT(thread_local_top_.pending_message_obj_->IsJSMessageObject() || |
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2323 | 2290 |
2324 #ifdef DEBUG | 2291 #ifdef DEBUG |
2325 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ | 2292 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ |
2326 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); | 2293 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); |
2327 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) | 2294 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) |
2328 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) | 2295 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) |
2329 #undef ISOLATE_FIELD_OFFSET | 2296 #undef ISOLATE_FIELD_OFFSET |
2330 #endif | 2297 #endif |
2331 | 2298 |
2332 } } // namespace v8::internal | 2299 } } // namespace v8::internal |
OLD | NEW |