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 DCHECK(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 DCHECK(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(Name, Name) \ 162 V(String, String) \ 163 V(Symbol, Symbol) \ 164 V(Script, JSFunction) \ 165 V(UnboundScript, SharedFunctionInfo) \ 166 V(Function, JSFunction) \ 167 V(Message, JSMessageObject) \ 168 V(Context, Context) \ 169 V(External, Object) \ 170 V(StackTrace, JSArray) \ 171 V(StackFrame, JSObject) \ 172 V(DeclaredAccessorDescriptor, DeclaredAccessorDescriptor) 173 174 175 class Utils { 176 public: 177 static inline bool ApiCheck(bool condition, 178 const char* location, 179 const char* message) { 180 if (!condition) Utils::ReportApiFailure(location, message); 181 return condition; 182 } 183 184 static Local<FunctionTemplate> ToFunctionTemplate(NeanderObject obj); 185 static Local<ObjectTemplate> ToObjectTemplate(NeanderObject obj); 186 187 static inline Local<Context> ToLocal( 188 v8::internal::Handle<v8::internal::Context> obj); 189 static inline Local<Value> ToLocal( 190 v8::internal::Handle<v8::internal::Object> obj); 191 static inline Local<Function> ToLocal( 192 v8::internal::Handle<v8::internal::JSFunction> obj); 193 static inline Local<Name> ToLocal( 194 v8::internal::Handle<v8::internal::Name> obj); 195 static inline Local<String> ToLocal( 196 v8::internal::Handle<v8::internal::String> obj); 197 static inline Local<Symbol> ToLocal( 198 v8::internal::Handle<v8::internal::Symbol> obj); 199 static inline Local<RegExp> ToLocal( 200 v8::internal::Handle<v8::internal::JSRegExp> obj); 201 static inline Local<Object> ToLocal( 202 v8::internal::Handle<v8::internal::JSObject> obj); 203 static inline Local<Array> ToLocal( 204 v8::internal::Handle<v8::internal::JSArray> obj); 205 static inline Local<ArrayBuffer> ToLocal( 206 v8::internal::Handle<v8::internal::JSArrayBuffer> obj); 207 static inline Local<ArrayBufferView> ToLocal( 208 v8::internal::Handle<v8::internal::JSArrayBufferView> obj); 209 static inline Local<DataView> ToLocal( 210 v8::internal::Handle<v8::internal::JSDataView> obj); 211 212 static inline Local<TypedArray> ToLocal( 213 v8::internal::Handle<v8::internal::JSTypedArray> obj); 214 static inline Local<Uint8Array> ToLocalUint8Array( 215 v8::internal::Handle<v8::internal::JSTypedArray> obj); 216 static inline Local<Uint8ClampedArray> ToLocalUint8ClampedArray( 217 v8::internal::Handle<v8::internal::JSTypedArray> obj); 218 static inline Local<Int8Array> ToLocalInt8Array( 219 v8::internal::Handle<v8::internal::JSTypedArray> obj); 220 static inline Local<Uint16Array> ToLocalUint16Array( 221 v8::internal::Handle<v8::internal::JSTypedArray> obj); 222 static inline Local<Int16Array> ToLocalInt16Array( 223 v8::internal::Handle<v8::internal::JSTypedArray> obj); 224 static inline Local<Uint32Array> ToLocalUint32Array( 225 v8::internal::Handle<v8::internal::JSTypedArray> obj); 226 static inline Local<Int32Array> ToLocalInt32Array( 227 v8::internal::Handle<v8::internal::JSTypedArray> obj); 228 static inline Local<Float32Array> ToLocalFloat32Array( 229 v8::internal::Handle<v8::internal::JSTypedArray> obj); 230 static inline Local<Float64Array> ToLocalFloat64Array( 231 v8::internal::Handle<v8::internal::JSTypedArray> obj); 232 233 static inline Local<Message> MessageToLocal( 234 v8::internal::Handle<v8::internal::Object> obj); 235 static inline Local<StackTrace> StackTraceToLocal( 236 v8::internal::Handle<v8::internal::JSArray> obj); 237 static inline Local<StackFrame> StackFrameToLocal( 238 v8::internal::Handle<v8::internal::JSObject> obj); 239 static inline Local<Number> NumberToLocal( 240 v8::internal::Handle<v8::internal::Object> obj); 241 static inline Local<Integer> IntegerToLocal( 242 v8::internal::Handle<v8::internal::Object> obj); 243 static inline Local<Uint32> Uint32ToLocal( 244 v8::internal::Handle<v8::internal::Object> obj); 245 static inline Local<FunctionTemplate> ToLocal( 246 v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj); 247 static inline Local<ObjectTemplate> ToLocal( 248 v8::internal::Handle<v8::internal::ObjectTemplateInfo> obj); 249 static inline Local<Signature> ToLocal( 250 v8::internal::Handle<v8::internal::SignatureInfo> obj); 251 static inline Local<AccessorSignature> AccessorSignatureToLocal( 252 v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj); 253 static inline Local<TypeSwitch> ToLocal( 254 v8::internal::Handle<v8::internal::TypeSwitchInfo> obj); 255 static inline Local<External> ExternalToLocal( 256 v8::internal::Handle<v8::internal::JSObject> obj); 257 static inline Local<DeclaredAccessorDescriptor> ToLocal( 258 v8::internal::Handle<v8::internal::DeclaredAccessorDescriptor> obj); 259 260 #define DECLARE_OPEN_HANDLE(From, To) \ 261 static inline v8::internal::Handle<v8::internal::To> \ 262 OpenHandle(const From* that, bool allow_empty_handle = false); 263 264 OPEN_HANDLE_LIST(DECLARE_OPEN_HANDLE) 265 266 #undef DECLARE_OPEN_HANDLE 267 268 template<class From, class To> 269 static inline Local<To> Convert(v8::internal::Handle<From> obj) { 270 DCHECK(obj.is_null() || !obj->IsTheHole()); 271 return Local<To>(reinterpret_cast<To*>(obj.location())); 272 } 273 274 template <class T> 275 static inline v8::internal::Handle<v8::internal::Object> OpenPersistent( 276 const v8::Persistent<T>& persistent) { 277 return v8::internal::Handle<v8::internal::Object>( 278 reinterpret_cast<v8::internal::Object**>(persistent.val_)); 279 } 280 281 template <class T> 282 static inline v8::internal::Handle<v8::internal::Object> OpenPersistent( 283 v8::Persistent<T>* persistent) { 284 return OpenPersistent(*persistent); 285 } 286 287 template <class From, class To> 288 static inline v8::internal::Handle<To> OpenHandle(v8::Local<From> handle) { 289 return OpenHandle(*handle); 290 } 291 292 private: 293 static void ReportApiFailure(const char* location, const char* message); 294 }; 295 296 297 template <class T> 298 v8::internal::Handle<T> v8::internal::Handle<T>::EscapeFrom( 299 v8::EscapableHandleScope* scope) { 300 v8::internal::Handle<T> handle; 301 if (!is_null()) { 302 handle = *this; 303 } 304 return Utils::OpenHandle(*scope->Escape(Utils::ToLocal(handle)), true); 305 } 306 307 308 template <class T> 309 inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) { 310 return reinterpret_cast<T*>(obj.location()); 311 } 312 313 template <class T> 314 inline v8::Local<T> ToApiHandle( 315 v8::internal::Handle<v8::internal::Object> obj) { 316 return Utils::Convert<v8::internal::Object, T>(obj); 317 } 318 319 320 // Implementations of ToLocal 321 322 #define MAKE_TO_LOCAL(Name, From, To) \ 323 Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \ 324 return Convert<v8::internal::From, v8::To>(obj); \ 325 } 326 327 328 #define MAKE_TO_LOCAL_TYPED_ARRAY(Type, typeName, TYPE, ctype, size) \ 329 Local<v8::Type##Array> Utils::ToLocal##Type##Array( \ 330 v8::internal::Handle<v8::internal::JSTypedArray> obj) { \ 331 DCHECK(obj->type() == kExternal##Type##Array); \ 332 return Convert<v8::internal::JSTypedArray, v8::Type##Array>(obj); \ 333 } 334 335 336 MAKE_TO_LOCAL(ToLocal, Context, Context) 337 MAKE_TO_LOCAL(ToLocal, Object, Value) 338 MAKE_TO_LOCAL(ToLocal, JSFunction, Function) 339 MAKE_TO_LOCAL(ToLocal, Name, Name) 340 MAKE_TO_LOCAL(ToLocal, String, String) 341 MAKE_TO_LOCAL(ToLocal, Symbol, Symbol) 342 MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp) 343 MAKE_TO_LOCAL(ToLocal, JSObject, Object) 344 MAKE_TO_LOCAL(ToLocal, JSArray, Array) 345 MAKE_TO_LOCAL(ToLocal, JSArrayBuffer, ArrayBuffer) 346 MAKE_TO_LOCAL(ToLocal, JSArrayBufferView, ArrayBufferView) 347 MAKE_TO_LOCAL(ToLocal, JSDataView, DataView) 348 MAKE_TO_LOCAL(ToLocal, JSTypedArray, TypedArray) 349 350 TYPED_ARRAYS(MAKE_TO_LOCAL_TYPED_ARRAY) 351 352 MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate) 353 MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate) 354 MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature) 355 MAKE_TO_LOCAL(AccessorSignatureToLocal, FunctionTemplateInfo, AccessorSignature) 356 MAKE_TO_LOCAL(ToLocal, TypeSwitchInfo, TypeSwitch) 357 MAKE_TO_LOCAL(MessageToLocal, Object, Message) 358 MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace) 359 MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame) 360 MAKE_TO_LOCAL(NumberToLocal, Object, Number) 361 MAKE_TO_LOCAL(IntegerToLocal, Object, Integer) 362 MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32) 363 MAKE_TO_LOCAL(ExternalToLocal, JSObject, External) 364 MAKE_TO_LOCAL(ToLocal, DeclaredAccessorDescriptor, DeclaredAccessorDescriptor) 365 366 #undef MAKE_TO_LOCAL_TYPED_ARRAY 367 #undef MAKE_TO_LOCAL 368 369 370 // Implementations of OpenHandle 371 372 #define MAKE_OPEN_HANDLE(From, To) \ 373 v8::internal::Handle<v8::internal::To> Utils::OpenHandle( \ 374 const v8::From* that, bool allow_empty_handle) { \ 375 EXTRA_CHECK(allow_empty_handle || that != NULL); \ 376 EXTRA_CHECK(that == NULL || \ 377 (*reinterpret_cast<v8::internal::Object* const*>(that))->Is##To()); \ 378 return v8::internal::Handle<v8::internal::To>( \ 379 reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \ 380 } 381 382 OPEN_HANDLE_LIST(MAKE_OPEN_HANDLE) 383 384 #undef MAKE_OPEN_HANDLE 385 #undef OPEN_HANDLE_LIST 386 387 388 namespace internal { 389 390 // Tracks string usage to help make better decisions when 391 // externalizing strings. 392 // 393 // Implementation note: internally this class only tracks fresh 394 // strings and keeps a single use counter for them. 395 class StringTracker { 396 public: 397 // Records that the given string's characters were copied to some 398 // external buffer. If this happens often we should honor 399 // externalization requests for the string. 400 void RecordWrite(Handle<String> string) { 401 Address address = reinterpret_cast<Address>(*string); 402 Address top = isolate_->heap()->NewSpaceTop(); 403 if (IsFreshString(address, top)) { 404 IncrementUseCount(top); 405 } 406 } 407 408 // Estimates freshness and use frequency of the given string based 409 // on how close it is to the new space top and the recorded usage 410 // history. 411 inline bool IsFreshUnusedString(Handle<String> string) { 412 Address address = reinterpret_cast<Address>(*string); 413 Address top = isolate_->heap()->NewSpaceTop(); 414 return IsFreshString(address, top) && IsUseCountLow(top); 415 } 416 417 private: 418 StringTracker() : use_count_(0), last_top_(NULL), isolate_(NULL) { } 419 420 static inline bool IsFreshString(Address string, Address top) { 421 return top - kFreshnessLimit <= string && string <= top; 422 } 423 424 inline bool IsUseCountLow(Address top) { 425 if (last_top_ != top) return true; 426 return use_count_ < kUseLimit; 427 } 428 429 inline void IncrementUseCount(Address top) { 430 if (last_top_ != top) { 431 use_count_ = 0; 432 last_top_ = top; 433 } 434 ++use_count_; 435 } 436 437 // Single use counter shared by all fresh strings. 438 int use_count_; 439 440 // Last new space top when the use count above was valid. 441 Address last_top_; 442 443 Isolate* isolate_; 444 445 // How close to the new space top a fresh string has to be. 446 static const int kFreshnessLimit = 1024; 447 448 // The number of uses required to consider a string useful. 449 static const int kUseLimit = 32; 450 451 friend class Isolate; 452 453 DISALLOW_COPY_AND_ASSIGN(StringTracker); 454 }; 455 456 457 class DeferredHandles { 458 public: 459 ~DeferredHandles(); 460 461 private: 462 DeferredHandles(Object** first_block_limit, Isolate* isolate) 463 : next_(NULL), 464 previous_(NULL), 465 first_block_limit_(first_block_limit), 466 isolate_(isolate) { 467 isolate->LinkDeferredHandles(this); 468 } 469 470 void Iterate(ObjectVisitor* v); 471 472 List<Object**> blocks_; 473 DeferredHandles* next_; 474 DeferredHandles* previous_; 475 Object** first_block_limit_; 476 Isolate* isolate_; 477 478 friend class HandleScopeImplementer; 479 friend class Isolate; 480 }; 481 482 483 // This class is here in order to be able to declare it a friend of 484 // HandleScope. Moving these methods to be members of HandleScope would be 485 // neat in some ways, but it would expose internal implementation details in 486 // our public header file, which is undesirable. 487 // 488 // An isolate has a single instance of this class to hold the current thread's 489 // data. In multithreaded V8 programs this data is copied in and out of storage 490 // so that the currently executing thread always has its own copy of this 491 // data. 492 class HandleScopeImplementer { 493 public: 494 explicit HandleScopeImplementer(Isolate* isolate) 495 : isolate_(isolate), 496 blocks_(0), 497 entered_contexts_(0), 498 saved_contexts_(0), 499 spare_(NULL), 500 call_depth_(0), 501 last_handle_before_deferred_block_(NULL) { } 502 503 ~HandleScopeImplementer() { 504 DeleteArray(spare_); 505 } 506 507 // Threading support for handle data. 508 static int ArchiveSpacePerThread(); 509 char* RestoreThread(char* from); 510 char* ArchiveThread(char* to); 511 void FreeThreadResources(); 512 513 // Garbage collection support. 514 void Iterate(v8::internal::ObjectVisitor* v); 515 static char* Iterate(v8::internal::ObjectVisitor* v, char* data); 516 517 518 inline internal::Object** GetSpareOrNewBlock(); 519 inline void DeleteExtensions(internal::Object** prev_limit); 520 521 inline void IncrementCallDepth() {call_depth_++;} 522 inline void DecrementCallDepth() {call_depth_--;} 523 inline bool CallDepthIsZero() { return call_depth_ == 0; } 524 525 inline void EnterContext(Handle<Context> context); 526 inline void LeaveContext(); 527 inline bool LastEnteredContextWas(Handle<Context> context); 528 529 // Returns the last entered context or an empty handle if no 530 // contexts have been entered. 531 inline Handle<Context> LastEnteredContext(); 532 533 inline void SaveContext(Context* context); 534 inline Context* RestoreContext(); 535 inline bool HasSavedContexts(); 536 537 inline List<internal::Object**>* blocks() { return &blocks_; } 538 Isolate* isolate() const { return isolate_; } 539 540 void ReturnBlock(Object** block) { 541 DCHECK(block != NULL); 542 if (spare_ != NULL) DeleteArray(spare_); 543 spare_ = block; 544 } 545 546 private: 547 void ResetAfterArchive() { 548 blocks_.Initialize(0); 549 entered_contexts_.Initialize(0); 550 saved_contexts_.Initialize(0); 551 spare_ = NULL; 552 last_handle_before_deferred_block_ = NULL; 553 call_depth_ = 0; 554 } 555 556 void Free() { 557 DCHECK(blocks_.length() == 0); 558 DCHECK(entered_contexts_.length() == 0); 559 DCHECK(saved_contexts_.length() == 0); 560 blocks_.Free(); 561 entered_contexts_.Free(); 562 saved_contexts_.Free(); 563 if (spare_ != NULL) { 564 DeleteArray(spare_); 565 spare_ = NULL; 566 } 567 DCHECK(call_depth_ == 0); 568 } 569 570 void BeginDeferredScope(); 571 DeferredHandles* Detach(Object** prev_limit); 572 573 Isolate* isolate_; 574 List<internal::Object**> blocks_; 575 // Used as a stack to keep track of entered contexts. 576 List<Context*> entered_contexts_; 577 // Used as a stack to keep track of saved contexts. 578 List<Context*> saved_contexts_; 579 Object** spare_; 580 int call_depth_; 581 Object** last_handle_before_deferred_block_; 582 // This is only used for threading support. 583 HandleScopeData handle_scope_data_; 584 585 void IterateThis(ObjectVisitor* v); 586 char* RestoreThreadHelper(char* from); 587 char* ArchiveThreadHelper(char* to); 588 589 friend class DeferredHandles; 590 friend class DeferredHandleScope; 591 592 DISALLOW_COPY_AND_ASSIGN(HandleScopeImplementer); 593 }; 594 595 596 const int kHandleBlockSize = v8::internal::KB - 2; // fit in one page 597 598 599 void HandleScopeImplementer::SaveContext(Context* context) { 600 saved_contexts_.Add(context); 601 } 602 603 604 Context* HandleScopeImplementer::RestoreContext() { 605 return saved_contexts_.RemoveLast(); 606 } 607 608 609 bool HandleScopeImplementer::HasSavedContexts() { 610 return !saved_contexts_.is_empty(); 611 } 612 613 614 void HandleScopeImplementer::EnterContext(Handle<Context> context) { 615 entered_contexts_.Add(*context); 616 } 617 618 619 void HandleScopeImplementer::LeaveContext() { 620 entered_contexts_.RemoveLast(); 621 } 622 623 624 bool HandleScopeImplementer::LastEnteredContextWas(Handle<Context> context) { 625 return !entered_contexts_.is_empty() && entered_contexts_.last() == *context; 626 } 627 628 629 Handle<Context> HandleScopeImplementer::LastEnteredContext() { 630 if (entered_contexts_.is_empty()) return Handle<Context>::null(); 631 return Handle<Context>(entered_contexts_.last()); 632 } 633 634 635 // If there's a spare block, use it for growing the current scope. 636 internal::Object** HandleScopeImplementer::GetSpareOrNewBlock() { 637 internal::Object** block = (spare_ != NULL) ? 638 spare_ : 639 NewArray<internal::Object*>(kHandleBlockSize); 640 spare_ = NULL; 641 return block; 642 } 643 644 645 void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) { 646 while (!blocks_.is_empty()) { 647 internal::Object** block_start = blocks_.last(); 648 internal::Object** block_limit = block_start + kHandleBlockSize; 649 #ifdef DEBUG 650 // SealHandleScope may make the prev_limit to point inside the block. 651 if (block_start <= prev_limit && prev_limit <= block_limit) { 652 #ifdef ENABLE_HANDLE_ZAPPING 653 internal::HandleScope::ZapRange(prev_limit, block_limit); 654 #endif 655 break; 656 } 657 #else 658 if (prev_limit == block_limit) break; 659 #endif 660 661 blocks_.RemoveLast(); 662 #ifdef ENABLE_HANDLE_ZAPPING 663 internal::HandleScope::ZapRange(block_start, block_limit); 664 #endif 665 if (spare_ != NULL) { 666 DeleteArray(spare_); 667 } 668 spare_ = block_start; 669 } 670 DCHECK((blocks_.is_empty() && prev_limit == NULL) || 671 (!blocks_.is_empty() && prev_limit != NULL)); 672 } 673 674 675 // Interceptor functions called from generated inline caches to notify 676 // CPU profiler that external callbacks are invoked. 677 void InvokeAccessorGetterCallback( 678 v8::Local<v8::Name> property, 679 const v8::PropertyCallbackInfo<v8::Value>& info, 680 v8::AccessorNameGetterCallback getter); 681 682 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info, 683 v8::FunctionCallback callback); 684 685 class Testing { 686 public: 687 static v8::Testing::StressType stress_type() { return stress_type_; } 688 static void set_stress_type(v8::Testing::StressType stress_type) { 689 stress_type_ = stress_type; 690 } 691 692 private: 693 static v8::Testing::StressType stress_type_; 694 }; 695 696 } } // namespace v8::internal 697 698 #endif // V8_API_H_ 699