Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(552)

Side by Side Diff: src/api.cc

Issue 18707: Split handle scopes into an internal version and a version accessible... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/api.h ('k') | src/apiutils.h » ('j') | src/apiutils.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/api.h ('k') | src/apiutils.h » ('j') | src/apiutils.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698