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 15 namespace v8 { 16 17 // Constants used in the implementation of the API. The most natural thing 18 // would usually be to place these with the classes that use them, but 19 // we want to keep them out of v8.h because it is an externally 20 // visible file. 21 class Consts { 22 public: 23 enum TemplateType { 24 FUNCTION_TEMPLATE = 0, 25 OBJECT_TEMPLATE = 1 26 }; 27 }; 28 29 template <typename T> inline T ToCData(v8::internal::Object* obj) { 30 STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address)); 31 if (obj == v8::internal::Smi::kZero) return nullptr; 32 return reinterpret_cast<T>( 33 reinterpret_cast<intptr_t>( 34 v8::internal::Foreign::cast(obj)->foreign_address())); 35 } 36 37 38 template <typename T> 39 inline v8::internal::Handle<v8::internal::Object> FromCData( 40 v8::internal::Isolate* isolate, T obj) { 41 STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address)); 42 if (obj == nullptr) return handle(v8::internal::Smi::kZero, isolate); 43 return isolate->factory()->NewForeign( 44 reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(obj))); 45 } 46 47 48 class ApiFunction { 49 public: 50 explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { } 51 v8::internal::Address address() { return addr_; } 52 private: 53 v8::internal::Address addr_; 54 }; 55 56 57 58 class RegisteredExtension { 59 public: 60 explicit RegisteredExtension(Extension* extension); 61 static void Register(RegisteredExtension* that); 62 static void UnregisterAll(); 63 Extension* extension() { return extension_; } 64 RegisteredExtension* next() { return next_; } 65 static RegisteredExtension* first_extension() { return first_extension_; } 66 private: 67 Extension* extension_; 68 RegisteredExtension* next_; 69 static RegisteredExtension* first_extension_; 70 }; 71 72 #define OPEN_HANDLE_LIST(V) \ 73 V(Template, TemplateInfo) \ 74 V(FunctionTemplate, FunctionTemplateInfo) \ 75 V(ObjectTemplate, ObjectTemplateInfo) \ 76 V(Signature, FunctionTemplateInfo) \ 77 V(AccessorSignature, FunctionTemplateInfo) \ 78 V(Data, Object) \ 79 V(RegExp, JSRegExp) \ 80 V(Object, JSReceiver) \ 81 V(Array, JSArray) \ 82 V(Map, JSMap) \ 83 V(Set, JSSet) \ 84 V(ArrayBuffer, JSArrayBuffer) \ 85 V(ArrayBufferView, JSArrayBufferView) \ 86 V(TypedArray, JSTypedArray) \ 87 V(Uint8Array, JSTypedArray) \ 88 V(Uint8ClampedArray, JSTypedArray) \ 89 V(Int8Array, JSTypedArray) \ 90 V(Uint16Array, JSTypedArray) \ 91 V(Int16Array, JSTypedArray) \ 92 V(Uint32Array, JSTypedArray) \ 93 V(Int32Array, JSTypedArray) \ 94 V(Float32Array, JSTypedArray) \ 95 V(Float64Array, JSTypedArray) \ 96 V(DataView, JSDataView) \ 97 V(SharedArrayBuffer, JSArrayBuffer) \ 98 V(Name, Name) \ 99 V(String, String) \ 100 V(Symbol, Symbol) \ 101 V(Script, JSFunction) \ 102 V(UnboundScript, SharedFunctionInfo) \ 103 V(Module, Module) \ 104 V(Function, JSReceiver) \ 105 V(Message, JSMessageObject) \ 106 V(Context, Context) \ 107 V(External, Object) \ 108 V(StackTrace, JSArray) \ 109 V(StackFrame, JSObject) \ 110 V(Proxy, JSProxy) \ 111 V(NativeWeakMap, JSWeakMap) \ 112 V(debug::GeneratorObject, JSGeneratorObject) \ 113 V(debug::Script, Script) \ 114 V(Promise, JSPromise) 115 116 class Utils { 117 public: 118 static inline bool ApiCheck(bool condition, 119 const char* location, 120 const char* message) { 121 if (!condition) Utils::ReportApiFailure(location, message); 122 return condition; 123 } 124 static void ReportOOMFailure(const char* location, bool is_heap_oom); 125 126 static inline Local<Context> ToLocal( 127 v8::internal::Handle<v8::internal::Context> obj); 128 static inline Local<Value> ToLocal( 129 v8::internal::Handle<v8::internal::Object> obj); 130 static inline Local<Module> ToLocal( 131 v8::internal::Handle<v8::internal::Module> obj); 132 static inline Local<Name> ToLocal( 133 v8::internal::Handle<v8::internal::Name> obj); 134 static inline Local<String> ToLocal( 135 v8::internal::Handle<v8::internal::String> obj); 136 static inline Local<Symbol> ToLocal( 137 v8::internal::Handle<v8::internal::Symbol> obj); 138 static inline Local<RegExp> ToLocal( 139 v8::internal::Handle<v8::internal::JSRegExp> obj); 140 static inline Local<Object> ToLocal( 141 v8::internal::Handle<v8::internal::JSReceiver> obj); 142 static inline Local<Object> ToLocal( 143 v8::internal::Handle<v8::internal::JSObject> obj); 144 static inline Local<Function> ToLocal( 145 v8::internal::Handle<v8::internal::JSFunction> obj); 146 static inline Local<Array> ToLocal( 147 v8::internal::Handle<v8::internal::JSArray> obj); 148 static inline Local<Map> ToLocal( 149 v8::internal::Handle<v8::internal::JSMap> obj); 150 static inline Local<Set> ToLocal( 151 v8::internal::Handle<v8::internal::JSSet> obj); 152 static inline Local<Proxy> ToLocal( 153 v8::internal::Handle<v8::internal::JSProxy> obj); 154 static inline Local<ArrayBuffer> ToLocal( 155 v8::internal::Handle<v8::internal::JSArrayBuffer> obj); 156 static inline Local<ArrayBufferView> ToLocal( 157 v8::internal::Handle<v8::internal::JSArrayBufferView> obj); 158 static inline Local<DataView> ToLocal( 159 v8::internal::Handle<v8::internal::JSDataView> obj); 160 static inline Local<TypedArray> ToLocal( 161 v8::internal::Handle<v8::internal::JSTypedArray> obj); 162 static inline Local<Uint8Array> ToLocalUint8Array( 163 v8::internal::Handle<v8::internal::JSTypedArray> obj); 164 static inline Local<Uint8ClampedArray> ToLocalUint8ClampedArray( 165 v8::internal::Handle<v8::internal::JSTypedArray> obj); 166 static inline Local<Int8Array> ToLocalInt8Array( 167 v8::internal::Handle<v8::internal::JSTypedArray> obj); 168 static inline Local<Uint16Array> ToLocalUint16Array( 169 v8::internal::Handle<v8::internal::JSTypedArray> obj); 170 static inline Local<Int16Array> ToLocalInt16Array( 171 v8::internal::Handle<v8::internal::JSTypedArray> obj); 172 static inline Local<Uint32Array> ToLocalUint32Array( 173 v8::internal::Handle<v8::internal::JSTypedArray> obj); 174 static inline Local<Int32Array> ToLocalInt32Array( 175 v8::internal::Handle<v8::internal::JSTypedArray> obj); 176 static inline Local<Float32Array> ToLocalFloat32Array( 177 v8::internal::Handle<v8::internal::JSTypedArray> obj); 178 static inline Local<Float64Array> ToLocalFloat64Array( 179 v8::internal::Handle<v8::internal::JSTypedArray> obj); 180 181 static inline Local<SharedArrayBuffer> ToLocalShared( 182 v8::internal::Handle<v8::internal::JSArrayBuffer> obj); 183 184 static inline Local<Message> MessageToLocal( 185 v8::internal::Handle<v8::internal::Object> obj); 186 static inline Local<Promise> PromiseToLocal( 187 v8::internal::Handle<v8::internal::JSObject> obj); 188 static inline Local<StackTrace> StackTraceToLocal( 189 v8::internal::Handle<v8::internal::JSArray> obj); 190 static inline Local<StackFrame> StackFrameToLocal( 191 v8::internal::Handle<v8::internal::JSObject> obj); 192 static inline Local<Number> NumberToLocal( 193 v8::internal::Handle<v8::internal::Object> obj); 194 static inline Local<Integer> IntegerToLocal( 195 v8::internal::Handle<v8::internal::Object> obj); 196 static inline Local<Uint32> Uint32ToLocal( 197 v8::internal::Handle<v8::internal::Object> obj); 198 static inline Local<FunctionTemplate> ToLocal( 199 v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj); 200 static inline Local<ObjectTemplate> ToLocal( 201 v8::internal::Handle<v8::internal::ObjectTemplateInfo> obj); 202 static inline Local<Signature> SignatureToLocal( 203 v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj); 204 static inline Local<AccessorSignature> AccessorSignatureToLocal( 205 v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj); 206 static inline Local<External> ExternalToLocal( 207 v8::internal::Handle<v8::internal::JSObject> obj); 208 static inline Local<NativeWeakMap> NativeWeakMapToLocal( 209 v8::internal::Handle<v8::internal::JSWeakMap> obj); 210 static inline Local<Function> CallableToLocal( 211 v8::internal::Handle<v8::internal::JSReceiver> obj); 212 213 #define DECLARE_OPEN_HANDLE(From, To) \ 214 static inline v8::internal::Handle<v8::internal::To> \ 215 OpenHandle(const From* that, bool allow_empty_handle = false); 216 217 OPEN_HANDLE_LIST(DECLARE_OPEN_HANDLE) 218 219 #undef DECLARE_OPEN_HANDLE 220 221 template<class From, class To> 222 static inline Local<To> Convert(v8::internal::Handle<From> obj) { 223 DCHECK(obj.is_null() || 224 (obj->IsSmi() || 225 !obj->IsTheHole(i::HeapObject::cast(*obj)->GetIsolate()))); 226 return Local<To>(reinterpret_cast<To*>(obj.location())); 227 } 228 229 template <class T> 230 static inline v8::internal::Handle<v8::internal::Object> OpenPersistent( 231 const v8::Persistent<T>& persistent) { 232 return v8::internal::Handle<v8::internal::Object>( 233 reinterpret_cast<v8::internal::Object**>(persistent.val_)); 234 } 235 236 template <class T> 237 static inline v8::internal::Handle<v8::internal::Object> OpenPersistent( 238 v8::Persistent<T>* persistent) { 239 return OpenPersistent(*persistent); 240 } 241 242 template <class From, class To> 243 static inline v8::internal::Handle<To> OpenHandle(v8::Local<From> handle) { 244 return OpenHandle(*handle); 245 } 246 247 private: 248 static void ReportApiFailure(const char* location, const char* message); 249 }; 250 251 252 template <class T> 253 inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) { 254 return reinterpret_cast<T*>(obj.location()); 255 } 256 257 template <class T> 258 inline v8::Local<T> ToApiHandle( 259 v8::internal::Handle<v8::internal::Object> obj) { 260 return Utils::Convert<v8::internal::Object, T>(obj); 261 } 262 263 264 template <class T> 265 inline bool ToLocal(v8::internal::MaybeHandle<v8::internal::Object> maybe, 266 Local<T>* local) { 267 v8::internal::Handle<v8::internal::Object> handle; 268 if (maybe.ToHandle(&handle)) { 269 *local = Utils::Convert<v8::internal::Object, T>(handle); 270 return true; 271 } 272 return false; 273 } 274 275 276 // Implementations of ToLocal 277 278 #define MAKE_TO_LOCAL(Name, From, To) \ 279 Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \ 280 return Convert<v8::internal::From, v8::To>(obj); \ 281 } 282 283 284 #define MAKE_TO_LOCAL_TYPED_ARRAY(Type, typeName, TYPE, ctype, size) \ 285 Local<v8::Type##Array> Utils::ToLocal##Type##Array( \ 286 v8::internal::Handle<v8::internal::JSTypedArray> obj) { \ 287 DCHECK(obj->type() == v8::internal::kExternal##Type##Array); \ 288 return Convert<v8::internal::JSTypedArray, v8::Type##Array>(obj); \ 289 } 290 291 292 MAKE_TO_LOCAL(ToLocal, Context, Context) 293 MAKE_TO_LOCAL(ToLocal, Object, Value) 294 MAKE_TO_LOCAL(ToLocal, Module, Module) 295 MAKE_TO_LOCAL(ToLocal, Name, Name) 296 MAKE_TO_LOCAL(ToLocal, String, String) 297 MAKE_TO_LOCAL(ToLocal, Symbol, Symbol) 298 MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp) 299 MAKE_TO_LOCAL(ToLocal, JSReceiver, Object) 300 MAKE_TO_LOCAL(ToLocal, JSObject, Object) 301 MAKE_TO_LOCAL(ToLocal, JSFunction, Function) 302 MAKE_TO_LOCAL(ToLocal, JSArray, Array) 303 MAKE_TO_LOCAL(ToLocal, JSMap, Map) 304 MAKE_TO_LOCAL(ToLocal, JSSet, Set) 305 MAKE_TO_LOCAL(ToLocal, JSProxy, Proxy) 306 MAKE_TO_LOCAL(ToLocal, JSArrayBuffer, ArrayBuffer) 307 MAKE_TO_LOCAL(ToLocal, JSArrayBufferView, ArrayBufferView) 308 MAKE_TO_LOCAL(ToLocal, JSDataView, DataView) 309 MAKE_TO_LOCAL(ToLocal, JSTypedArray, TypedArray) 310 MAKE_TO_LOCAL(ToLocalShared, JSArrayBuffer, SharedArrayBuffer) 311 312 TYPED_ARRAYS(MAKE_TO_LOCAL_TYPED_ARRAY) 313 314 MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate) 315 MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate) 316 MAKE_TO_LOCAL(SignatureToLocal, FunctionTemplateInfo, Signature) 317 MAKE_TO_LOCAL(AccessorSignatureToLocal, FunctionTemplateInfo, AccessorSignature) 318 MAKE_TO_LOCAL(MessageToLocal, Object, Message) 319 MAKE_TO_LOCAL(PromiseToLocal, JSObject, Promise) 320 MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace) 321 MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame) 322 MAKE_TO_LOCAL(NumberToLocal, Object, Number) 323 MAKE_TO_LOCAL(IntegerToLocal, Object, Integer) 324 MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32) 325 MAKE_TO_LOCAL(ExternalToLocal, JSObject, External) 326 MAKE_TO_LOCAL(NativeWeakMapToLocal, JSWeakMap, NativeWeakMap) 327 MAKE_TO_LOCAL(CallableToLocal, JSReceiver, Function) 328 329 #undef MAKE_TO_LOCAL_TYPED_ARRAY 330 #undef MAKE_TO_LOCAL 331 332 333 // Implementations of OpenHandle 334 335 #define MAKE_OPEN_HANDLE(From, To) \ 336 v8::internal::Handle<v8::internal::To> Utils::OpenHandle( \ 337 const v8::From* that, bool allow_empty_handle) { \ 338 DCHECK(allow_empty_handle || that != NULL); \ 339 DCHECK(that == NULL || \ 340 (*reinterpret_cast<v8::internal::Object* const*>(that))->Is##To()); \ 341 return v8::internal::Handle<v8::internal::To>( \ 342 reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \ 343 } 344 345 OPEN_HANDLE_LIST(MAKE_OPEN_HANDLE) 346 347 #undef MAKE_OPEN_HANDLE 348 #undef OPEN_HANDLE_LIST 349 350 351 namespace internal { 352 353 class V8_EXPORT_PRIVATE 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