| OLD | NEW |
| 1 // Copyright 2007-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2007-2008 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 18 matching lines...) Expand all Loading... |
| 29 | 29 |
| 30 #include "api.h" | 30 #include "api.h" |
| 31 #include "bootstrapper.h" | 31 #include "bootstrapper.h" |
| 32 #include "compiler.h" | 32 #include "compiler.h" |
| 33 #include "debug.h" | 33 #include "debug.h" |
| 34 #include "execution.h" | 34 #include "execution.h" |
| 35 #include "global-handles.h" | 35 #include "global-handles.h" |
| 36 #include "platform.h" | 36 #include "platform.h" |
| 37 #include "serialize.h" | 37 #include "serialize.h" |
| 38 #include "snapshot.h" | 38 #include "snapshot.h" |
| 39 #include "v8threads.h" |
| 39 | 40 |
| 40 | 41 |
| 41 namespace i = v8::internal; | 42 namespace i = v8::internal; |
| 42 #define LOG_API(expr) LOG(ApiEntryCall(expr)) | 43 #define LOG_API(expr) LOG(ApiEntryCall(expr)) |
| 43 | 44 |
| 44 | 45 |
| 45 namespace v8 { | 46 namespace v8 { |
| 46 | 47 |
| 47 | 48 |
| 48 #define ON_BAILOUT(location, code) \ | 49 #define ON_BAILOUT(location, code) \ |
| (...skipping 17 matching lines...) Expand all Loading... |
| 66 if (!thread_local.IgnoreOutOfMemory()) \ | 67 if (!thread_local.IgnoreOutOfMemory()) \ |
| 67 i::V8::FatalProcessOutOfMemory(NULL); \ | 68 i::V8::FatalProcessOutOfMemory(NULL); \ |
| 68 } \ | 69 } \ |
| 69 bool call_depth_is_zero = thread_local.CallDepthIsZero(); \ | 70 bool call_depth_is_zero = thread_local.CallDepthIsZero(); \ |
| 70 i::Top::optional_reschedule_exception(call_depth_is_zero); \ | 71 i::Top::optional_reschedule_exception(call_depth_is_zero); \ |
| 71 return value; \ | 72 return value; \ |
| 72 } \ | 73 } \ |
| 73 } while (false) | 74 } while (false) |
| 74 | 75 |
| 75 | 76 |
| 77 #define API_ENTRY_CHECK(msg) \ |
| 78 do { \ |
| 79 if (v8::Locker::IsActive()) { \ |
| 80 ApiCheck(i::ThreadManager::IsLockedByCurrentThread(), \ |
| 81 msg, \ |
| 82 "Entering the V8 API without proper locking in place"); \ |
| 83 } \ |
| 84 } while (false) |
| 85 |
| 76 // --- D a t a t h a t i s s p e c i f i c t o a t h r e a d --- | 86 // --- D a t a t h a t i s s p e c i f i c t o a t h r e a d --- |
| 77 | 87 |
| 78 | 88 |
| 79 static i::HandleScopeImplementer thread_local; | 89 static i::HandleScopeImplementer thread_local; |
| 80 | 90 |
| 81 | 91 |
| 82 // --- E x c e p t i o n B e h a v i o r --- | 92 // --- E x c e p t i o n B e h a v i o r --- |
| 83 | 93 |
| 84 | 94 |
| 85 static bool has_shut_down = false; | 95 static bool has_shut_down = false; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 | 193 |
| 184 static i::StringInputBuffer write_input_buffer; | 194 static i::StringInputBuffer write_input_buffer; |
| 185 | 195 |
| 186 | 196 |
| 187 static void EnsureInitialized(const char* location) { | 197 static void EnsureInitialized(const char* location) { |
| 188 if (IsDeadCheck(location)) return; | 198 if (IsDeadCheck(location)) return; |
| 189 ApiCheck(v8::V8::Initialize(), location, "Error initializing V8"); | 199 ApiCheck(v8::V8::Initialize(), location, "Error initializing V8"); |
| 190 } | 200 } |
| 191 | 201 |
| 192 | 202 |
| 203 ImplementationUtilities::HandleScopeData* |
| 204 ImplementationUtilities::CurrentHandleScope() { |
| 205 return &i::HandleScope::current_; |
| 206 } |
| 207 |
| 208 |
| 209 #ifdef DEBUG |
| 210 void ImplementationUtilities::ZapHandleRange(void** begin, void** end) { |
| 211 i::HandleScope::ZapRange(begin, end); |
| 212 } |
| 213 #endif |
| 214 |
| 215 |
| 193 v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() { | 216 v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() { |
| 194 if (IsDeadCheck("v8::Undefined()")) return v8::Handle<v8::Primitive>(); | 217 if (IsDeadCheck("v8::Undefined()")) return v8::Handle<v8::Primitive>(); |
| 195 EnsureInitialized("v8::Undefined()"); | 218 EnsureInitialized("v8::Undefined()"); |
| 196 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value())); | 219 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value())); |
| 197 } | 220 } |
| 198 | 221 |
| 199 | 222 |
| 200 v8::Handle<v8::Primitive> ImplementationUtilities::Null() { | 223 v8::Handle<v8::Primitive> ImplementationUtilities::Null() { |
| 201 if (IsDeadCheck("v8::Null()")) return v8::Handle<v8::Primitive>(); | 224 if (IsDeadCheck("v8::Null()")) return v8::Handle<v8::Primitive>(); |
| 202 EnsureInitialized("v8::Null()"); | 225 EnsureInitialized("v8::Null()"); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 | 375 |
| 353 void V8::DisposeGlobal(void** obj) { | 376 void V8::DisposeGlobal(void** obj) { |
| 354 LOG_API("DisposeGlobal"); | 377 LOG_API("DisposeGlobal"); |
| 355 if (has_shut_down) return; | 378 if (has_shut_down) return; |
| 356 i::GlobalHandles::Destroy(reinterpret_cast<i::Object**>(obj)); | 379 i::GlobalHandles::Destroy(reinterpret_cast<i::Object**>(obj)); |
| 357 } | 380 } |
| 358 | 381 |
| 359 // --- H a n d l e s --- | 382 // --- H a n d l e s --- |
| 360 | 383 |
| 361 | 384 |
| 362 HandleScope::Data HandleScope::current_ = { -1, NULL, NULL }; | 385 HandleScope::HandleScope() : is_closed_(false) { |
| 386 API_ENTRY_CHECK("HandleScope::HandleScope"); |
| 387 i::HandleScope::Enter(&previous_); |
| 388 } |
| 389 |
| 390 |
| 391 HandleScope::~HandleScope() { |
| 392 if (!is_closed_) { |
| 393 i::HandleScope::Leave(&previous_); |
| 394 } |
| 395 } |
| 363 | 396 |
| 364 | 397 |
| 365 int HandleScope::NumberOfHandles() { | 398 int HandleScope::NumberOfHandles() { |
| 366 int n = thread_local.Blocks()->length(); | 399 return i::HandleScope::NumberOfHandles(); |
| 367 if (n == 0) return 0; | |
| 368 return ((n - 1) * i::kHandleBlockSize) + | |
| 369 (current_.next - thread_local.Blocks()->last()); | |
| 370 } | 400 } |
| 371 | 401 |
| 372 | 402 |
| 373 void** v8::HandleScope::CreateHandle(void* value) { | 403 void** v8::HandleScope::CreateHandle(void* value) { |
| 374 void** result = current_.next; | 404 return i::HandleScope::CreateHandle(value); |
| 375 if (result == current_.limit) { | |
| 376 // Make sure there's at least one scope on the stack and that the | |
| 377 // top of the scope stack isn't a barrier. | |
| 378 if (!ApiCheck(current_.extensions >= 0, | |
| 379 "v8::HandleScope::CreateHandle()", | |
| 380 "Cannot create a handle without a HandleScope")) { | |
| 381 return NULL; | |
| 382 } | |
| 383 // If there's more room in the last block, we use that. This is used | |
| 384 // for fast creation of scopes after scope barriers. | |
| 385 if (!thread_local.Blocks()->is_empty()) { | |
| 386 void** limit = &thread_local.Blocks()->last()[i::kHandleBlockSize]; | |
| 387 if (current_.limit != limit) { | |
| 388 current_.limit = limit; | |
| 389 } | |
| 390 } | |
| 391 | |
| 392 // If we still haven't found a slot for the handle, we extend the | |
| 393 // current handle scope by allocating a new handle block. | |
| 394 if (result == current_.limit) { | |
| 395 // If there's a spare block, use it for growing the current scope. | |
| 396 result = thread_local.GetSpareOrNewBlock(); | |
| 397 // Add the extension to the global list of blocks, but count the | |
| 398 // extension as part of the current scope. | |
| 399 thread_local.Blocks()->Add(result); | |
| 400 current_.extensions++; | |
| 401 current_.limit = &result[i::kHandleBlockSize]; | |
| 402 } | |
| 403 } | |
| 404 | |
| 405 // Update the current next field, set the value in the created | |
| 406 // handle, and return the result. | |
| 407 ASSERT(result < current_.limit); | |
| 408 current_.next = result + 1; | |
| 409 *result = value; | |
| 410 return result; | |
| 411 } | 405 } |
| 412 | 406 |
| 413 | 407 |
| 414 void Context::Enter() { | 408 void Context::Enter() { |
| 415 if (IsDeadCheck("v8::Context::Enter()")) return; | 409 if (IsDeadCheck("v8::Context::Enter()")) return; |
| 416 i::Handle<i::Context> env = Utils::OpenHandle(this); | 410 i::Handle<i::Context> env = Utils::OpenHandle(this); |
| 417 thread_local.EnterContext(env); | 411 thread_local.EnterContext(env); |
| 418 | 412 |
| 419 thread_local.SaveContext(i::GlobalHandles::Create(i::Top::context())); | 413 thread_local.SaveContext(i::GlobalHandles::Create(i::Top::context())); |
| 420 i::Top::set_context(*env); | 414 i::Top::set_context(*env); |
| 421 } | 415 } |
| 422 | 416 |
| 423 | 417 |
| 424 void Context::Exit() { | 418 void Context::Exit() { |
| 425 if (has_shut_down) return; | 419 if (has_shut_down) return; |
| 426 if (!ApiCheck(thread_local.LeaveLastContext(), | 420 if (!ApiCheck(thread_local.LeaveLastContext(), |
| 427 "v8::Context::Exit()", | 421 "v8::Context::Exit()", |
| 428 "Cannot exit non-entered context")) { | 422 "Cannot exit non-entered context")) { |
| 429 return; | 423 return; |
| 430 } | 424 } |
| 431 | 425 |
| 432 // Content of 'last_context' could be NULL. | 426 // Content of 'last_context' could be NULL. |
| 433 i::Handle<i::Object> last_context = thread_local.RestoreContext(); | 427 i::Handle<i::Object> last_context = thread_local.RestoreContext(); |
| 434 i::Top::set_context(static_cast<i::Context*>(*last_context)); | 428 i::Top::set_context(static_cast<i::Context*>(*last_context)); |
| 435 i::GlobalHandles::Destroy(last_context.location()); | 429 i::GlobalHandles::Destroy(last_context.location()); |
| 436 } | 430 } |
| 437 | 431 |
| 438 | 432 |
| 439 void v8::HandleScope::DeleteExtensions() { | |
| 440 ASSERT(current_.extensions != 0); | |
| 441 thread_local.DeleteExtensions(current_.extensions); | |
| 442 } | |
| 443 | |
| 444 | |
| 445 void HandleScope::ZapRange(void** start, void** end) { | |
| 446 if (start == NULL) return; | |
| 447 for (void** p = start; p < end; p++) { | |
| 448 *p = reinterpret_cast<void*>(v8::internal::kHandleZapValue); | |
| 449 } | |
| 450 } | |
| 451 | |
| 452 | |
| 453 void** v8::HandleScope::RawClose(void** value) { | 433 void** v8::HandleScope::RawClose(void** value) { |
| 454 if (!ApiCheck(!is_closed_, | 434 if (!ApiCheck(!is_closed_, |
| 455 "v8::HandleScope::Close()", | 435 "v8::HandleScope::Close()", |
| 456 "Local scope has already been closed")) { | 436 "Local scope has already been closed")) { |
| 457 return 0; | 437 return 0; |
| 458 } | 438 } |
| 459 LOG_API("CloseHandleScope"); | 439 LOG_API("CloseHandleScope"); |
| 460 | 440 |
| 461 // Read the result before popping the handle block. | 441 // Read the result before popping the handle block. |
| 462 i::Object* result = reinterpret_cast<i::Object*>(*value); | 442 i::Object* result = reinterpret_cast<i::Object*>(*value); |
| 463 is_closed_ = true; | 443 is_closed_ = true; |
| 464 RestorePreviousState(); | 444 i::HandleScope::Leave(&previous_); |
| 465 | 445 |
| 466 // Allocate a new handle on the previous handle block. | 446 // Allocate a new handle on the previous handle block. |
| 467 i::Handle<i::Object> handle(result); | 447 i::Handle<i::Object> handle(result); |
| 468 return reinterpret_cast<void**>(handle.location()); | 448 return reinterpret_cast<void**>(handle.location()); |
| 469 } | 449 } |
| 470 | 450 |
| 471 | 451 |
| 472 // --- N e a n d e r --- | 452 // --- N e a n d e r --- |
| 473 | 453 |
| 474 | 454 |
| (...skipping 2469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2944 return &thread_local; | 2924 return &thread_local; |
| 2945 } | 2925 } |
| 2946 | 2926 |
| 2947 | 2927 |
| 2948 char* HandleScopeImplementer::ArchiveThread(char* storage) { | 2928 char* HandleScopeImplementer::ArchiveThread(char* storage) { |
| 2949 return thread_local.ArchiveThreadHelper(storage); | 2929 return thread_local.ArchiveThreadHelper(storage); |
| 2950 } | 2930 } |
| 2951 | 2931 |
| 2952 | 2932 |
| 2953 char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) { | 2933 char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) { |
| 2954 ImplementationUtilities::HandleScopeData* current = | 2934 v8::ImplementationUtilities::HandleScopeData* current = |
| 2955 ImplementationUtilities::CurrentHandleScope(); | 2935 v8::ImplementationUtilities::CurrentHandleScope(); |
| 2956 handle_scope_data_ = *current; | 2936 handle_scope_data_ = *current; |
| 2957 memcpy(storage, this, sizeof(*this)); | 2937 memcpy(storage, this, sizeof(*this)); |
| 2958 | 2938 |
| 2959 Initialize(); | 2939 Initialize(); |
| 2960 current->Initialize(); | 2940 current->Initialize(); |
| 2961 | 2941 |
| 2962 return storage + ArchiveSpacePerThread(); | 2942 return storage + ArchiveSpacePerThread(); |
| 2963 } | 2943 } |
| 2964 | 2944 |
| 2965 | 2945 |
| 2966 int HandleScopeImplementer::ArchiveSpacePerThread() { | 2946 int HandleScopeImplementer::ArchiveSpacePerThread() { |
| 2967 return sizeof(thread_local); | 2947 return sizeof(thread_local); |
| 2968 } | 2948 } |
| 2969 | 2949 |
| 2970 | 2950 |
| 2971 char* HandleScopeImplementer::RestoreThread(char* storage) { | 2951 char* HandleScopeImplementer::RestoreThread(char* storage) { |
| 2972 return thread_local.RestoreThreadHelper(storage); | 2952 return thread_local.RestoreThreadHelper(storage); |
| 2973 } | 2953 } |
| 2974 | 2954 |
| 2975 | 2955 |
| 2976 char* HandleScopeImplementer::RestoreThreadHelper(char* storage) { | 2956 char* HandleScopeImplementer::RestoreThreadHelper(char* storage) { |
| 2977 memcpy(this, storage, sizeof(*this)); | 2957 memcpy(this, storage, sizeof(*this)); |
| 2978 *ImplementationUtilities::CurrentHandleScope() = handle_scope_data_; | 2958 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_; |
| 2979 return storage + ArchiveSpacePerThread(); | 2959 return storage + ArchiveSpacePerThread(); |
| 2980 } | 2960 } |
| 2981 | 2961 |
| 2982 | 2962 |
| 2983 void HandleScopeImplementer::Iterate( | 2963 void HandleScopeImplementer::Iterate( |
| 2984 ObjectVisitor* v, | 2964 ObjectVisitor* v, |
| 2985 List<void**>* blocks, | 2965 List<void**>* blocks, |
| 2986 ImplementationUtilities::HandleScopeData* handle_data) { | 2966 v8::ImplementationUtilities::HandleScopeData* handle_data) { |
| 2987 // Iterate over all handles in the blocks except for the last. | 2967 // Iterate over all handles in the blocks except for the last. |
| 2988 for (int i = blocks->length() - 2; i >= 0; --i) { | 2968 for (int i = blocks->length() - 2; i >= 0; --i) { |
| 2989 Object** block = | 2969 Object** block = |
| 2990 reinterpret_cast<Object**>(blocks->at(i)); | 2970 reinterpret_cast<Object**>(blocks->at(i)); |
| 2991 v->VisitPointers(block, &block[kHandleBlockSize]); | 2971 v->VisitPointers(block, &block[kHandleBlockSize]); |
| 2992 } | 2972 } |
| 2993 | 2973 |
| 2994 // Iterate over live handles in the last block (if any). | 2974 // Iterate over live handles in the last block (if any). |
| 2995 if (!blocks->is_empty()) { | 2975 if (!blocks->is_empty()) { |
| 2996 v->VisitPointers(reinterpret_cast<Object**>(blocks->last()), | 2976 v->VisitPointers(reinterpret_cast<Object**>(blocks->last()), |
| 2997 reinterpret_cast<Object**>(handle_data->next)); | 2977 reinterpret_cast<Object**>(handle_data->next)); |
| 2998 } | 2978 } |
| 2999 } | 2979 } |
| 3000 | 2980 |
| 3001 | 2981 |
| 3002 void HandleScopeImplementer::Iterate(ObjectVisitor* v) { | 2982 void HandleScopeImplementer::Iterate(ObjectVisitor* v) { |
| 3003 ImplementationUtilities::HandleScopeData* current = | 2983 v8::ImplementationUtilities::HandleScopeData* current = |
| 3004 ImplementationUtilities::CurrentHandleScope(); | 2984 v8::ImplementationUtilities::CurrentHandleScope(); |
| 3005 Iterate(v, thread_local.Blocks(), current); | 2985 Iterate(v, thread_local.Blocks(), current); |
| 3006 } | 2986 } |
| 3007 | 2987 |
| 3008 | 2988 |
| 3009 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) { | 2989 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) { |
| 3010 HandleScopeImplementer* thread_local = | 2990 HandleScopeImplementer* thread_local = |
| 3011 reinterpret_cast<HandleScopeImplementer*>(storage); | 2991 reinterpret_cast<HandleScopeImplementer*>(storage); |
| 3012 List<void**>* blocks_of_archived_thread = thread_local->Blocks(); | 2992 List<void**>* blocks_of_archived_thread = thread_local->Blocks(); |
| 3013 ImplementationUtilities::HandleScopeData* handle_data_of_archived_thread = | 2993 v8::ImplementationUtilities::HandleScopeData* handle_data_of_archived_thread = |
| 3014 &thread_local->handle_scope_data_; | 2994 &thread_local->handle_scope_data_; |
| 3015 Iterate(v, blocks_of_archived_thread, handle_data_of_archived_thread); | 2995 Iterate(v, blocks_of_archived_thread, handle_data_of_archived_thread); |
| 3016 | 2996 |
| 3017 return storage + ArchiveSpacePerThread(); | 2997 return storage + ArchiveSpacePerThread(); |
| 3018 } | 2998 } |
| 3019 | 2999 |
| 3020 } } // namespace v8::internal | 3000 } } // namespace v8::internal |
| OLD | NEW |