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