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 |