api.h revision 25f6136652d8341ed047e7fc1a450af5bd218ea9
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
137v8::Arguments::Arguments(v8::Local<v8::Value> data,
138                         v8::Local<v8::Object> holder,
139                         v8::Local<v8::Function> callee,
140                         bool is_construct_call,
141                         void** values, int length)
142    : data_(data), holder_(holder), callee_(callee),
143      is_construct_call_(is_construct_call),
144      values_(values), length_(length) { }
145
146
147enum ExtensionTraversalState {
148  UNVISITED, VISITED, INSTALLED
149};
150
151
152class RegisteredExtension {
153 public:
154  explicit RegisteredExtension(Extension* extension);
155  static void Register(RegisteredExtension* that);
156  Extension* extension() { return extension_; }
157  RegisteredExtension* next() { return next_; }
158  RegisteredExtension* next_auto() { return next_auto_; }
159  ExtensionTraversalState state() { return state_; }
160  void set_state(ExtensionTraversalState value) { state_ = value; }
161  static RegisteredExtension* first_extension() { return first_extension_; }
162 private:
163  Extension* extension_;
164  RegisteredExtension* next_;
165  RegisteredExtension* next_auto_;
166  ExtensionTraversalState state_;
167  static RegisteredExtension* first_extension_;
168  static RegisteredExtension* first_auto_extension_;
169};
170
171
172class Utils {
173 public:
174  static bool ReportApiFailure(const char* location, const char* message);
175
176  static Local<FunctionTemplate> ToFunctionTemplate(NeanderObject obj);
177  static Local<ObjectTemplate> ToObjectTemplate(NeanderObject obj);
178
179  static inline Local<Context> ToLocal(
180      v8::internal::Handle<v8::internal::Context> obj);
181  static inline Local<Value> ToLocal(
182      v8::internal::Handle<v8::internal::Object> obj);
183  static inline Local<Function> ToLocal(
184      v8::internal::Handle<v8::internal::JSFunction> obj);
185  static inline Local<String> ToLocal(
186      v8::internal::Handle<v8::internal::String> obj);
187  static inline Local<Object> ToLocal(
188      v8::internal::Handle<v8::internal::JSObject> obj);
189  static inline Local<Array> ToLocal(
190      v8::internal::Handle<v8::internal::JSArray> obj);
191  static inline Local<External> ToLocal(
192      v8::internal::Handle<v8::internal::Proxy> obj);
193  static inline Local<Message> MessageToLocal(
194      v8::internal::Handle<v8::internal::Object> obj);
195  static inline Local<StackTrace> StackTraceToLocal(
196      v8::internal::Handle<v8::internal::JSArray> obj);
197  static inline Local<StackFrame> StackFrameToLocal(
198      v8::internal::Handle<v8::internal::JSObject> obj);
199  static inline Local<Number> NumberToLocal(
200      v8::internal::Handle<v8::internal::Object> obj);
201  static inline Local<Integer> IntegerToLocal(
202      v8::internal::Handle<v8::internal::Object> obj);
203  static inline Local<Uint32> Uint32ToLocal(
204      v8::internal::Handle<v8::internal::Object> obj);
205  static inline Local<FunctionTemplate> ToLocal(
206      v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
207  static inline Local<ObjectTemplate> ToLocal(
208      v8::internal::Handle<v8::internal::ObjectTemplateInfo> obj);
209  static inline Local<Signature> ToLocal(
210      v8::internal::Handle<v8::internal::SignatureInfo> obj);
211  static inline Local<TypeSwitch> ToLocal(
212      v8::internal::Handle<v8::internal::TypeSwitchInfo> obj);
213
214  static inline v8::internal::Handle<v8::internal::TemplateInfo>
215      OpenHandle(const Template* that);
216  static inline v8::internal::Handle<v8::internal::FunctionTemplateInfo>
217      OpenHandle(const FunctionTemplate* that);
218  static inline v8::internal::Handle<v8::internal::ObjectTemplateInfo>
219      OpenHandle(const ObjectTemplate* that);
220  static inline v8::internal::Handle<v8::internal::Object>
221      OpenHandle(const Data* data);
222  static inline v8::internal::Handle<v8::internal::JSObject>
223      OpenHandle(const v8::Object* data);
224  static inline v8::internal::Handle<v8::internal::JSArray>
225      OpenHandle(const v8::Array* data);
226  static inline v8::internal::Handle<v8::internal::String>
227      OpenHandle(const String* data);
228  static inline v8::internal::Handle<v8::internal::Object>
229      OpenHandle(const Script* data);
230  static inline v8::internal::Handle<v8::internal::JSFunction>
231      OpenHandle(const Function* data);
232  static inline v8::internal::Handle<v8::internal::JSObject>
233      OpenHandle(const Message* message);
234  static inline v8::internal::Handle<v8::internal::JSArray>
235      OpenHandle(const StackTrace* stack_trace);
236  static inline v8::internal::Handle<v8::internal::JSObject>
237      OpenHandle(const StackFrame* stack_frame);
238  static inline v8::internal::Handle<v8::internal::Context>
239      OpenHandle(const v8::Context* context);
240  static inline v8::internal::Handle<v8::internal::SignatureInfo>
241      OpenHandle(const v8::Signature* sig);
242  static inline v8::internal::Handle<v8::internal::TypeSwitchInfo>
243      OpenHandle(const v8::TypeSwitch* that);
244  static inline v8::internal::Handle<v8::internal::Proxy>
245      OpenHandle(const v8::External* that);
246};
247
248
249template <class T>
250static inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) {
251  return reinterpret_cast<T*>(obj.location());
252}
253
254
255template <class T>
256v8::internal::Handle<T> v8::internal::Handle<T>::EscapeFrom(
257    v8::HandleScope* scope) {
258  v8::internal::Handle<T> handle;
259  if (!is_null()) {
260    handle = *this;
261  }
262  return Utils::OpenHandle(*scope->Close(Utils::ToLocal(handle)));
263}
264
265
266// Implementations of ToLocal
267
268#define MAKE_TO_LOCAL(Name, From, To)                                       \
269  Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \
270    ASSERT(obj.is_null() || !obj->IsTheHole());                             \
271    return Local<To>(reinterpret_cast<To*>(obj.location()));                \
272  }
273
274MAKE_TO_LOCAL(ToLocal, Context, Context)
275MAKE_TO_LOCAL(ToLocal, Object, Value)
276MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
277MAKE_TO_LOCAL(ToLocal, String, String)
278MAKE_TO_LOCAL(ToLocal, JSObject, Object)
279MAKE_TO_LOCAL(ToLocal, JSArray, Array)
280MAKE_TO_LOCAL(ToLocal, Proxy, External)
281MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate)
282MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate)
283MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature)
284MAKE_TO_LOCAL(ToLocal, TypeSwitchInfo, TypeSwitch)
285MAKE_TO_LOCAL(MessageToLocal, Object, Message)
286MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace)
287MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame)
288MAKE_TO_LOCAL(NumberToLocal, Object, Number)
289MAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
290MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)
291
292#undef MAKE_TO_LOCAL
293
294
295// Implementations of OpenHandle
296
297#define MAKE_OPEN_HANDLE(From, To) \
298  v8::internal::Handle<v8::internal::To> Utils::OpenHandle(\
299    const v8::From* that) { \
300    return v8::internal::Handle<v8::internal::To>( \
301        reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \
302  }
303
304MAKE_OPEN_HANDLE(Template, TemplateInfo)
305MAKE_OPEN_HANDLE(FunctionTemplate, FunctionTemplateInfo)
306MAKE_OPEN_HANDLE(ObjectTemplate, ObjectTemplateInfo)
307MAKE_OPEN_HANDLE(Signature, SignatureInfo)
308MAKE_OPEN_HANDLE(TypeSwitch, TypeSwitchInfo)
309MAKE_OPEN_HANDLE(Data, Object)
310MAKE_OPEN_HANDLE(Object, JSObject)
311MAKE_OPEN_HANDLE(Array, JSArray)
312MAKE_OPEN_HANDLE(String, String)
313MAKE_OPEN_HANDLE(Script, Object)
314MAKE_OPEN_HANDLE(Function, JSFunction)
315MAKE_OPEN_HANDLE(Message, JSObject)
316MAKE_OPEN_HANDLE(Context, Context)
317MAKE_OPEN_HANDLE(External, Proxy)
318MAKE_OPEN_HANDLE(StackTrace, JSArray)
319MAKE_OPEN_HANDLE(StackFrame, JSObject)
320
321#undef MAKE_OPEN_HANDLE
322
323
324namespace internal {
325
326// This class is here in order to be able to declare it a friend of
327// HandleScope.  Moving these methods to be members of HandleScope would be
328// neat in some ways, but it would expose external implementation details in
329// our public header file, which is undesirable.
330//
331// There is a singleton instance of this class to hold the per-thread data.
332// For multithreaded V8 programs this data is copied in and out of storage
333// so that the currently executing thread always has its own copy of this
334// data.
335class HandleScopeImplementer {
336 public:
337
338  HandleScopeImplementer()
339      : blocks_(0),
340        entered_contexts_(0),
341        saved_contexts_(0),
342        spare_(NULL),
343        ignore_out_of_memory_(false),
344        call_depth_(0) { }
345
346  static HandleScopeImplementer* instance();
347
348  // Threading support for handle data.
349  static int ArchiveSpacePerThread();
350  static char* RestoreThread(char* from);
351  static char* ArchiveThread(char* to);
352  static void FreeThreadResources();
353
354  // Garbage collection support.
355  static void Iterate(v8::internal::ObjectVisitor* v);
356  static char* Iterate(v8::internal::ObjectVisitor* v, char* data);
357
358
359  inline internal::Object** GetSpareOrNewBlock();
360  inline void DeleteExtensions(int extensions);
361
362  inline void IncrementCallDepth() {call_depth_++;}
363  inline void DecrementCallDepth() {call_depth_--;}
364  inline bool CallDepthIsZero() { return call_depth_ == 0; }
365
366  inline void EnterContext(Handle<Object> context);
367  inline bool LeaveLastContext();
368
369  // Returns the last entered context or an empty handle if no
370  // contexts have been entered.
371  inline Handle<Object> LastEnteredContext();
372
373  inline void SaveContext(Context* context);
374  inline Context* RestoreContext();
375  inline bool HasSavedContexts();
376
377  inline List<internal::Object**>* blocks() { return &blocks_; }
378  inline bool ignore_out_of_memory() { return ignore_out_of_memory_; }
379  inline void set_ignore_out_of_memory(bool value) {
380    ignore_out_of_memory_ = value;
381  }
382
383 private:
384  void ResetAfterArchive() {
385    blocks_.Initialize(0);
386    entered_contexts_.Initialize(0);
387    saved_contexts_.Initialize(0);
388    spare_ = NULL;
389    ignore_out_of_memory_ = false;
390    call_depth_ = 0;
391  }
392
393  void Free() {
394    ASSERT(blocks_.length() == 0);
395    ASSERT(entered_contexts_.length() == 0);
396    ASSERT(saved_contexts_.length() == 0);
397    blocks_.Free();
398    entered_contexts_.Free();
399    saved_contexts_.Free();
400    if (spare_ != NULL) {
401      DeleteArray(spare_);
402      spare_ = NULL;
403    }
404    ASSERT(call_depth_ == 0);
405  }
406
407  List<internal::Object**> blocks_;
408  // Used as a stack to keep track of entered contexts.
409  List<Handle<Object> > entered_contexts_;
410  // Used as a stack to keep track of saved contexts.
411  List<Context*> saved_contexts_;
412  Object** spare_;
413  bool ignore_out_of_memory_;
414  int call_depth_;
415  // This is only used for threading support.
416  v8::ImplementationUtilities::HandleScopeData handle_scope_data_;
417
418  void IterateThis(ObjectVisitor* v);
419  char* RestoreThreadHelper(char* from);
420  char* ArchiveThreadHelper(char* to);
421
422  DISALLOW_COPY_AND_ASSIGN(HandleScopeImplementer);
423};
424
425
426static const int kHandleBlockSize = v8::internal::KB - 2;  // fit in one page
427
428
429void HandleScopeImplementer::SaveContext(Context* context) {
430  saved_contexts_.Add(context);
431}
432
433
434Context* HandleScopeImplementer::RestoreContext() {
435  return saved_contexts_.RemoveLast();
436}
437
438
439bool HandleScopeImplementer::HasSavedContexts() {
440  return !saved_contexts_.is_empty();
441}
442
443
444void HandleScopeImplementer::EnterContext(Handle<Object> context) {
445  entered_contexts_.Add(context);
446}
447
448
449bool HandleScopeImplementer::LeaveLastContext() {
450  if (entered_contexts_.is_empty()) return false;
451  entered_contexts_.RemoveLast();
452  return true;
453}
454
455
456Handle<Object> HandleScopeImplementer::LastEnteredContext() {
457  if (entered_contexts_.is_empty()) return Handle<Object>::null();
458  return entered_contexts_.last();
459}
460
461
462// If there's a spare block, use it for growing the current scope.
463internal::Object** HandleScopeImplementer::GetSpareOrNewBlock() {
464  internal::Object** block = (spare_ != NULL) ?
465      spare_ :
466      NewArray<internal::Object*>(kHandleBlockSize);
467  spare_ = NULL;
468  return block;
469}
470
471
472void HandleScopeImplementer::DeleteExtensions(int extensions) {
473  if (spare_ != NULL) {
474    DeleteArray(spare_);
475    spare_ = NULL;
476  }
477  for (int i = extensions; i > 1; --i) {
478    internal::Object** block = blocks_.RemoveLast();
479#ifdef DEBUG
480    v8::ImplementationUtilities::ZapHandleRange(block,
481                                                &block[kHandleBlockSize]);
482#endif
483    DeleteArray(block);
484  }
485  spare_ = blocks_.RemoveLast();
486#ifdef DEBUG
487  v8::ImplementationUtilities::ZapHandleRange(
488      spare_,
489      &spare_[kHandleBlockSize]);
490#endif
491}
492
493} }  // namespace v8::internal
494
495#endif  // V8_API_H_
496