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