blob: a825dd79708580d881002d0fdc7211b9aaccb41d [file] [log] [blame]
Ben Murdoch257744e2011-11-30 15:57:28 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// 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
Ben Murdochb0fe1622011-05-05 13:52:32 +010034#include "../include/v8-testing.h"
35
Steve Blocka7e24c12009-10-30 11:49:00 +000036namespace 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.
42class 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.
53class NeanderObject {
54 public:
55 explicit NeanderObject(int size);
Ben Murdoch8b112d22011-06-08 16:22:53 +010056 explicit inline NeanderObject(v8::internal::Handle<v8::internal::Object> obj);
57 explicit inline NeanderObject(v8::internal::Object* obj);
Steve Blocka7e24c12009-10-30 11:49:00 +000058 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.
69class NeanderArray {
70 public:
71 NeanderArray();
Ben Murdoch8b112d22011-06-08 16:22:53 +010072 explicit inline NeanderArray(v8::internal::Handle<v8::internal::Object> obj);
Steve Blocka7e24c12009-10-30 11:49:00 +000073 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
90NeanderObject::NeanderObject(v8::internal::Handle<v8::internal::Object> obj)
91 : value_(v8::internal::Handle<v8::internal::JSObject>::cast(obj)) { }
92
93
94NeanderObject::NeanderObject(v8::internal::Object* obj)
95 : value_(v8::internal::Handle<v8::internal::JSObject>(
96 v8::internal::JSObject::cast(obj))) { }
97
98
99NeanderArray::NeanderArray(v8::internal::Handle<v8::internal::Object> obj)
100 : obj_(obj) { }
101
102
103v8::internal::Object* NeanderObject::get(int offset) {
104 ASSERT(value()->HasFastElements());
105 return v8::internal::FixedArray::cast(value()->elements())->get(offset);
106}
107
108
109void 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
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000115template <typename T> inline T ToCData(v8::internal::Object* obj) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000116 STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
117 return reinterpret_cast<T>(
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000118 reinterpret_cast<intptr_t>(
119 v8::internal::Foreign::cast(obj)->foreign_address()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000120}
121
122
123template <typename T>
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000124inline v8::internal::Handle<v8::internal::Object> FromCData(T obj) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000125 STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
Ben Murdoch257744e2011-11-30 15:57:28 +0000126 return FACTORY->NewForeign(
Steve Blocka7e24c12009-10-30 11:49:00 +0000127 reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(obj)));
128}
129
130
Steve Blockd0582a62009-12-15 09:54:21 +0000131class ApiFunction {
132 public:
133 explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { }
134 v8::internal::Address address() { return addr_; }
135 private:
136 v8::internal::Address addr_;
137};
138
139
Steve Blocka7e24c12009-10-30 11:49:00 +0000140
141class RegisteredExtension {
142 public:
143 explicit RegisteredExtension(Extension* extension);
144 static void Register(RegisteredExtension* that);
145 Extension* extension() { return extension_; }
146 RegisteredExtension* next() { return next_; }
147 RegisteredExtension* next_auto() { return next_auto_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000148 static RegisteredExtension* first_extension() { return first_extension_; }
149 private:
150 Extension* extension_;
151 RegisteredExtension* next_;
152 RegisteredExtension* next_auto_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000153 static RegisteredExtension* first_extension_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000154};
155
156
157class Utils {
158 public:
159 static bool ReportApiFailure(const char* location, const char* message);
160
161 static Local<FunctionTemplate> ToFunctionTemplate(NeanderObject obj);
162 static Local<ObjectTemplate> ToObjectTemplate(NeanderObject obj);
163
164 static inline Local<Context> ToLocal(
165 v8::internal::Handle<v8::internal::Context> obj);
166 static inline Local<Value> ToLocal(
167 v8::internal::Handle<v8::internal::Object> obj);
168 static inline Local<Function> ToLocal(
169 v8::internal::Handle<v8::internal::JSFunction> obj);
170 static inline Local<String> ToLocal(
171 v8::internal::Handle<v8::internal::String> obj);
Ben Murdochf87a2032010-10-22 12:50:53 +0100172 static inline Local<RegExp> ToLocal(
173 v8::internal::Handle<v8::internal::JSRegExp> obj);
Steve Blocka7e24c12009-10-30 11:49:00 +0000174 static inline Local<Object> ToLocal(
175 v8::internal::Handle<v8::internal::JSObject> obj);
176 static inline Local<Array> ToLocal(
177 v8::internal::Handle<v8::internal::JSArray> obj);
178 static inline Local<External> ToLocal(
Ben Murdoch257744e2011-11-30 15:57:28 +0000179 v8::internal::Handle<v8::internal::Foreign> obj);
Steve Blocka7e24c12009-10-30 11:49:00 +0000180 static inline Local<Message> MessageToLocal(
181 v8::internal::Handle<v8::internal::Object> obj);
Kristian Monsen25f61362010-05-21 11:50:48 +0100182 static inline Local<StackTrace> StackTraceToLocal(
183 v8::internal::Handle<v8::internal::JSArray> obj);
184 static inline Local<StackFrame> StackFrameToLocal(
185 v8::internal::Handle<v8::internal::JSObject> obj);
Steve Blocka7e24c12009-10-30 11:49:00 +0000186 static inline Local<Number> NumberToLocal(
187 v8::internal::Handle<v8::internal::Object> obj);
188 static inline Local<Integer> IntegerToLocal(
189 v8::internal::Handle<v8::internal::Object> obj);
190 static inline Local<Uint32> Uint32ToLocal(
191 v8::internal::Handle<v8::internal::Object> obj);
192 static inline Local<FunctionTemplate> ToLocal(
193 v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
194 static inline Local<ObjectTemplate> ToLocal(
195 v8::internal::Handle<v8::internal::ObjectTemplateInfo> obj);
196 static inline Local<Signature> ToLocal(
197 v8::internal::Handle<v8::internal::SignatureInfo> obj);
198 static inline Local<TypeSwitch> ToLocal(
199 v8::internal::Handle<v8::internal::TypeSwitchInfo> obj);
200
201 static inline v8::internal::Handle<v8::internal::TemplateInfo>
202 OpenHandle(const Template* that);
203 static inline v8::internal::Handle<v8::internal::FunctionTemplateInfo>
204 OpenHandle(const FunctionTemplate* that);
205 static inline v8::internal::Handle<v8::internal::ObjectTemplateInfo>
206 OpenHandle(const ObjectTemplate* that);
207 static inline v8::internal::Handle<v8::internal::Object>
208 OpenHandle(const Data* data);
Ben Murdochf87a2032010-10-22 12:50:53 +0100209 static inline v8::internal::Handle<v8::internal::JSRegExp>
210 OpenHandle(const RegExp* data);
Steve Blocka7e24c12009-10-30 11:49:00 +0000211 static inline v8::internal::Handle<v8::internal::JSObject>
212 OpenHandle(const v8::Object* data);
213 static inline v8::internal::Handle<v8::internal::JSArray>
214 OpenHandle(const v8::Array* data);
215 static inline v8::internal::Handle<v8::internal::String>
216 OpenHandle(const String* data);
Steve Block6ded16b2010-05-10 14:33:55 +0100217 static inline v8::internal::Handle<v8::internal::Object>
Steve Blocka7e24c12009-10-30 11:49:00 +0000218 OpenHandle(const Script* data);
219 static inline v8::internal::Handle<v8::internal::JSFunction>
220 OpenHandle(const Function* data);
221 static inline v8::internal::Handle<v8::internal::JSObject>
222 OpenHandle(const Message* message);
Kristian Monsen25f61362010-05-21 11:50:48 +0100223 static inline v8::internal::Handle<v8::internal::JSArray>
224 OpenHandle(const StackTrace* stack_trace);
225 static inline v8::internal::Handle<v8::internal::JSObject>
226 OpenHandle(const StackFrame* stack_frame);
Steve Blocka7e24c12009-10-30 11:49:00 +0000227 static inline v8::internal::Handle<v8::internal::Context>
228 OpenHandle(const v8::Context* context);
229 static inline v8::internal::Handle<v8::internal::SignatureInfo>
230 OpenHandle(const v8::Signature* sig);
231 static inline v8::internal::Handle<v8::internal::TypeSwitchInfo>
232 OpenHandle(const v8::TypeSwitch* that);
Ben Murdoch257744e2011-11-30 15:57:28 +0000233 static inline v8::internal::Handle<v8::internal::Foreign>
Steve Blocka7e24c12009-10-30 11:49:00 +0000234 OpenHandle(const v8::External* that);
235};
236
237
238template <class T>
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000239inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000240 return reinterpret_cast<T*>(obj.location());
241}
242
243
244template <class T>
245v8::internal::Handle<T> v8::internal::Handle<T>::EscapeFrom(
246 v8::HandleScope* scope) {
Steve Block6ded16b2010-05-10 14:33:55 +0100247 v8::internal::Handle<T> handle;
248 if (!is_null()) {
249 handle = *this;
250 }
251 return Utils::OpenHandle(*scope->Close(Utils::ToLocal(handle)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000252}
253
254
255// Implementations of ToLocal
256
257#define MAKE_TO_LOCAL(Name, From, To) \
258 Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \
Steve Block6ded16b2010-05-10 14:33:55 +0100259 ASSERT(obj.is_null() || !obj->IsTheHole()); \
Steve Blocka7e24c12009-10-30 11:49:00 +0000260 return Local<To>(reinterpret_cast<To*>(obj.location())); \
261 }
262
263MAKE_TO_LOCAL(ToLocal, Context, Context)
264MAKE_TO_LOCAL(ToLocal, Object, Value)
265MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
266MAKE_TO_LOCAL(ToLocal, String, String)
Ben Murdochf87a2032010-10-22 12:50:53 +0100267MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
Steve Blocka7e24c12009-10-30 11:49:00 +0000268MAKE_TO_LOCAL(ToLocal, JSObject, Object)
269MAKE_TO_LOCAL(ToLocal, JSArray, Array)
Ben Murdoch257744e2011-11-30 15:57:28 +0000270MAKE_TO_LOCAL(ToLocal, Foreign, External)
Steve Blocka7e24c12009-10-30 11:49:00 +0000271MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate)
272MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate)
273MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature)
274MAKE_TO_LOCAL(ToLocal, TypeSwitchInfo, TypeSwitch)
275MAKE_TO_LOCAL(MessageToLocal, Object, Message)
Kristian Monsen25f61362010-05-21 11:50:48 +0100276MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace)
277MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame)
Steve Blocka7e24c12009-10-30 11:49:00 +0000278MAKE_TO_LOCAL(NumberToLocal, Object, Number)
279MAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
280MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)
281
282#undef MAKE_TO_LOCAL
283
284
285// Implementations of OpenHandle
286
287#define MAKE_OPEN_HANDLE(From, To) \
288 v8::internal::Handle<v8::internal::To> Utils::OpenHandle(\
289 const v8::From* that) { \
290 return v8::internal::Handle<v8::internal::To>( \
291 reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \
292 }
293
294MAKE_OPEN_HANDLE(Template, TemplateInfo)
295MAKE_OPEN_HANDLE(FunctionTemplate, FunctionTemplateInfo)
296MAKE_OPEN_HANDLE(ObjectTemplate, ObjectTemplateInfo)
297MAKE_OPEN_HANDLE(Signature, SignatureInfo)
298MAKE_OPEN_HANDLE(TypeSwitch, TypeSwitchInfo)
299MAKE_OPEN_HANDLE(Data, Object)
Ben Murdochf87a2032010-10-22 12:50:53 +0100300MAKE_OPEN_HANDLE(RegExp, JSRegExp)
Steve Blocka7e24c12009-10-30 11:49:00 +0000301MAKE_OPEN_HANDLE(Object, JSObject)
302MAKE_OPEN_HANDLE(Array, JSArray)
303MAKE_OPEN_HANDLE(String, String)
Steve Block6ded16b2010-05-10 14:33:55 +0100304MAKE_OPEN_HANDLE(Script, Object)
Steve Blocka7e24c12009-10-30 11:49:00 +0000305MAKE_OPEN_HANDLE(Function, JSFunction)
306MAKE_OPEN_HANDLE(Message, JSObject)
307MAKE_OPEN_HANDLE(Context, Context)
Ben Murdoch257744e2011-11-30 15:57:28 +0000308MAKE_OPEN_HANDLE(External, Foreign)
Kristian Monsen25f61362010-05-21 11:50:48 +0100309MAKE_OPEN_HANDLE(StackTrace, JSArray)
310MAKE_OPEN_HANDLE(StackFrame, JSObject)
Steve Blocka7e24c12009-10-30 11:49:00 +0000311
312#undef MAKE_OPEN_HANDLE
313
314
315namespace internal {
316
Steve Block44f0eee2011-05-26 01:26:41 +0100317// Tracks string usage to help make better decisions when
318// externalizing strings.
319//
320// Implementation note: internally this class only tracks fresh
321// strings and keeps a single use counter for them.
322class StringTracker {
323 public:
324 // Records that the given string's characters were copied to some
325 // external buffer. If this happens often we should honor
326 // externalization requests for the string.
327 void RecordWrite(Handle<String> string) {
328 Address address = reinterpret_cast<Address>(*string);
329 Address top = isolate_->heap()->NewSpaceTop();
330 if (IsFreshString(address, top)) {
331 IncrementUseCount(top);
332 }
333 }
334
335 // Estimates freshness and use frequency of the given string based
336 // on how close it is to the new space top and the recorded usage
337 // history.
338 inline bool IsFreshUnusedString(Handle<String> string) {
339 Address address = reinterpret_cast<Address>(*string);
340 Address top = isolate_->heap()->NewSpaceTop();
341 return IsFreshString(address, top) && IsUseCountLow(top);
342 }
343
344 private:
345 StringTracker() : use_count_(0), last_top_(NULL), isolate_(NULL) { }
346
347 static inline bool IsFreshString(Address string, Address top) {
348 return top - kFreshnessLimit <= string && string <= top;
349 }
350
351 inline bool IsUseCountLow(Address top) {
352 if (last_top_ != top) return true;
353 return use_count_ < kUseLimit;
354 }
355
356 inline void IncrementUseCount(Address top) {
357 if (last_top_ != top) {
358 use_count_ = 0;
359 last_top_ = top;
360 }
361 ++use_count_;
362 }
363
364 // Single use counter shared by all fresh strings.
365 int use_count_;
366
367 // Last new space top when the use count above was valid.
368 Address last_top_;
369
370 Isolate* isolate_;
371
372 // How close to the new space top a fresh string has to be.
373 static const int kFreshnessLimit = 1024;
374
375 // The number of uses required to consider a string useful.
376 static const int kUseLimit = 32;
377
378 friend class Isolate;
379
380 DISALLOW_COPY_AND_ASSIGN(StringTracker);
381};
382
383
Steve Blocka7e24c12009-10-30 11:49:00 +0000384// This class is here in order to be able to declare it a friend of
385// HandleScope. Moving these methods to be members of HandleScope would be
Steve Block44f0eee2011-05-26 01:26:41 +0100386// neat in some ways, but it would expose internal implementation details in
Steve Blocka7e24c12009-10-30 11:49:00 +0000387// our public header file, which is undesirable.
388//
Steve Block44f0eee2011-05-26 01:26:41 +0100389// An isolate has a single instance of this class to hold the current thread's
390// data. In multithreaded V8 programs this data is copied in and out of storage
Steve Blocka7e24c12009-10-30 11:49:00 +0000391// so that the currently executing thread always has its own copy of this
392// data.
Ben Murdoch257744e2011-11-30 15:57:28 +0000393class HandleScopeImplementer {
Steve Blocka7e24c12009-10-30 11:49:00 +0000394 public:
Ben Murdoch257744e2011-11-30 15:57:28 +0000395 explicit HandleScopeImplementer(Isolate* isolate)
396 : isolate_(isolate),
397 blocks_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +0000398 entered_contexts_(0),
399 saved_contexts_(0),
400 spare_(NULL),
Steve Blocka7e24c12009-10-30 11:49:00 +0000401 call_depth_(0) { }
402
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000403 ~HandleScopeImplementer() {
404 DeleteArray(spare_);
405 }
406
Steve Blocka7e24c12009-10-30 11:49:00 +0000407 // Threading support for handle data.
408 static int ArchiveSpacePerThread();
Steve Block44f0eee2011-05-26 01:26:41 +0100409 char* RestoreThread(char* from);
410 char* ArchiveThread(char* to);
411 void FreeThreadResources();
Steve Blocka7e24c12009-10-30 11:49:00 +0000412
413 // Garbage collection support.
Steve Block44f0eee2011-05-26 01:26:41 +0100414 void Iterate(v8::internal::ObjectVisitor* v);
Steve Blocka7e24c12009-10-30 11:49:00 +0000415 static char* Iterate(v8::internal::ObjectVisitor* v, char* data);
416
417
418 inline internal::Object** GetSpareOrNewBlock();
John Reck59135872010-11-02 12:39:01 -0700419 inline void DeleteExtensions(internal::Object** prev_limit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000420
421 inline void IncrementCallDepth() {call_depth_++;}
422 inline void DecrementCallDepth() {call_depth_--;}
423 inline bool CallDepthIsZero() { return call_depth_ == 0; }
424
425 inline void EnterContext(Handle<Object> context);
426 inline bool LeaveLastContext();
427
428 // Returns the last entered context or an empty handle if no
429 // contexts have been entered.
430 inline Handle<Object> LastEnteredContext();
431
432 inline void SaveContext(Context* context);
433 inline Context* RestoreContext();
434 inline bool HasSavedContexts();
435
436 inline List<internal::Object**>* blocks() { return &blocks_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000437
438 private:
439 void ResetAfterArchive() {
440 blocks_.Initialize(0);
441 entered_contexts_.Initialize(0);
442 saved_contexts_.Initialize(0);
443 spare_ = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000444 call_depth_ = 0;
445 }
446
447 void Free() {
448 ASSERT(blocks_.length() == 0);
449 ASSERT(entered_contexts_.length() == 0);
450 ASSERT(saved_contexts_.length() == 0);
451 blocks_.Free();
452 entered_contexts_.Free();
453 saved_contexts_.Free();
454 if (spare_ != NULL) {
455 DeleteArray(spare_);
456 spare_ = NULL;
457 }
458 ASSERT(call_depth_ == 0);
459 }
460
Ben Murdoch257744e2011-11-30 15:57:28 +0000461 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000462 List<internal::Object**> blocks_;
463 // Used as a stack to keep track of entered contexts.
464 List<Handle<Object> > entered_contexts_;
465 // Used as a stack to keep track of saved contexts.
466 List<Context*> saved_contexts_;
467 Object** spare_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000468 int call_depth_;
469 // This is only used for threading support.
470 v8::ImplementationUtilities::HandleScopeData handle_scope_data_;
471
472 void IterateThis(ObjectVisitor* v);
473 char* RestoreThreadHelper(char* from);
474 char* ArchiveThreadHelper(char* to);
475
476 DISALLOW_COPY_AND_ASSIGN(HandleScopeImplementer);
477};
478
479
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000480const int kHandleBlockSize = v8::internal::KB - 2; // fit in one page
Steve Blocka7e24c12009-10-30 11:49:00 +0000481
482
483void HandleScopeImplementer::SaveContext(Context* context) {
484 saved_contexts_.Add(context);
485}
486
487
488Context* HandleScopeImplementer::RestoreContext() {
489 return saved_contexts_.RemoveLast();
490}
491
492
493bool HandleScopeImplementer::HasSavedContexts() {
494 return !saved_contexts_.is_empty();
495}
496
497
498void HandleScopeImplementer::EnterContext(Handle<Object> context) {
499 entered_contexts_.Add(context);
500}
501
502
503bool HandleScopeImplementer::LeaveLastContext() {
504 if (entered_contexts_.is_empty()) return false;
505 entered_contexts_.RemoveLast();
506 return true;
507}
508
509
510Handle<Object> HandleScopeImplementer::LastEnteredContext() {
511 if (entered_contexts_.is_empty()) return Handle<Object>::null();
512 return entered_contexts_.last();
513}
514
515
516// If there's a spare block, use it for growing the current scope.
517internal::Object** HandleScopeImplementer::GetSpareOrNewBlock() {
518 internal::Object** block = (spare_ != NULL) ?
519 spare_ :
520 NewArray<internal::Object*>(kHandleBlockSize);
521 spare_ = NULL;
522 return block;
523}
524
525
John Reck59135872010-11-02 12:39:01 -0700526void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) {
527 while (!blocks_.is_empty()) {
528 internal::Object** block_start = blocks_.last();
529 internal::Object** block_limit = block_start + kHandleBlockSize;
Steve Blocka7e24c12009-10-30 11:49:00 +0000530#ifdef DEBUG
John Reck59135872010-11-02 12:39:01 -0700531 // NoHandleAllocation may make the prev_limit to point inside the block.
532 if (block_start <= prev_limit && prev_limit <= block_limit) break;
533#else
534 if (prev_limit == block_limit) break;
Steve Blocka7e24c12009-10-30 11:49:00 +0000535#endif
John Reck59135872010-11-02 12:39:01 -0700536
537 blocks_.RemoveLast();
Steve Blocka7e24c12009-10-30 11:49:00 +0000538#ifdef DEBUG
John Reck59135872010-11-02 12:39:01 -0700539 v8::ImplementationUtilities::ZapHandleRange(block_start, block_limit);
Steve Blocka7e24c12009-10-30 11:49:00 +0000540#endif
John Reck59135872010-11-02 12:39:01 -0700541 if (spare_ != NULL) {
542 DeleteArray(spare_);
543 }
544 spare_ = block_start;
545 }
546 ASSERT((blocks_.is_empty() && prev_limit == NULL) ||
547 (!blocks_.is_empty() && prev_limit != NULL));
Steve Blocka7e24c12009-10-30 11:49:00 +0000548}
549
Ben Murdochb0fe1622011-05-05 13:52:32 +0100550
551class Testing {
552 public:
553 static v8::Testing::StressType stress_type() { return stress_type_; }
554 static void set_stress_type(v8::Testing::StressType stress_type) {
555 stress_type_ = stress_type;
556 }
557
558 private:
559 static v8::Testing::StressType stress_type_;
560};
561
Steve Blocka7e24c12009-10-30 11:49:00 +0000562} } // namespace v8::internal
563
564#endif // V8_API_H_