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 "include/v8-testing.h" 9 #include "src/contexts.h" 10 #include "src/debug/debug-interface.h" 11 #include "src/factory.h" 12 #include "src/isolate.h" 13 #include "src/list.h" 14 #include "src/objects-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 template <typename T> inline T ToCData(v8::internal::Object* obj) { 31 STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address)); 32 if (obj == v8::internal::Smi::kZero) return nullptr; 33 return reinterpret_cast<T>( 34 reinterpret_cast<intptr_t>( 35 v8::internal::Foreign::cast(obj)->foreign_address())); 36 } 37 38 39 template <typename T> 40 inline v8::internal::Handle<v8::internal::Object> FromCData( 41 v8::internal::Isolate* isolate, T obj) { 42 STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address)); 43 if (obj == nullptr) return handle(v8::internal::Smi::kZero, isolate); 44 return isolate->factory()->NewForeign( 45 reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(obj))); 46 } 47 48 49 class ApiFunction { 50 public: 51 explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { } 52 v8::internal::Address address() { return addr_; } 53 private: 54 v8::internal::Address addr_; 55 }; 56 57 58 59 class RegisteredExtension { 60 public: 61 explicit RegisteredExtension(Extension* extension); 62 static void Register(RegisteredExtension* that); 63 static void UnregisterAll(); 64 Extension* extension() { return extension_; } 65 RegisteredExtension* next() { return next_; } 66 static RegisteredExtension* first_extension() { return first_extension_; } 67 private: 68 Extension* extension_; 69 RegisteredExtension* next_; 70 static RegisteredExtension* first_extension_; 71 }; 72 73 #define OPEN_HANDLE_LIST(V) \ 74 V(Template, TemplateInfo) \ 75 V(FunctionTemplate, FunctionTemplateInfo) \ 76 V(ObjectTemplate, ObjectTemplateInfo) \ 77 V(Signature, FunctionTemplateInfo) \ 78 V(AccessorSignature, FunctionTemplateInfo) \ 79 V(Data, Object) \ 80 V(RegExp, JSRegExp) \ 81 V(Object, JSReceiver) \ 82 V(Array, JSArray) \ 83 V(Map, JSMap) \ 84 V(Set, JSSet) \ 85 V(ArrayBuffer, JSArrayBuffer) \ 86 V(ArrayBufferView, JSArrayBufferView) \ 87 V(TypedArray, JSTypedArray) \ 88 V(Uint8Array, JSTypedArray) \ 89 V(Uint8ClampedArray, JSTypedArray) \ 90 V(Int8Array, JSTypedArray) \ 91 V(Uint16Array, JSTypedArray) \ 92 V(Int16Array, JSTypedArray) \ 93 V(Uint32Array, JSTypedArray) \ 94 V(Int32Array, JSTypedArray) \ 95 V(Float32Array, JSTypedArray) \ 96 V(Float64Array, JSTypedArray) \ 97 V(DataView, JSDataView) \ 98 V(SharedArrayBuffer, JSArrayBuffer) \ 99 V(Name, Name) \ 100 V(String, String) \ 101 V(Symbol, Symbol) \ 102 V(Script, JSFunction) \ 103 V(UnboundScript, SharedFunctionInfo) \ 104 V(Module, Module) \ 105 V(Function, JSReceiver) \ 106 V(Message, JSMessageObject) \ 107 V(Context, Context) \ 108 V(External, Object) \ 109 V(StackTrace, JSArray) \ 110 V(StackFrame, JSObject) \ 111 V(Proxy, JSProxy) \ 112 V(NativeWeakMap, JSWeakMap) \ 113 V(DebugInterface::Script, Script) 114 115 class Utils { 116 public: 117 static inline bool ApiCheck(bool condition, 118 const char* location, 119 const char* message) { 120 if (!condition) Utils::ReportApiFailure(location, message); 121 return condition; 122 } 123 static void ReportOOMFailure(const char* location, bool is_heap_oom); 124 125 static inline Local<Context> ToLocal( 126 v8::internal::Handle<v8::internal::Context> obj); 127 static inline Local<Value> ToLocal( 128 v8::internal::Handle<v8::internal::Object> obj); 129 static inline Local<Module> ToLocal( 130 v8::internal::Handle<v8::internal::Module> obj); 131 static inline Local<Name> ToLocal( 132 v8::internal::Handle<v8::internal::Name> obj); 133 static inline Local<String> ToLocal( 134 v8::internal::Handle<v8::internal::String> obj); 135 static inline Local<Symbol> ToLocal( 136 v8::internal::Handle<v8::internal::Symbol> obj); 137 static inline Local<RegExp> ToLocal( 138 v8::internal::Handle<v8::internal::JSRegExp> obj); 139 static inline Local<Object> ToLocal( 140 v8::internal::Handle<v8::internal::JSReceiver> obj); 141 static inline Local<Object> ToLocal( 142 v8::internal::Handle<v8::internal::JSObject> obj); 143 static inline Local<Function> ToLocal( 144 v8::internal::Handle<v8::internal::JSFunction> obj); 145 static inline Local<Array> ToLocal( 146 v8::internal::Handle<v8::internal::JSArray> obj); 147 static inline Local<Map> ToLocal( 148 v8::internal::Handle<v8::internal::JSMap> obj); 149 static inline Local<Set> ToLocal( 150 v8::internal::Handle<v8::internal::JSSet> obj); 151 static inline Local<Proxy> ToLocal( 152 v8::internal::Handle<v8::internal::JSProxy> obj); 153 static inline Local<ArrayBuffer> ToLocal( 154 v8::internal::Handle<v8::internal::JSArrayBuffer> obj); 155 static inline Local<ArrayBufferView> ToLocal( 156 v8::internal::Handle<v8::internal::JSArrayBufferView> obj); 157 static inline Local<DataView> ToLocal( 158 v8::internal::Handle<v8::internal::JSDataView> obj); 159 static inline Local<TypedArray> ToLocal( 160 v8::internal::Handle<v8::internal::JSTypedArray> obj); 161 static inline Local<Uint8Array> ToLocalUint8Array( 162 v8::internal::Handle<v8::internal::JSTypedArray> obj); 163 static inline Local<Uint8ClampedArray> ToLocalUint8ClampedArray( 164 v8::internal::Handle<v8::internal::JSTypedArray> obj); 165 static inline Local<Int8Array> ToLocalInt8Array( 166 v8::internal::Handle<v8::internal::JSTypedArray> obj); 167 static inline Local<Uint16Array> ToLocalUint16Array( 168 v8::internal::Handle<v8::internal::JSTypedArray> obj); 169 static inline Local<Int16Array> ToLocalInt16Array( 170 v8::internal::Handle<v8::internal::JSTypedArray> obj); 171 static inline Local<Uint32Array> ToLocalUint32Array( 172 v8::internal::Handle<v8::internal::JSTypedArray> obj); 173 static inline Local<Int32Array> ToLocalInt32Array( 174 v8::internal::Handle<v8::internal::JSTypedArray> obj); 175 static inline Local<Float32Array> ToLocalFloat32Array( 176 v8::internal::Handle<v8::internal::JSTypedArray> obj); 177 static inline Local<Float64Array> ToLocalFloat64Array( 178 v8::internal::Handle<v8::internal::JSTypedArray> obj); 179 180 static inline Local<SharedArrayBuffer> ToLocalShared( 181 v8::internal::Handle<v8::internal::JSArrayBuffer> obj); 182 183 static inline Local<Message> MessageToLocal( 184 v8::internal::Handle<v8::internal::Object> obj); 185 static inline Local<Promise> PromiseToLocal( 186 v8::internal::Handle<v8::internal::JSObject> obj); 187 static inline Local<StackTrace> StackTraceToLocal( 188 v8::internal::Handle<v8::internal::JSArray> obj); 189 static inline Local<StackFrame> StackFrameToLocal( 190 v8::internal::Handle<v8::internal::JSObject> obj); 191 static inline Local<Number> NumberToLocal( 192 v8::internal::Handle<v8::internal::Object> obj); 193 static inline Local<Integer> IntegerToLocal( 194 v8::internal::Handle<v8::internal::Object> obj); 195 static inline Local<Uint32> Uint32ToLocal( 196 v8::internal::Handle<v8::internal::Object> obj); 197 static inline Local<FunctionTemplate> ToLocal( 198 v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj); 199 static inline Local<ObjectTemplate> ToLocal( 200 v8::internal::Handle<v8::internal::ObjectTemplateInfo> obj); 201 static inline Local<Signature> SignatureToLocal( 202 v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj); 203 static inline Local<AccessorSignature> AccessorSignatureToLocal( 204 v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj); 205 static inline Local<External> ExternalToLocal( 206 v8::internal::Handle<v8::internal::JSObject> obj); 207 static inline Local<NativeWeakMap> NativeWeakMapToLocal( 208 v8::internal::Handle<v8::internal::JSWeakMap> obj); 209 static inline Local<Function> CallableToLocal( 210 v8::internal::Handle<v8::internal::JSReceiver> obj); 211 212 #define DECLARE_OPEN_HANDLE(From, To) \ 213 static inline v8::internal::Handle<v8::internal::To> \ 214 OpenHandle(const From* that, bool allow_empty_handle = false); 215 216 OPEN_HANDLE_LIST(DECLARE_OPEN_HANDLE) 217 218 #undef DECLARE_OPEN_HANDLE 219 220 template<class From, class To> 221 static inline Local<To> Convert(v8::internal::Handle<From> obj) { 222 DCHECK(obj.is_null() || 223 (obj->IsSmi() || 224 !obj->IsTheHole(i::HeapObject::cast(*obj)->GetIsolate()))); 225 return Local<To>(reinterpret_cast<To*>(obj.location())); 226 } 227 228 template <class T> 229 static inline v8::internal::Handle<v8::internal::Object> OpenPersistent( 230 const v8::Persistent<T>& persistent) { 231 return v8::internal::Handle<v8::internal::Object>( 232 reinterpret_cast<v8::internal::Object**>(persistent.val_)); 233 } 234 235 template <class T> 236 static inline v8::internal::Handle<v8::internal::Object> OpenPersistent( 237 v8::Persistent<T>* persistent) { 238 return OpenPersistent(*persistent); 239 } 240 241 template <class From, class To> 242 static inline v8::internal::Handle<To> OpenHandle(v8::Local<From> handle) { 243 return OpenHandle(*handle); 244 } 245 246 private: 247 static void ReportApiFailure(const char* location, const char* message); 248 }; 249 250 251 template <class T> 252 inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) { 253 return reinterpret_cast<T*>(obj.location()); 254 } 255 256 template <class T> 257 inline v8::Local<T> ToApiHandle( 258 v8::internal::Handle<v8::internal::Object> obj) { 259 return Utils::Convert<v8::internal::Object, T>(obj); 260 } 261 262 263 template <class T> 264 inline bool ToLocal(v8::internal::MaybeHandle<v8::internal::Object> maybe, 265 Local<T>* local) { 266 v8::internal::Handle<v8::internal::Object> handle; 267 if (maybe.ToHandle(&handle)) { 268 *local = Utils::Convert<v8::internal::Object, T>(handle); 269 return true; 270 } 271 return false; 272 } 273 274 275 // Implementations of ToLocal 276 277 #define MAKE_TO_LOCAL(Name, From, To) \ 278 Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \ 279 return Convert<v8::internal::From, v8::To>(obj); \ 280 } 281 282 283 #define MAKE_TO_LOCAL_TYPED_ARRAY(Type, typeName, TYPE, ctype, size) \ 284 Local<v8::Type##Array> Utils::ToLocal##Type##Array( \ 285 v8::internal::Handle<v8::internal::JSTypedArray> obj) { \ 286 DCHECK(obj->type() == v8::internal::kExternal##Type##Array); \ 287 return Convert<v8::internal::JSTypedArray, v8::Type##Array>(obj); \ 288 } 289 290 291 MAKE_TO_LOCAL(ToLocal, Context, Context) 292 MAKE_TO_LOCAL(ToLocal, Object, Value) 293 MAKE_TO_LOCAL(ToLocal, Module, Module) 294 MAKE_TO_LOCAL(ToLocal, Name, Name) 295 MAKE_TO_LOCAL(ToLocal, String, String) 296 MAKE_TO_LOCAL(ToLocal, Symbol, Symbol) 297 MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp) 298 MAKE_TO_LOCAL(ToLocal, JSReceiver, Object) 299 MAKE_TO_LOCAL(ToLocal, JSObject, Object) 300 MAKE_TO_LOCAL(ToLocal, JSFunction, Function) 301 MAKE_TO_LOCAL(ToLocal, JSArray, Array) 302 MAKE_TO_LOCAL(ToLocal, JSMap, Map) 303 MAKE_TO_LOCAL(ToLocal, JSSet, Set) 304 MAKE_TO_LOCAL(ToLocal, JSProxy, Proxy) 305 MAKE_TO_LOCAL(ToLocal, JSArrayBuffer, ArrayBuffer) 306 MAKE_TO_LOCAL(ToLocal, JSArrayBufferView, ArrayBufferView) 307 MAKE_TO_LOCAL(ToLocal, JSDataView, DataView) 308 MAKE_TO_LOCAL(ToLocal, JSTypedArray, TypedArray) 309 MAKE_TO_LOCAL(ToLocalShared, JSArrayBuffer, SharedArrayBuffer) 310 311 TYPED_ARRAYS(MAKE_TO_LOCAL_TYPED_ARRAY) 312 313 MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate) 314 MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate) 315 MAKE_TO_LOCAL(SignatureToLocal, FunctionTemplateInfo, Signature) 316 MAKE_TO_LOCAL(AccessorSignatureToLocal, FunctionTemplateInfo, AccessorSignature) 317 MAKE_TO_LOCAL(MessageToLocal, Object, Message) 318 MAKE_TO_LOCAL(PromiseToLocal, JSObject, Promise) 319 MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace) 320 MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame) 321 MAKE_TO_LOCAL(NumberToLocal, Object, Number) 322 MAKE_TO_LOCAL(IntegerToLocal, Object, Integer) 323 MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32) 324 MAKE_TO_LOCAL(ExternalToLocal, JSObject, External) 325 MAKE_TO_LOCAL(NativeWeakMapToLocal, JSWeakMap, NativeWeakMap) 326 MAKE_TO_LOCAL(CallableToLocal, JSReceiver, Function) 327 328 #undef MAKE_TO_LOCAL_TYPED_ARRAY 329 #undef MAKE_TO_LOCAL 330 331 332 // Implementations of OpenHandle 333 334 #define MAKE_OPEN_HANDLE(From, To) \ 335 v8::internal::Handle<v8::internal::To> Utils::OpenHandle( \ 336 const v8::From* that, bool allow_empty_handle) { \ 337 DCHECK(allow_empty_handle || that != NULL); \ 338 DCHECK(that == NULL || \ 339 (*reinterpret_cast<v8::internal::Object* const*>(that))->Is##To()); \ 340 return v8::internal::Handle<v8::internal::To>( \ 341 reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \ 342 } 343 344 OPEN_HANDLE_LIST(MAKE_OPEN_HANDLE) 345 346 #undef MAKE_OPEN_HANDLE 347 #undef OPEN_HANDLE_LIST 348 349 350 namespace internal { 351 352 353 class DeferredHandles { 354 public: 355 ~DeferredHandles(); 356 357 private: 358 DeferredHandles(Object** first_block_limit, Isolate* isolate) 359 : next_(NULL), 360 previous_(NULL), 361 first_block_limit_(first_block_limit), 362 isolate_(isolate) { 363 isolate->LinkDeferredHandles(this); 364 } 365 366 void Iterate(ObjectVisitor* v); 367 368 List<Object**> blocks_; 369 DeferredHandles* next_; 370 DeferredHandles* previous_; 371 Object** first_block_limit_; 372 Isolate* isolate_; 373 374 friend class HandleScopeImplementer; 375 friend class Isolate; 376 }; 377 378 379 // This class is here in order to be able to declare it a friend of 380 // HandleScope. Moving these methods to be members of HandleScope would be 381 // neat in some ways, but it would expose internal implementation details in 382 // our public header file, which is undesirable. 383 // 384 // An isolate has a single instance of this class to hold the current thread's 385 // data. In multithreaded V8 programs this data is copied in and out of storage 386 // so that the currently executing thread always has its own copy of this 387 // data. 388 class HandleScopeImplementer { 389 public: 390 explicit HandleScopeImplementer(Isolate* isolate) 391 : isolate_(isolate), 392 blocks_(0), 393 entered_contexts_(0), 394 saved_contexts_(0), 395 microtask_context_(nullptr), 396 spare_(NULL), 397 call_depth_(0), 398 microtasks_depth_(0), 399 microtasks_suppressions_(0), 400 entered_context_count_during_microtasks_(0), 401 #ifdef DEBUG 402 debug_microtasks_depth_(0), 403 #endif 404 microtasks_policy_(v8::MicrotasksPolicy::kAuto), 405 last_handle_before_deferred_block_(NULL) { } 406 407 ~HandleScopeImplementer() { 408 DeleteArray(spare_); 409 } 410 411 // Threading support for handle data. 412 static int ArchiveSpacePerThread(); 413 char* RestoreThread(char* from); 414 char* ArchiveThread(char* to); 415 void FreeThreadResources(); 416 417 // Garbage collection support. 418 void Iterate(v8::internal::ObjectVisitor* v); 419 static char* Iterate(v8::internal::ObjectVisitor* v, char* data); 420 421 422 inline internal::Object** GetSpareOrNewBlock(); 423 inline void DeleteExtensions(internal::Object** prev_limit); 424 425 // Call depth represents nested v8 api calls. 426 inline void IncrementCallDepth() {call_depth_++;} 427 inline void DecrementCallDepth() {call_depth_--;} 428 inline bool CallDepthIsZero() { return call_depth_ == 0; } 429 430 // Microtasks scope depth represents nested scopes controlling microtasks 431 // invocation, which happens when depth reaches zero. 432 inline void IncrementMicrotasksScopeDepth() {microtasks_depth_++;} 433 inline void DecrementMicrotasksScopeDepth() {microtasks_depth_--;} 434 inline int GetMicrotasksScopeDepth() { return microtasks_depth_; } 435 436 // Possibly nested microtasks suppression scopes prevent microtasks 437 // from running. 438 inline void IncrementMicrotasksSuppressions() {microtasks_suppressions_++;} 439 inline void DecrementMicrotasksSuppressions() {microtasks_suppressions_--;} 440 inline bool HasMicrotasksSuppressions() { return !!microtasks_suppressions_; } 441 442 #ifdef DEBUG 443 // In debug we check that calls not intended to invoke microtasks are 444 // still correctly wrapped with microtask scopes. 445 inline void IncrementDebugMicrotasksScopeDepth() {debug_microtasks_depth_++;} 446 inline void DecrementDebugMicrotasksScopeDepth() {debug_microtasks_depth_--;} 447 inline bool DebugMicrotasksScopeDepthIsZero() { 448 return debug_microtasks_depth_ == 0; 449 } 450 #endif 451 452 inline void set_microtasks_policy(v8::MicrotasksPolicy policy); 453 inline v8::MicrotasksPolicy microtasks_policy() const; 454 455 inline void EnterContext(Handle<Context> context); 456 inline void LeaveContext(); 457 inline bool LastEnteredContextWas(Handle<Context> context); 458 459 // Returns the last entered context or an empty handle if no 460 // contexts have been entered. 461 inline Handle<Context> LastEnteredContext(); 462 463 inline void EnterMicrotaskContext(Handle<Context> context); 464 inline void LeaveMicrotaskContext(); 465 inline Handle<Context> MicrotaskContext(); 466 inline bool MicrotaskContextIsLastEnteredContext() const { 467 return microtask_context_ && 468 entered_context_count_during_microtasks_ == 469 entered_contexts_.length(); 470 } 471 472 inline void SaveContext(Context* context); 473 inline Context* RestoreContext(); 474 inline bool HasSavedContexts(); 475 476 inline List<internal::Object**>* blocks() { return &blocks_; } 477 Isolate* isolate() const { return isolate_; } 478 479 void ReturnBlock(Object** block) { 480 DCHECK(block != NULL); 481 if (spare_ != NULL) DeleteArray(spare_); 482 spare_ = block; 483 } 484 485 private: 486 void ResetAfterArchive() { 487 blocks_.Initialize(0); 488 entered_contexts_.Initialize(0); 489 saved_contexts_.Initialize(0); 490 microtask_context_ = nullptr; 491 entered_context_count_during_microtasks_ = 0; 492 spare_ = NULL; 493 last_handle_before_deferred_block_ = NULL; 494 call_depth_ = 0; 495 } 496 497 void Free() { 498 DCHECK(blocks_.length() == 0); 499 DCHECK(entered_contexts_.length() == 0); 500 DCHECK(saved_contexts_.length() == 0); 501 DCHECK(!microtask_context_); 502 blocks_.Free(); 503 entered_contexts_.Free(); 504 saved_contexts_.Free(); 505 if (spare_ != NULL) { 506 DeleteArray(spare_); 507 spare_ = NULL; 508 } 509 DCHECK(call_depth_ == 0); 510 } 511 512 void BeginDeferredScope(); 513 DeferredHandles* Detach(Object** prev_limit); 514 515 Isolate* isolate_; 516 List<internal::Object**> blocks_; 517 // Used as a stack to keep track of entered contexts. 518 List<Context*> entered_contexts_; 519 // Used as a stack to keep track of saved contexts. 520 List<Context*> saved_contexts_; 521 Context* microtask_context_; 522 Object** spare_; 523 int call_depth_; 524 int microtasks_depth_; 525 int microtasks_suppressions_; 526 int entered_context_count_during_microtasks_; 527 #ifdef DEBUG 528 int debug_microtasks_depth_; 529 #endif 530 v8::MicrotasksPolicy microtasks_policy_; 531 Object** last_handle_before_deferred_block_; 532 // This is only used for threading support. 533 HandleScopeData handle_scope_data_; 534 535 void IterateThis(ObjectVisitor* v); 536 char* RestoreThreadHelper(char* from); 537 char* ArchiveThreadHelper(char* to); 538 539 friend class DeferredHandles; 540 friend class DeferredHandleScope; 541 542 DISALLOW_COPY_AND_ASSIGN(HandleScopeImplementer); 543 }; 544 545 546 const int kHandleBlockSize = v8::internal::KB - 2; // fit in one page 547 548 549 void HandleScopeImplementer::set_microtasks_policy( 550 v8::MicrotasksPolicy policy) { 551 microtasks_policy_ = policy; 552 } 553 554 555 v8::MicrotasksPolicy HandleScopeImplementer::microtasks_policy() const { 556 return microtasks_policy_; 557 } 558 559 560 void HandleScopeImplementer::SaveContext(Context* context) { 561 saved_contexts_.Add(context); 562 } 563 564 565 Context* HandleScopeImplementer::RestoreContext() { 566 return saved_contexts_.RemoveLast(); 567 } 568 569 570 bool HandleScopeImplementer::HasSavedContexts() { 571 return !saved_contexts_.is_empty(); 572 } 573 574 575 void HandleScopeImplementer::EnterContext(Handle<Context> context) { 576 entered_contexts_.Add(*context); 577 } 578 579 580 void HandleScopeImplementer::LeaveContext() { 581 entered_contexts_.RemoveLast(); 582 } 583 584 585 bool HandleScopeImplementer::LastEnteredContextWas(Handle<Context> context) { 586 return !entered_contexts_.is_empty() && entered_contexts_.last() == *context; 587 } 588 589 590 Handle<Context> HandleScopeImplementer::LastEnteredContext() { 591 if (entered_contexts_.is_empty()) return Handle<Context>::null(); 592 return Handle<Context>(entered_contexts_.last()); 593 } 594 595 void HandleScopeImplementer::EnterMicrotaskContext(Handle<Context> context) { 596 DCHECK(!microtask_context_); 597 microtask_context_ = *context; 598 entered_context_count_during_microtasks_ = entered_contexts_.length(); 599 } 600 601 void HandleScopeImplementer::LeaveMicrotaskContext() { 602 DCHECK(microtask_context_); 603 microtask_context_ = nullptr; 604 entered_context_count_during_microtasks_ = 0; 605 } 606 607 Handle<Context> HandleScopeImplementer::MicrotaskContext() { 608 if (microtask_context_) return Handle<Context>(microtask_context_); 609 return Handle<Context>::null(); 610 } 611 612 // If there's a spare block, use it for growing the current scope. 613 internal::Object** HandleScopeImplementer::GetSpareOrNewBlock() { 614 internal::Object** block = (spare_ != NULL) ? 615 spare_ : 616 NewArray<internal::Object*>(kHandleBlockSize); 617 spare_ = NULL; 618 return block; 619 } 620 621 622 void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) { 623 while (!blocks_.is_empty()) { 624 internal::Object** block_start = blocks_.last(); 625 internal::Object** block_limit = block_start + kHandleBlockSize; 626 627 // SealHandleScope may make the prev_limit to point inside the block. 628 if (block_start <= prev_limit && prev_limit <= block_limit) { 629 #ifdef ENABLE_HANDLE_ZAPPING 630 internal::HandleScope::ZapRange(prev_limit, block_limit); 631 #endif 632 break; 633 } 634 635 blocks_.RemoveLast(); 636 #ifdef ENABLE_HANDLE_ZAPPING 637 internal::HandleScope::ZapRange(block_start, block_limit); 638 #endif 639 if (spare_ != NULL) { 640 DeleteArray(spare_); 641 } 642 spare_ = block_start; 643 } 644 DCHECK((blocks_.is_empty() && prev_limit == NULL) || 645 (!blocks_.is_empty() && prev_limit != NULL)); 646 } 647 648 649 // Interceptor functions called from generated inline caches to notify 650 // CPU profiler that external callbacks are invoked. 651 void InvokeAccessorGetterCallback( 652 v8::Local<v8::Name> property, 653 const v8::PropertyCallbackInfo<v8::Value>& info, 654 v8::AccessorNameGetterCallback getter); 655 656 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info, 657 v8::FunctionCallback callback); 658 659 class Testing { 660 public: 661 static v8::Testing::StressType stress_type() { return stress_type_; } 662 static void set_stress_type(v8::Testing::StressType stress_type) { 663 stress_type_ = stress_type; 664 } 665 666 private: 667 static v8::Testing::StressType stress_type_; 668 }; 669 670 } // namespace internal 671 } // namespace v8 672 673 #endif // V8_API_H_ 674