1 // Copyright 2008 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 "apiutils.h" 32 #include "factory.h" 33 34 #include "../include/v8-testing.h" 35 36 namespace v8 { 37 38 // Constants used in the implementation of the API. The most natural thing 39 // would usually be to place these with the classes that use them, but 40 // we want to keep them out of v8.h because it is an externally 41 // visible file. 42 class Consts { 43 public: 44 enum TemplateType { 45 FUNCTION_TEMPLATE = 0, 46 OBJECT_TEMPLATE = 1 47 }; 48 }; 49 50 51 // Utilities for working with neander-objects, primitive 52 // env-independent JSObjects used by the api. 53 class NeanderObject { 54 public: 55 explicit NeanderObject(int size); 56 explicit inline NeanderObject(v8::internal::Handle<v8::internal::Object> obj); 57 explicit inline NeanderObject(v8::internal::Object* obj); 58 inline v8::internal::Object* get(int index); 59 inline void set(int index, v8::internal::Object* value); 60 inline v8::internal::Handle<v8::internal::JSObject> value() { return value_; } 61 int size(); 62 private: 63 v8::internal::Handle<v8::internal::JSObject> value_; 64 }; 65 66 67 // Utilities for working with neander-arrays, a simple extensible 68 // array abstraction built on neander-objects. 69 class NeanderArray { 70 public: 71 NeanderArray(); 72 explicit inline NeanderArray(v8::internal::Handle<v8::internal::Object> obj); 73 inline v8::internal::Handle<v8::internal::JSObject> value() { 74 return obj_.value(); 75 } 76 77 void add(v8::internal::Handle<v8::internal::Object> value); 78 79 int length(); 80 81 v8::internal::Object* get(int index); 82 // Change the value at an index to undefined value. If the index is 83 // out of bounds, the request is ignored. Returns the old value. 84 void set(int index, v8::internal::Object* value); 85 private: 86 NeanderObject obj_; 87 }; 88 89 90 NeanderObject::NeanderObject(v8::internal::Handle<v8::internal::Object> obj) 91 : value_(v8::internal::Handle<v8::internal::JSObject>::cast(obj)) { } 92 93 94 NeanderObject::NeanderObject(v8::internal::Object* obj) 95 : value_(v8::internal::Handle<v8::internal::JSObject>( 96 v8::internal::JSObject::cast(obj))) { } 97 98 99 NeanderArray::NeanderArray(v8::internal::Handle<v8::internal::Object> obj) 100 : obj_(obj) { } 101 102 103 v8::internal::Object* NeanderObject::get(int offset) { 104 ASSERT(value()->HasFastElements()); 105 return v8::internal::FixedArray::cast(value()->elements())->get(offset); 106 } 107 108 109 void NeanderObject::set(int offset, v8::internal::Object* value) { 110 ASSERT(value_->HasFastElements()); 111 v8::internal::FixedArray::cast(value_->elements())->set(offset, value); 112 } 113 114 115 template <typename T> static inline T ToCData(v8::internal::Object* obj) { 116 STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address)); 117 return reinterpret_cast<T>( 118 reinterpret_cast<intptr_t>(v8::internal::Proxy::cast(obj)->proxy())); 119 } 120 121 122 template <typename T> 123 static inline v8::internal::Handle<v8::internal::Object> FromCData(T obj) { 124 STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address)); 125 return FACTORY->NewProxy( 126 reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(obj))); 127 } 128 129 130 class ApiFunction { 131 public: 132 explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { } 133 v8::internal::Address address() { return addr_; } 134 private: 135 v8::internal::Address addr_; 136 }; 137 138 139 enum ExtensionTraversalState { 140 UNVISITED, VISITED, INSTALLED 141 }; 142 143 144 class RegisteredExtension { 145 public: 146 explicit RegisteredExtension(Extension* extension); 147 static void Register(RegisteredExtension* that); 148 Extension* extension() { return extension_; } 149 RegisteredExtension* next() { return next_; } 150 RegisteredExtension* next_auto() { return next_auto_; } 151 ExtensionTraversalState state() { return state_; } 152 void set_state(ExtensionTraversalState value) { state_ = value; } 153 static RegisteredExtension* first_extension() { return first_extension_; } 154 private: 155 Extension* extension_; 156 RegisteredExtension* next_; 157 RegisteredExtension* next_auto_; 158 ExtensionTraversalState state_; 159 static RegisteredExtension* first_extension_; 160 }; 161 162 163 class Utils { 164 public: 165 static bool ReportApiFailure(const char* location, const char* message); 166 167 static Local<FunctionTemplate> ToFunctionTemplate(NeanderObject obj); 168 static Local<ObjectTemplate> ToObjectTemplate(NeanderObject obj); 169 170 static inline Local<Context> ToLocal( 171 v8::internal::Handle<v8::internal::Context> obj); 172 static inline Local<Value> ToLocal( 173 v8::internal::Handle<v8::internal::Object> obj); 174 static inline Local<Function> ToLocal( 175 v8::internal::Handle<v8::internal::JSFunction> obj); 176 static inline Local<String> ToLocal( 177 v8::internal::Handle<v8::internal::String> obj); 178 static inline Local<RegExp> ToLocal( 179 v8::internal::Handle<v8::internal::JSRegExp> obj); 180 static inline Local<Object> ToLocal( 181 v8::internal::Handle<v8::internal::JSObject> obj); 182 static inline Local<Array> ToLocal( 183 v8::internal::Handle<v8::internal::JSArray> obj); 184 static inline Local<External> ToLocal( 185 v8::internal::Handle<v8::internal::Proxy> obj); 186 static inline Local<Message> MessageToLocal( 187 v8::internal::Handle<v8::internal::Object> 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> ToLocal( 203 v8::internal::Handle<v8::internal::SignatureInfo> obj); 204 static inline Local<TypeSwitch> ToLocal( 205 v8::internal::Handle<v8::internal::TypeSwitchInfo> obj); 206 207 static inline v8::internal::Handle<v8::internal::TemplateInfo> 208 OpenHandle(const Template* that); 209 static inline v8::internal::Handle<v8::internal::FunctionTemplateInfo> 210 OpenHandle(const FunctionTemplate* that); 211 static inline v8::internal::Handle<v8::internal::ObjectTemplateInfo> 212 OpenHandle(const ObjectTemplate* that); 213 static inline v8::internal::Handle<v8::internal::Object> 214 OpenHandle(const Data* data); 215 static inline v8::internal::Handle<v8::internal::JSRegExp> 216 OpenHandle(const RegExp* data); 217 static inline v8::internal::Handle<v8::internal::JSObject> 218 OpenHandle(const v8::Object* data); 219 static inline v8::internal::Handle<v8::internal::JSArray> 220 OpenHandle(const v8::Array* data); 221 static inline v8::internal::Handle<v8::internal::String> 222 OpenHandle(const String* data); 223 static inline v8::internal::Handle<v8::internal::Object> 224 OpenHandle(const Script* data); 225 static inline v8::internal::Handle<v8::internal::JSFunction> 226 OpenHandle(const Function* data); 227 static inline v8::internal::Handle<v8::internal::JSObject> 228 OpenHandle(const Message* message); 229 static inline v8::internal::Handle<v8::internal::JSArray> 230 OpenHandle(const StackTrace* stack_trace); 231 static inline v8::internal::Handle<v8::internal::JSObject> 232 OpenHandle(const StackFrame* stack_frame); 233 static inline v8::internal::Handle<v8::internal::Context> 234 OpenHandle(const v8::Context* context); 235 static inline v8::internal::Handle<v8::internal::SignatureInfo> 236 OpenHandle(const v8::Signature* sig); 237 static inline v8::internal::Handle<v8::internal::TypeSwitchInfo> 238 OpenHandle(const v8::TypeSwitch* that); 239 static inline v8::internal::Handle<v8::internal::Proxy> 240 OpenHandle(const v8::External* that); 241 }; 242 243 244 template <class T> 245 static inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) { 246 return reinterpret_cast<T*>(obj.location()); 247 } 248 249 250 template <class T> 251 v8::internal::Handle<T> v8::internal::Handle<T>::EscapeFrom( 252 v8::HandleScope* scope) { 253 v8::internal::Handle<T> handle; 254 if (!is_null()) { 255 handle = *this; 256 } 257 return Utils::OpenHandle(*scope->Close(Utils::ToLocal(handle))); 258 } 259 260 261 // Implementations of ToLocal 262 263 #define MAKE_TO_LOCAL(Name, From, To) \ 264 Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \ 265 ASSERT(obj.is_null() || !obj->IsTheHole()); \ 266 return Local<To>(reinterpret_cast<To*>(obj.location())); \ 267 } 268 269 MAKE_TO_LOCAL(ToLocal, Context, Context) 270 MAKE_TO_LOCAL(ToLocal, Object, Value) 271 MAKE_TO_LOCAL(ToLocal, JSFunction, Function) 272 MAKE_TO_LOCAL(ToLocal, String, String) 273 MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp) 274 MAKE_TO_LOCAL(ToLocal, JSObject, Object) 275 MAKE_TO_LOCAL(ToLocal, JSArray, Array) 276 MAKE_TO_LOCAL(ToLocal, Proxy, External) 277 MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate) 278 MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate) 279 MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature) 280 MAKE_TO_LOCAL(ToLocal, TypeSwitchInfo, TypeSwitch) 281 MAKE_TO_LOCAL(MessageToLocal, Object, Message) 282 MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace) 283 MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame) 284 MAKE_TO_LOCAL(NumberToLocal, Object, Number) 285 MAKE_TO_LOCAL(IntegerToLocal, Object, Integer) 286 MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32) 287 288 #undef MAKE_TO_LOCAL 289 290 291 // Implementations of OpenHandle 292 293 #define MAKE_OPEN_HANDLE(From, To) \ 294 v8::internal::Handle<v8::internal::To> Utils::OpenHandle(\ 295 const v8::From* that) { \ 296 return v8::internal::Handle<v8::internal::To>( \ 297 reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \ 298 } 299 300 MAKE_OPEN_HANDLE(Template, TemplateInfo) 301 MAKE_OPEN_HANDLE(FunctionTemplate, FunctionTemplateInfo) 302 MAKE_OPEN_HANDLE(ObjectTemplate, ObjectTemplateInfo) 303 MAKE_OPEN_HANDLE(Signature, SignatureInfo) 304 MAKE_OPEN_HANDLE(TypeSwitch, TypeSwitchInfo) 305 MAKE_OPEN_HANDLE(Data, Object) 306 MAKE_OPEN_HANDLE(RegExp, JSRegExp) 307 MAKE_OPEN_HANDLE(Object, JSObject) 308 MAKE_OPEN_HANDLE(Array, JSArray) 309 MAKE_OPEN_HANDLE(String, String) 310 MAKE_OPEN_HANDLE(Script, Object) 311 MAKE_OPEN_HANDLE(Function, JSFunction) 312 MAKE_OPEN_HANDLE(Message, JSObject) 313 MAKE_OPEN_HANDLE(Context, Context) 314 MAKE_OPEN_HANDLE(External, Proxy) 315 MAKE_OPEN_HANDLE(StackTrace, JSArray) 316 MAKE_OPEN_HANDLE(StackFrame, JSObject) 317 318 #undef MAKE_OPEN_HANDLE 319 320 321 namespace internal { 322 323 // Tracks string usage to help make better decisions when 324 // externalizing strings. 325 // 326 // Implementation note: internally this class only tracks fresh 327 // strings and keeps a single use counter for them. 328 class StringTracker { 329 public: 330 // Records that the given string's characters were copied to some 331 // external buffer. If this happens often we should honor 332 // externalization requests for the string. 333 void RecordWrite(Handle<String> string) { 334 Address address = reinterpret_cast<Address>(*string); 335 Address top = isolate_->heap()->NewSpaceTop(); 336 if (IsFreshString(address, top)) { 337 IncrementUseCount(top); 338 } 339 } 340 341 // Estimates freshness and use frequency of the given string based 342 // on how close it is to the new space top and the recorded usage 343 // history. 344 inline bool IsFreshUnusedString(Handle<String> string) { 345 Address address = reinterpret_cast<Address>(*string); 346 Address top = isolate_->heap()->NewSpaceTop(); 347 return IsFreshString(address, top) && IsUseCountLow(top); 348 } 349 350 private: 351 StringTracker() : use_count_(0), last_top_(NULL), isolate_(NULL) { } 352 353 static inline bool IsFreshString(Address string, Address top) { 354 return top - kFreshnessLimit <= string && string <= top; 355 } 356 357 inline bool IsUseCountLow(Address top) { 358 if (last_top_ != top) return true; 359 return use_count_ < kUseLimit; 360 } 361 362 inline void IncrementUseCount(Address top) { 363 if (last_top_ != top) { 364 use_count_ = 0; 365 last_top_ = top; 366 } 367 ++use_count_; 368 } 369 370 // Single use counter shared by all fresh strings. 371 int use_count_; 372 373 // Last new space top when the use count above was valid. 374 Address last_top_; 375 376 Isolate* isolate_; 377 378 // How close to the new space top a fresh string has to be. 379 static const int kFreshnessLimit = 1024; 380 381 // The number of uses required to consider a string useful. 382 static const int kUseLimit = 32; 383 384 friend class Isolate; 385 386 DISALLOW_COPY_AND_ASSIGN(StringTracker); 387 }; 388 389 390 // This class is here in order to be able to declare it a friend of 391 // HandleScope. Moving these methods to be members of HandleScope would be 392 // neat in some ways, but it would expose internal implementation details in 393 // our public header file, which is undesirable. 394 // 395 // An isolate has a single instance of this class to hold the current thread's 396 // data. In multithreaded V8 programs this data is copied in and out of storage 397 // so that the currently executing thread always has its own copy of this 398 // data. 399 ISOLATED_CLASS HandleScopeImplementer { 400 public: 401 402 HandleScopeImplementer() 403 : blocks_(0), 404 entered_contexts_(0), 405 saved_contexts_(0), 406 spare_(NULL), 407 call_depth_(0) { } 408 409 // Threading support for handle data. 410 static int ArchiveSpacePerThread(); 411 char* RestoreThread(char* from); 412 char* ArchiveThread(char* to); 413 void FreeThreadResources(); 414 415 // Garbage collection support. 416 void Iterate(v8::internal::ObjectVisitor* v); 417 static char* Iterate(v8::internal::ObjectVisitor* v, char* data); 418 419 420 inline internal::Object** GetSpareOrNewBlock(); 421 inline void DeleteExtensions(internal::Object** prev_limit); 422 423 inline void IncrementCallDepth() {call_depth_++;} 424 inline void DecrementCallDepth() {call_depth_--;} 425 inline bool CallDepthIsZero() { return call_depth_ == 0; } 426 427 inline void EnterContext(Handle<Object> context); 428 inline bool LeaveLastContext(); 429 430 // Returns the last entered context or an empty handle if no 431 // contexts have been entered. 432 inline Handle<Object> LastEnteredContext(); 433 434 inline void SaveContext(Context* context); 435 inline Context* RestoreContext(); 436 inline bool HasSavedContexts(); 437 438 inline List<internal::Object**>* blocks() { return &blocks_; } 439 440 private: 441 void ResetAfterArchive() { 442 blocks_.Initialize(0); 443 entered_contexts_.Initialize(0); 444 saved_contexts_.Initialize(0); 445 spare_ = NULL; 446 call_depth_ = 0; 447 } 448 449 void Free() { 450 ASSERT(blocks_.length() == 0); 451 ASSERT(entered_contexts_.length() == 0); 452 ASSERT(saved_contexts_.length() == 0); 453 blocks_.Free(); 454 entered_contexts_.Free(); 455 saved_contexts_.Free(); 456 if (spare_ != NULL) { 457 DeleteArray(spare_); 458 spare_ = NULL; 459 } 460 ASSERT(call_depth_ == 0); 461 } 462 463 List<internal::Object**> blocks_; 464 // Used as a stack to keep track of entered contexts. 465 List<Handle<Object> > entered_contexts_; 466 // Used as a stack to keep track of saved contexts. 467 List<Context*> saved_contexts_; 468 Object** spare_; 469 int call_depth_; 470 // This is only used for threading support. 471 v8::ImplementationUtilities::HandleScopeData handle_scope_data_; 472 473 void IterateThis(ObjectVisitor* v); 474 char* RestoreThreadHelper(char* from); 475 char* ArchiveThreadHelper(char* to); 476 477 DISALLOW_COPY_AND_ASSIGN(HandleScopeImplementer); 478 }; 479 480 481 static const int kHandleBlockSize = v8::internal::KB - 2; // fit in one page 482 483 484 void HandleScopeImplementer::SaveContext(Context* context) { 485 saved_contexts_.Add(context); 486 } 487 488 489 Context* HandleScopeImplementer::RestoreContext() { 490 return saved_contexts_.RemoveLast(); 491 } 492 493 494 bool HandleScopeImplementer::HasSavedContexts() { 495 return !saved_contexts_.is_empty(); 496 } 497 498 499 void HandleScopeImplementer::EnterContext(Handle<Object> context) { 500 entered_contexts_.Add(context); 501 } 502 503 504 bool HandleScopeImplementer::LeaveLastContext() { 505 if (entered_contexts_.is_empty()) return false; 506 entered_contexts_.RemoveLast(); 507 return true; 508 } 509 510 511 Handle<Object> HandleScopeImplementer::LastEnteredContext() { 512 if (entered_contexts_.is_empty()) return Handle<Object>::null(); 513 return entered_contexts_.last(); 514 } 515 516 517 // If there's a spare block, use it for growing the current scope. 518 internal::Object** HandleScopeImplementer::GetSpareOrNewBlock() { 519 internal::Object** block = (spare_ != NULL) ? 520 spare_ : 521 NewArray<internal::Object*>(kHandleBlockSize); 522 spare_ = NULL; 523 return block; 524 } 525 526 527 void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) { 528 while (!blocks_.is_empty()) { 529 internal::Object** block_start = blocks_.last(); 530 internal::Object** block_limit = block_start + kHandleBlockSize; 531 #ifdef DEBUG 532 // NoHandleAllocation may make the prev_limit to point inside the block. 533 if (block_start <= prev_limit && prev_limit <= block_limit) break; 534 #else 535 if (prev_limit == block_limit) break; 536 #endif 537 538 blocks_.RemoveLast(); 539 #ifdef DEBUG 540 v8::ImplementationUtilities::ZapHandleRange(block_start, block_limit); 541 #endif 542 if (spare_ != NULL) { 543 DeleteArray(spare_); 544 } 545 spare_ = block_start; 546 } 547 ASSERT((blocks_.is_empty() && prev_limit == NULL) || 548 (!blocks_.is_empty() && prev_limit != NULL)); 549 } 550 551 552 class Testing { 553 public: 554 static v8::Testing::StressType stress_type() { return stress_type_; } 555 static void set_stress_type(v8::Testing::StressType stress_type) { 556 stress_type_ = stress_type; 557 } 558 559 private: 560 static v8::Testing::StressType stress_type_; 561 }; 562 563 } } // namespace v8::internal 564 565 #endif // V8_API_H_ 566