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