1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_API_H_ 6 #define V8_API_H_ 7 8 #include "src/v8.h" 9 10 #include "include/v8-testing.h" 11 #include "src/contexts.h" 12 #include "src/factory.h" 13 #include "src/isolate.h" 14 #include "src/list-inl.h" 15 16 namespace v8 { 17 18 // Constants used in the implementation of the API. The most natural thing 19 // would usually be to place these with the classes that use them, but 20 // we want to keep them out of v8.h because it is an externally 21 // visible file. 22 class Consts { 23 public: 24 enum TemplateType { 25 FUNCTION_TEMPLATE = 0, 26 OBJECT_TEMPLATE = 1 27 }; 28 }; 29 30 31 // Utilities for working with neander-objects, primitive 32 // env-independent JSObjects used by the api. 33 class NeanderObject { 34 public: 35 explicit NeanderObject(v8::internal::Isolate* isolate, int size); 36 explicit inline NeanderObject(v8::internal::Handle<v8::internal::Object> obj); 37 explicit inline NeanderObject(v8::internal::Object* obj); 38 inline v8::internal::Object* get(int index); 39 inline void set(int index, v8::internal::Object* value); 40 inline v8::internal::Handle<v8::internal::JSObject> value() { return value_; } 41 int size(); 42 private: 43 v8::internal::Handle<v8::internal::JSObject> value_; 44 }; 45 46 47 // Utilities for working with neander-arrays, a simple extensible 48 // array abstraction built on neander-objects. 49 class NeanderArray { 50 public: 51 explicit NeanderArray(v8::internal::Isolate* isolate); 52 explicit inline NeanderArray(v8::internal::Handle<v8::internal::Object> obj); 53 inline v8::internal::Handle<v8::internal::JSObject> value() { 54 return obj_.value(); 55 } 56 57 void add(v8::internal::Handle<v8::internal::Object> value); 58 59 int length(); 60 61 v8::internal::Object* get(int index); 62 // Change the value at an index to undefined value. If the index is 63 // out of bounds, the request is ignored. Returns the old value. 64 void set(int index, v8::internal::Object* value); 65 private: 66 NeanderObject obj_; 67 }; 68 69 70 NeanderObject::NeanderObject(v8::internal::Handle<v8::internal::Object> obj) 71 : value_(v8::internal::Handle<v8::internal::JSObject>::cast(obj)) { } 72 73 74 NeanderObject::NeanderObject(v8::internal::Object* obj) 75 : value_(v8::internal::Handle<v8::internal::JSObject>( 76 v8::internal::JSObject::cast(obj))) { } 77 78 79 NeanderArray::NeanderArray(v8::internal::Handle<v8::internal::Object> obj) 80 : obj_(obj) { } 81 82 83 v8::internal::Object* NeanderObject::get(int offset) { 84 ASSERT(value()->HasFastObjectElements()); 85 return v8::internal::FixedArray::cast(value()->elements())->get(offset); 86 } 87 88 89 void NeanderObject::set(int offset, v8::internal::Object* value) { 90 ASSERT(value_->HasFastObjectElements()); 91 v8::internal::FixedArray::cast(value_->elements())->set(offset, value); 92 } 93 94 95 template <typename T> inline T ToCData(v8::internal::Object* obj) { 96 STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address)); 97 return reinterpret_cast<T>( 98 reinterpret_cast<intptr_t>( 99 v8::internal::Foreign::cast(obj)->foreign_address())); 100 } 101 102 103 template <typename T> 104 inline v8::internal::Handle<v8::internal::Object> FromCData( 105 v8::internal::Isolate* isolate, T obj) { 106 STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address)); 107 return isolate->factory()->NewForeign( 108 reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(obj))); 109 } 110 111 112 class ApiFunction { 113 public: 114 explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { } 115 v8::internal::Address address() { return addr_; } 116 private: 117 v8::internal::Address addr_; 118 }; 119 120 121 122 class RegisteredExtension { 123 public: 124 explicit RegisteredExtension(Extension* extension); 125 static void Register(RegisteredExtension* that); 126 static void UnregisterAll(); 127 Extension* extension() { return extension_; } 128 RegisteredExtension* next() { return next_; } 129 static RegisteredExtension* first_extension() { return first_extension_; } 130 private: 131 Extension* extension_; 132 RegisteredExtension* next_; 133 static RegisteredExtension* first_extension_; 134 }; 135 136 137 #define OPEN_HANDLE_LIST(V) \ 138 V(Template, TemplateInfo) \ 139 V(FunctionTemplate, FunctionTemplateInfo) \ 140 V(ObjectTemplate, ObjectTemplateInfo) \ 141 V(Signature, SignatureInfo) \ 142 V(AccessorSignature, FunctionTemplateInfo) \ 143 V(TypeSwitch, TypeSwitchInfo) \ 144 V(Data, Object) \ 145 V(RegExp, JSRegExp) \ 146 V(Object, JSObject) \ 147 V(Array, JSArray) \ 148 V(ArrayBuffer, JSArrayBuffer) \ 149 V(ArrayBufferView, JSArrayBufferView) \ 150 V(TypedArray, JSTypedArray) \ 151 V(Uint8Array, JSTypedArray) \ 152 V(Uint8ClampedArray, JSTypedArray) \ 153 V(Int8Array, JSTypedArray) \ 154 V(Uint16Array, JSTypedArray) \ 155 V(Int16Array, JSTypedArray) \ 156 V(Uint32Array, JSTypedArray) \ 157 V(Int32Array, JSTypedArray) \ 158 V(Float32Array, JSTypedArray) \ 159 V(Float64Array, JSTypedArray) \ 160 V(DataView, JSDataView) \ 161 V(String, String) \ 162 V(Symbol, Symbol) \ 163 V(Script, JSFunction) \ 164 V(UnboundScript, SharedFunctionInfo) \ 165 V(Function, JSFunction) \ 166 V(Message, JSMessageObject) \ 167 V(Context, Context) \ 168 V(External, Object) \ 169 V(StackTrace, JSArray) \ 170 V(StackFrame, JSObject) \ 171 V(DeclaredAccessorDescriptor, DeclaredAccessorDescriptor) 172 173 174 class Utils { 175 public: 176 static inline bool ApiCheck(bool condition, 177 const char* location, 178 const char* message) { 179 if (!condition) Utils::ReportApiFailure(location, message); 180 return condition; 181 } 182 183 static Local<FunctionTemplate> ToFunctionTemplate(NeanderObject obj); 184 static Local<ObjectTemplate> ToObjectTemplate(NeanderObject obj); 185 186 static inline Local<Context> ToLocal( 187 v8::internal::Handle<v8::internal::Context> obj); 188 static inline Local<Value> ToLocal( 189 v8::internal::Handle<v8::internal::Object> obj); 190 static inline Local<Function> ToLocal( 191 v8::internal::Handle<v8::internal::JSFunction> obj); 192 static inline Local<String> ToLocal( 193 v8::internal::Handle<v8::internal::String> obj); 194 static inline Local<Symbol> ToLocal( 195 v8::internal::Handle<v8::internal::Symbol> obj); 196 static inline Local<RegExp> ToLocal( 197 v8::internal::Handle<v8::internal::JSRegExp> obj); 198 static inline Local<Object> ToLocal( 199 v8::internal::Handle<v8::internal::JSObject> obj); 200 static inline Local<Array> ToLocal( 201 v8::internal::Handle<v8::internal::JSArray> obj); 202 static inline Local<ArrayBuffer> ToLocal( 203 v8::internal::Handle<v8::internal::JSArrayBuffer> obj); 204 static inline Local<ArrayBufferView> ToLocal( 205 v8::internal::Handle<v8::internal::JSArrayBufferView> obj); 206 static inline Local<DataView> ToLocal( 207 v8::internal::Handle<v8::internal::JSDataView> obj); 208 209 static inline Local<TypedArray> ToLocal( 210 v8::internal::Handle<v8::internal::JSTypedArray> obj); 211 static inline Local<Uint8Array> ToLocalUint8Array( 212 v8::internal::Handle<v8::internal::JSTypedArray> obj); 213 static inline Local<Uint8ClampedArray> ToLocalUint8ClampedArray( 214 v8::internal::Handle<v8::internal::JSTypedArray> obj); 215 static inline Local<Int8Array> ToLocalInt8Array( 216 v8::internal::Handle<v8::internal::JSTypedArray> obj); 217 static inline Local<Uint16Array> ToLocalUint16Array( 218 v8::internal::Handle<v8::internal::JSTypedArray> obj); 219 static inline Local<Int16Array> ToLocalInt16Array( 220 v8::internal::Handle<v8::internal::JSTypedArray> obj); 221 static inline Local<Uint32Array> ToLocalUint32Array( 222 v8::internal::Handle<v8::internal::JSTypedArray> obj); 223 static inline Local<Int32Array> ToLocalInt32Array( 224 v8::internal::Handle<v8::internal::JSTypedArray> obj); 225 static inline Local<Float32Array> ToLocalFloat32Array( 226 v8::internal::Handle<v8::internal::JSTypedArray> obj); 227 static inline Local<Float64Array> ToLocalFloat64Array( 228 v8::internal::Handle<v8::internal::JSTypedArray> obj); 229 230 static inline Local<Message> MessageToLocal( 231 v8::internal::Handle<v8::internal::Object> obj); 232 static inline Local<StackTrace> StackTraceToLocal( 233 v8::internal::Handle<v8::internal::JSArray> obj); 234 static inline Local<StackFrame> StackFrameToLocal( 235 v8::internal::Handle<v8::internal::JSObject> obj); 236 static inline Local<Number> NumberToLocal( 237 v8::internal::Handle<v8::internal::Object> obj); 238 static inline Local<Integer> IntegerToLocal( 239 v8::internal::Handle<v8::internal::Object> obj); 240 static inline Local<Uint32> Uint32ToLocal( 241 v8::internal::Handle<v8::internal::Object> obj); 242 static inline Local<FunctionTemplate> ToLocal( 243 v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj); 244 static inline Local<ObjectTemplate> ToLocal( 245 v8::internal::Handle<v8::internal::ObjectTemplateInfo> obj); 246 static inline Local<Signature> ToLocal( 247 v8::internal::Handle<v8::internal::SignatureInfo> obj); 248 static inline Local<AccessorSignature> AccessorSignatureToLocal( 249 v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj); 250 static inline Local<TypeSwitch> ToLocal( 251 v8::internal::Handle<v8::internal::TypeSwitchInfo> obj); 252 static inline Local<External> ExternalToLocal( 253 v8::internal::Handle<v8::internal::JSObject> obj); 254 static inline Local<DeclaredAccessorDescriptor> ToLocal( 255 v8::internal::Handle<v8::internal::DeclaredAccessorDescriptor> obj); 256 257 #define DECLARE_OPEN_HANDLE(From, To) \ 258 static inline v8::internal::Handle<v8::internal::To> \ 259 OpenHandle(const From* that, bool allow_empty_handle = false); 260 261 OPEN_HANDLE_LIST(DECLARE_OPEN_HANDLE) 262 263 #undef DECLARE_OPEN_HANDLE 264 265 template<class From, class To> 266 static inline Local<To> Convert(v8::internal::Handle<From> obj) { 267 ASSERT(obj.is_null() || !obj->IsTheHole()); 268 return Local<To>(reinterpret_cast<To*>(obj.location())); 269 } 270 271 template <class T> 272 static inline v8::internal::Handle<v8::internal::Object> OpenPersistent( 273 const v8::Persistent<T>& persistent) { 274 return v8::internal::Handle<v8::internal::Object>( 275 reinterpret_cast<v8::internal::Object**>(persistent.val_)); 276 } 277 278 template <class T> 279 static inline v8::internal::Handle<v8::internal::Object> OpenPersistent( 280 v8::Persistent<T>* persistent) { 281 return OpenPersistent(*persistent); 282 } 283 284 template <class From, class To> 285 static inline v8::internal::Handle<To> OpenHandle(v8::Local<From> handle) { 286 return OpenHandle(*handle); 287 } 288 289 private: 290 static void ReportApiFailure(const char* location, const char* message); 291 }; 292 293 294 template <class T> 295 v8::internal::Handle<T> v8::internal::Handle<T>::EscapeFrom( 296 v8::EscapableHandleScope* scope) { 297 v8::internal::Handle<T> handle; 298 if (!is_null()) { 299 handle = *this; 300 } 301 return Utils::OpenHandle(*scope->Escape(Utils::ToLocal(handle)), true); 302 } 303 304 305 template <class T> 306 inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) { 307 return reinterpret_cast<T*>(obj.location()); 308 } 309 310 template <class T> 311 inline v8::Local<T> ToApiHandle( 312 v8::internal::Handle<v8::internal::Object> obj) { 313 return Utils::Convert<v8::internal::Object, T>(obj); 314 } 315 316 317 // Implementations of ToLocal 318 319 #define MAKE_TO_LOCAL(Name, From, To) \ 320 Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \ 321 return Convert<v8::internal::From, v8::To>(obj); \ 322 } 323 324 325 #define MAKE_TO_LOCAL_TYPED_ARRAY(Type, typeName, TYPE, ctype, size) \ 326 Local<v8::Type##Array> Utils::ToLocal##Type##Array( \ 327 v8::internal::Handle<v8::internal::JSTypedArray> obj) { \ 328 ASSERT(obj->type() == kExternal##Type##Array); \ 329 return Convert<v8::internal::JSTypedArray, v8::Type##Array>(obj); \ 330 } 331 332 333 MAKE_TO_LOCAL(ToLocal, Context, Context) 334 MAKE_TO_LOCAL(ToLocal, Object, Value) 335 MAKE_TO_LOCAL(ToLocal, JSFunction, Function) 336 MAKE_TO_LOCAL(ToLocal, String, String) 337 MAKE_TO_LOCAL(ToLocal, Symbol, Symbol) 338 MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp) 339 MAKE_TO_LOCAL(ToLocal, JSObject, Object) 340 MAKE_TO_LOCAL(ToLocal, JSArray, Array) 341 MAKE_TO_LOCAL(ToLocal, JSArrayBuffer, ArrayBuffer) 342 MAKE_TO_LOCAL(ToLocal, JSArrayBufferView, ArrayBufferView) 343 MAKE_TO_LOCAL(ToLocal, JSDataView, DataView) 344 MAKE_TO_LOCAL(ToLocal, JSTypedArray, TypedArray) 345 346 TYPED_ARRAYS(MAKE_TO_LOCAL_TYPED_ARRAY) 347 348 MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate) 349 MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate) 350 MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature) 351 MAKE_TO_LOCAL(AccessorSignatureToLocal, FunctionTemplateInfo, AccessorSignature) 352 MAKE_TO_LOCAL(ToLocal, TypeSwitchInfo, TypeSwitch) 353 MAKE_TO_LOCAL(MessageToLocal, Object, Message) 354 MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace) 355 MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame) 356 MAKE_TO_LOCAL(NumberToLocal, Object, Number) 357 MAKE_TO_LOCAL(IntegerToLocal, Object, Integer) 358 MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32) 359 MAKE_TO_LOCAL(ExternalToLocal, JSObject, External) 360 MAKE_TO_LOCAL(ToLocal, DeclaredAccessorDescriptor, DeclaredAccessorDescriptor) 361 362 #undef MAKE_TO_LOCAL_TYPED_ARRAY 363 #undef MAKE_TO_LOCAL 364 365 366 // Implementations of OpenHandle 367 368 #define MAKE_OPEN_HANDLE(From, To) \ 369 v8::internal::Handle<v8::internal::To> Utils::OpenHandle( \ 370 const v8::From* that, bool allow_empty_handle) { \ 371 EXTRA_CHECK(allow_empty_handle || that != NULL); \ 372 EXTRA_CHECK(that == NULL || \ 373 (*reinterpret_cast<v8::internal::Object**>( \ 374 const_cast<v8::From*>(that)))->Is##To()); \ 375 return v8::internal::Handle<v8::internal::To>( \ 376 reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \ 377 } 378 379 OPEN_HANDLE_LIST(MAKE_OPEN_HANDLE) 380 381 #undef MAKE_OPEN_HANDLE 382 #undef OPEN_HANDLE_LIST 383 384 385 namespace internal { 386 387 // Tracks string usage to help make better decisions when 388 // externalizing strings. 389 // 390 // Implementation note: internally this class only tracks fresh 391 // strings and keeps a single use counter for them. 392 class StringTracker { 393 public: 394 // Records that the given string's characters were copied to some 395 // external buffer. If this happens often we should honor 396 // externalization requests for the string. 397 void RecordWrite(Handle<String> string) { 398 Address address = reinterpret_cast<Address>(*string); 399 Address top = isolate_->heap()->NewSpaceTop(); 400 if (IsFreshString(address, top)) { 401 IncrementUseCount(top); 402 } 403 } 404 405 // Estimates freshness and use frequency of the given string based 406 // on how close it is to the new space top and the recorded usage 407 // history. 408 inline bool IsFreshUnusedString(Handle<String> string) { 409 Address address = reinterpret_cast<Address>(*string); 410 Address top = isolate_->heap()->NewSpaceTop(); 411 return IsFreshString(address, top) && IsUseCountLow(top); 412 } 413 414 private: 415 StringTracker() : use_count_(0), last_top_(NULL), isolate_(NULL) { } 416 417 static inline bool IsFreshString(Address string, Address top) { 418 return top - kFreshnessLimit <= string && string <= top; 419 } 420 421 inline bool IsUseCountLow(Address top) { 422 if (last_top_ != top) return true; 423 return use_count_ < kUseLimit; 424 } 425 426 inline void IncrementUseCount(Address top) { 427 if (last_top_ != top) { 428 use_count_ = 0; 429 last_top_ = top; 430 } 431 ++use_count_; 432 } 433 434 // Single use counter shared by all fresh strings. 435 int use_count_; 436 437 // Last new space top when the use count above was valid. 438 Address last_top_; 439 440 Isolate* isolate_; 441 442 // How close to the new space top a fresh string has to be. 443 static const int kFreshnessLimit = 1024; 444 445 // The number of uses required to consider a string useful. 446 static const int kUseLimit = 32; 447 448 friend class Isolate; 449 450 DISALLOW_COPY_AND_ASSIGN(StringTracker); 451 }; 452 453 454 class DeferredHandles { 455 public: 456 ~DeferredHandles(); 457 458 private: 459 DeferredHandles(Object** first_block_limit, Isolate* isolate) 460 : next_(NULL), 461 previous_(NULL), 462 first_block_limit_(first_block_limit), 463 isolate_(isolate) { 464 isolate->LinkDeferredHandles(this); 465 } 466 467 void Iterate(ObjectVisitor* v); 468 469 List<Object**> blocks_; 470 DeferredHandles* next_; 471 DeferredHandles* previous_; 472 Object** first_block_limit_; 473 Isolate* isolate_; 474 475 friend class HandleScopeImplementer; 476 friend class Isolate; 477 }; 478 479 480 // This class is here in order to be able to declare it a friend of 481 // HandleScope. Moving these methods to be members of HandleScope would be 482 // neat in some ways, but it would expose internal implementation details in 483 // our public header file, which is undesirable. 484 // 485 // An isolate has a single instance of this class to hold the current thread's 486 // data. In multithreaded V8 programs this data is copied in and out of storage 487 // so that the currently executing thread always has its own copy of this 488 // data. 489 class HandleScopeImplementer { 490 public: 491 explicit HandleScopeImplementer(Isolate* isolate) 492 : isolate_(isolate), 493 blocks_(0), 494 entered_contexts_(0), 495 saved_contexts_(0), 496 spare_(NULL), 497 call_depth_(0), 498 last_handle_before_deferred_block_(NULL) { } 499 500 ~HandleScopeImplementer() { 501 DeleteArray(spare_); 502 } 503 504 // Threading support for handle data. 505 static int ArchiveSpacePerThread(); 506 char* RestoreThread(char* from); 507 char* ArchiveThread(char* to); 508 void FreeThreadResources(); 509 510 // Garbage collection support. 511 void Iterate(v8::internal::ObjectVisitor* v); 512 static char* Iterate(v8::internal::ObjectVisitor* v, char* data); 513 514 515 inline internal::Object** GetSpareOrNewBlock(); 516 inline void DeleteExtensions(internal::Object** prev_limit); 517 518 inline void IncrementCallDepth() {call_depth_++;} 519 inline void DecrementCallDepth() {call_depth_--;} 520 inline bool CallDepthIsZero() { return call_depth_ == 0; } 521 522 inline void EnterContext(Handle<Context> context); 523 inline void LeaveContext(); 524 inline bool LastEnteredContextWas(Handle<Context> context); 525 526 // Returns the last entered context or an empty handle if no 527 // contexts have been entered. 528 inline Handle<Context> LastEnteredContext(); 529 530 inline void SaveContext(Context* context); 531 inline Context* RestoreContext(); 532 inline bool HasSavedContexts(); 533 534 inline List<internal::Object**>* blocks() { return &blocks_; } 535 Isolate* isolate() const { return isolate_; } 536 537 void ReturnBlock(Object** block) { 538 ASSERT(block != NULL); 539 if (spare_ != NULL) DeleteArray(spare_); 540 spare_ = block; 541 } 542 543 private: 544 void ResetAfterArchive() { 545 blocks_.Initialize(0); 546 entered_contexts_.Initialize(0); 547 saved_contexts_.Initialize(0); 548 spare_ = NULL; 549 last_handle_before_deferred_block_ = NULL; 550 call_depth_ = 0; 551 } 552 553 void Free() { 554 ASSERT(blocks_.length() == 0); 555 ASSERT(entered_contexts_.length() == 0); 556 ASSERT(saved_contexts_.length() == 0); 557 blocks_.Free(); 558 entered_contexts_.Free(); 559 saved_contexts_.Free(); 560 if (spare_ != NULL) { 561 DeleteArray(spare_); 562 spare_ = NULL; 563 } 564 ASSERT(call_depth_ == 0); 565 } 566 567 void BeginDeferredScope(); 568 DeferredHandles* Detach(Object** prev_limit); 569 570 Isolate* isolate_; 571 List<internal::Object**> blocks_; 572 // Used as a stack to keep track of entered contexts. 573 List<Context*> entered_contexts_; 574 // Used as a stack to keep track of saved contexts. 575 List<Context*> saved_contexts_; 576 Object** spare_; 577 int call_depth_; 578 Object** last_handle_before_deferred_block_; 579 // This is only used for threading support. 580 HandleScopeData handle_scope_data_; 581 582 void IterateThis(ObjectVisitor* v); 583 char* RestoreThreadHelper(char* from); 584 char* ArchiveThreadHelper(char* to); 585 586 friend class DeferredHandles; 587 friend class DeferredHandleScope; 588 589 DISALLOW_COPY_AND_ASSIGN(HandleScopeImplementer); 590 }; 591 592 593 const int kHandleBlockSize = v8::internal::KB - 2; // fit in one page 594 595 596 void HandleScopeImplementer::SaveContext(Context* context) { 597 saved_contexts_.Add(context); 598 } 599 600 601 Context* HandleScopeImplementer::RestoreContext() { 602 return saved_contexts_.RemoveLast(); 603 } 604 605 606 bool HandleScopeImplementer::HasSavedContexts() { 607 return !saved_contexts_.is_empty(); 608 } 609 610 611 void HandleScopeImplementer::EnterContext(Handle<Context> context) { 612 entered_contexts_.Add(*context); 613 } 614 615 616 void HandleScopeImplementer::LeaveContext() { 617 entered_contexts_.RemoveLast(); 618 } 619 620 621 bool HandleScopeImplementer::LastEnteredContextWas(Handle<Context> context) { 622 return !entered_contexts_.is_empty() && entered_contexts_.last() == *context; 623 } 624 625 626 Handle<Context> HandleScopeImplementer::LastEnteredContext() { 627 if (entered_contexts_.is_empty()) return Handle<Context>::null(); 628 return Handle<Context>(entered_contexts_.last()); 629 } 630 631 632 // If there's a spare block, use it for growing the current scope. 633 internal::Object** HandleScopeImplementer::GetSpareOrNewBlock() { 634 internal::Object** block = (spare_ != NULL) ? 635 spare_ : 636 NewArray<internal::Object*>(kHandleBlockSize); 637 spare_ = NULL; 638 return block; 639 } 640 641 642 void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) { 643 while (!blocks_.is_empty()) { 644 internal::Object** block_start = blocks_.last(); 645 internal::Object** block_limit = block_start + kHandleBlockSize; 646 #ifdef DEBUG 647 // SealHandleScope may make the prev_limit to point inside the block. 648 if (block_start <= prev_limit && prev_limit <= block_limit) { 649 #ifdef ENABLE_HANDLE_ZAPPING 650 internal::HandleScope::ZapRange(prev_limit, block_limit); 651 #endif 652 break; 653 } 654 #else 655 if (prev_limit == block_limit) break; 656 #endif 657 658 blocks_.RemoveLast(); 659 #ifdef ENABLE_HANDLE_ZAPPING 660 internal::HandleScope::ZapRange(block_start, block_limit); 661 #endif 662 if (spare_ != NULL) { 663 DeleteArray(spare_); 664 } 665 spare_ = block_start; 666 } 667 ASSERT((blocks_.is_empty() && prev_limit == NULL) || 668 (!blocks_.is_empty() && prev_limit != NULL)); 669 } 670 671 672 // Interceptor functions called from generated inline caches to notify 673 // CPU profiler that external callbacks are invoked. 674 void InvokeAccessorGetterCallback( 675 v8::Local<v8::String> property, 676 const v8::PropertyCallbackInfo<v8::Value>& info, 677 v8::AccessorGetterCallback getter); 678 679 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info, 680 v8::FunctionCallback callback); 681 682 class Testing { 683 public: 684 static v8::Testing::StressType stress_type() { return stress_type_; } 685 static void set_stress_type(v8::Testing::StressType stress_type) { 686 stress_type_ = stress_type; 687 } 688 689 private: 690 static v8::Testing::StressType stress_type_; 691 }; 692 693 } } // namespace v8::internal 694 695 #endif // V8_API_H_ 696