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