• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2009 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 #include "v8.h"
29 
30 #include "api.h"
31 #include "arguments.h"
32 #include "bootstrapper.h"
33 #include "compiler.h"
34 #include "debug.h"
35 #include "execution.h"
36 #include "global-handles.h"
37 #include "globals.h"
38 #include "platform.h"
39 #include "serialize.h"
40 #include "snapshot.h"
41 #include "utils.h"
42 #include "v8threads.h"
43 #include "version.h"
44 
45 
46 #define LOG_API(expr) LOG(ApiEntryCall(expr))
47 
48 #ifdef ENABLE_HEAP_PROTECTION
49 #define ENTER_V8 i::VMState __state__(i::OTHER)
50 #define LEAVE_V8 i::VMState __state__(i::EXTERNAL)
51 #else
52 #define ENTER_V8 ((void) 0)
53 #define LEAVE_V8 ((void) 0)
54 #endif
55 
56 namespace v8 {
57 
58 
59 #define ON_BAILOUT(location, code)              \
60   if (IsDeadCheck(location)) {                  \
61     code;                                       \
62     UNREACHABLE();                              \
63   }
64 
65 
66 #define EXCEPTION_PREAMBLE()                                      \
67   thread_local.IncrementCallDepth();                              \
68   ASSERT(!i::Top::external_caught_exception());                   \
69   bool has_pending_exception = false
70 
71 
72 #define EXCEPTION_BAILOUT_CHECK(value)                                         \
73   do {                                                                         \
74     thread_local.DecrementCallDepth();                                         \
75     if (has_pending_exception) {                                               \
76       if (thread_local.CallDepthIsZero() && i::Top::is_out_of_memory()) {      \
77         if (!thread_local.ignore_out_of_memory())                              \
78           i::V8::FatalProcessOutOfMemory(NULL);                                \
79       }                                                                        \
80       bool call_depth_is_zero = thread_local.CallDepthIsZero();                \
81       i::Top::OptionalRescheduleException(call_depth_is_zero);                 \
82       return value;                                                            \
83     }                                                                          \
84   } while (false)
85 
86 
87 #define API_ENTRY_CHECK(msg)                                                   \
88   do {                                                                         \
89     if (v8::Locker::IsActive()) {                                              \
90       ApiCheck(i::ThreadManager::IsLockedByCurrentThread(),                    \
91                msg,                                                            \
92                "Entering the V8 API without proper locking in place");         \
93     }                                                                          \
94   } while (false)
95 
96 // --- D a t a   t h a t   i s   s p e c i f i c   t o   a   t h r e a d ---
97 
98 
99 static i::HandleScopeImplementer thread_local;
100 
101 
102 // --- E x c e p t i o n   B e h a v i o r ---
103 
104 
105 static FatalErrorCallback exception_behavior = NULL;
106 int i::Internals::kJSObjectType = JS_OBJECT_TYPE;
107 int i::Internals::kFirstNonstringType = FIRST_NONSTRING_TYPE;
108 int i::Internals::kProxyType = PROXY_TYPE;
109 
DefaultFatalErrorHandler(const char * location,const char * message)110 static void DefaultFatalErrorHandler(const char* location,
111                                      const char* message) {
112   ENTER_V8;
113   API_Fatal(location, message);
114 }
115 
116 
117 
GetFatalErrorHandler()118 static FatalErrorCallback& GetFatalErrorHandler() {
119   if (exception_behavior == NULL) {
120     exception_behavior = DefaultFatalErrorHandler;
121   }
122   return exception_behavior;
123 }
124 
125 
126 
127 // When V8 cannot allocated memory FatalProcessOutOfMemory is called.
128 // The default fatal error handler is called and execution is stopped.
FatalProcessOutOfMemory(const char * location)129 void i::V8::FatalProcessOutOfMemory(const char* location) {
130   i::HeapStats heap_stats;
131   int start_marker;
132   heap_stats.start_marker = &start_marker;
133   int new_space_size;
134   heap_stats.new_space_size = &new_space_size;
135   int new_space_capacity;
136   heap_stats.new_space_capacity = &new_space_capacity;
137   int old_pointer_space_size;
138   heap_stats.old_pointer_space_size = &old_pointer_space_size;
139   int old_pointer_space_capacity;
140   heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
141   int old_data_space_size;
142   heap_stats.old_data_space_size = &old_data_space_size;
143   int old_data_space_capacity;
144   heap_stats.old_data_space_capacity = &old_data_space_capacity;
145   int code_space_size;
146   heap_stats.code_space_size = &code_space_size;
147   int code_space_capacity;
148   heap_stats.code_space_capacity = &code_space_capacity;
149   int map_space_size;
150   heap_stats.map_space_size = &map_space_size;
151   int map_space_capacity;
152   heap_stats.map_space_capacity = &map_space_capacity;
153   int cell_space_size;
154   heap_stats.cell_space_size = &cell_space_size;
155   int cell_space_capacity;
156   heap_stats.cell_space_capacity = &cell_space_capacity;
157   int lo_space_size;
158   heap_stats.lo_space_size = &lo_space_size;
159   int global_handle_count;
160   heap_stats.global_handle_count = &global_handle_count;
161   int weak_global_handle_count;
162   heap_stats.weak_global_handle_count = &weak_global_handle_count;
163   int pending_global_handle_count;
164   heap_stats.pending_global_handle_count = &pending_global_handle_count;
165   int near_death_global_handle_count;
166   heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
167   int destroyed_global_handle_count;
168   heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count;
169   int end_marker;
170   heap_stats.end_marker = &end_marker;
171   i::Heap::RecordStats(&heap_stats);
172   i::V8::SetFatalError();
173   FatalErrorCallback callback = GetFatalErrorHandler();
174   {
175     LEAVE_V8;
176     callback(location, "Allocation failed - process out of memory");
177   }
178   // If the callback returns, we stop execution.
179   UNREACHABLE();
180 }
181 
182 
SetFatalErrorHandler(FatalErrorCallback that)183 void V8::SetFatalErrorHandler(FatalErrorCallback that) {
184   exception_behavior = that;
185 }
186 
187 
ReportApiFailure(const char * location,const char * message)188 bool Utils::ReportApiFailure(const char* location, const char* message) {
189   FatalErrorCallback callback = GetFatalErrorHandler();
190   callback(location, message);
191   i::V8::SetFatalError();
192   return false;
193 }
194 
195 
IsDead()196 bool V8::IsDead() {
197   return i::V8::IsDead();
198 }
199 
200 
ApiCheck(bool condition,const char * location,const char * message)201 static inline bool ApiCheck(bool condition,
202                             const char* location,
203                             const char* message) {
204   return condition ? true : Utils::ReportApiFailure(location, message);
205 }
206 
207 
ReportV8Dead(const char * location)208 static bool ReportV8Dead(const char* location) {
209   FatalErrorCallback callback = GetFatalErrorHandler();
210   callback(location, "V8 is no longer usable");
211   return true;
212 }
213 
214 
ReportEmptyHandle(const char * location)215 static bool ReportEmptyHandle(const char* location) {
216   FatalErrorCallback callback = GetFatalErrorHandler();
217   callback(location, "Reading from empty handle");
218   return true;
219 }
220 
221 
222 /**
223  * IsDeadCheck checks that the vm is usable.  If, for instance, the vm has been
224  * out of memory at some point this check will fail.  It should be called on
225  * entry to all methods that touch anything in the heap, except destructors
226  * which you sometimes can't avoid calling after the vm has crashed.  Functions
227  * that call EnsureInitialized or ON_BAILOUT don't have to also call
228  * IsDeadCheck.  ON_BAILOUT has the advantage over EnsureInitialized that you
229  * can arrange to return if the VM is dead.  This is needed to ensure that no VM
230  * heap allocations are attempted on a dead VM.  EnsureInitialized has the
231  * advantage over ON_BAILOUT that it actually initializes the VM if this has not
232  * yet been done.
233  */
IsDeadCheck(const char * location)234 static inline bool IsDeadCheck(const char* location) {
235   return !i::V8::IsRunning()
236       && i::V8::IsDead() ? ReportV8Dead(location) : false;
237 }
238 
239 
EmptyCheck(const char * location,v8::Handle<v8::Data> obj)240 static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
241   return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
242 }
243 
244 
EmptyCheck(const char * location,const v8::Data * obj)245 static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
246   return (obj == 0) ? ReportEmptyHandle(location) : false;
247 }
248 
249 // --- S t a t i c s ---
250 
251 
252 static i::StringInputBuffer write_input_buffer;
253 
254 
EnsureInitialized(const char * location)255 static inline bool EnsureInitialized(const char* location) {
256   if (i::V8::IsRunning()) {
257     return true;
258   }
259   if (IsDeadCheck(location)) {
260     return false;
261   }
262   return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
263 }
264 
265 
266 ImplementationUtilities::HandleScopeData*
CurrentHandleScope()267     ImplementationUtilities::CurrentHandleScope() {
268   return &i::HandleScope::current_;
269 }
270 
271 
272 #ifdef DEBUG
ZapHandleRange(i::Object ** begin,i::Object ** end)273 void ImplementationUtilities::ZapHandleRange(i::Object** begin,
274                                              i::Object** end) {
275   i::HandleScope::ZapRange(begin, end);
276 }
277 #endif
278 
279 
Undefined()280 v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
281   if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
282   return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
283 }
284 
285 
Null()286 v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
287   if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
288   return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
289 }
290 
291 
True()292 v8::Handle<v8::Boolean> ImplementationUtilities::True() {
293   if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
294   return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
295 }
296 
297 
False()298 v8::Handle<v8::Boolean> ImplementationUtilities::False() {
299   if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
300   return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
301 }
302 
303 
SetFlagsFromString(const char * str,int length)304 void V8::SetFlagsFromString(const char* str, int length) {
305   i::FlagList::SetFlagsFromString(str, length);
306 }
307 
308 
SetFlagsFromCommandLine(int * argc,char ** argv,bool remove_flags)309 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
310   i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
311 }
312 
313 
ThrowException(v8::Handle<v8::Value> value)314 v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
315   if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
316   ENTER_V8;
317   // If we're passed an empty handle, we throw an undefined exception
318   // to deal more gracefully with out of memory situations.
319   if (value.IsEmpty()) {
320     i::Top::ScheduleThrow(i::Heap::undefined_value());
321   } else {
322     i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
323   }
324   return v8::Undefined();
325 }
326 
327 
328 RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
329 
330 
RegisteredExtension(Extension * extension)331 RegisteredExtension::RegisteredExtension(Extension* extension)
332     : extension_(extension), state_(UNVISITED) { }
333 
334 
Register(RegisteredExtension * that)335 void RegisteredExtension::Register(RegisteredExtension* that) {
336   that->next_ = RegisteredExtension::first_extension_;
337   RegisteredExtension::first_extension_ = that;
338 }
339 
340 
RegisterExtension(Extension * that)341 void RegisterExtension(Extension* that) {
342   RegisteredExtension* extension = new RegisteredExtension(that);
343   RegisteredExtension::Register(extension);
344 }
345 
346 
Extension(const char * name,const char * source,int dep_count,const char ** deps)347 Extension::Extension(const char* name,
348                      const char* source,
349                      int dep_count,
350                      const char** deps)
351     : name_(name),
352       source_(source),
353       dep_count_(dep_count),
354       deps_(deps),
355       auto_enable_(false) { }
356 
357 
Undefined()358 v8::Handle<Primitive> Undefined() {
359   LOG_API("Undefined");
360   return ImplementationUtilities::Undefined();
361 }
362 
363 
Null()364 v8::Handle<Primitive> Null() {
365   LOG_API("Null");
366   return ImplementationUtilities::Null();
367 }
368 
369 
True()370 v8::Handle<Boolean> True() {
371   LOG_API("True");
372   return ImplementationUtilities::True();
373 }
374 
375 
False()376 v8::Handle<Boolean> False() {
377   LOG_API("False");
378   return ImplementationUtilities::False();
379 }
380 
381 
ResourceConstraints()382 ResourceConstraints::ResourceConstraints()
383   : max_young_space_size_(0),
384     max_old_space_size_(0),
385     stack_limit_(NULL) { }
386 
387 
SetResourceConstraints(ResourceConstraints * constraints)388 bool SetResourceConstraints(ResourceConstraints* constraints) {
389   int young_space_size = constraints->max_young_space_size();
390   int old_gen_size = constraints->max_old_space_size();
391   if (young_space_size != 0 || old_gen_size != 0) {
392     bool result = i::Heap::ConfigureHeap(young_space_size / 2, old_gen_size);
393     if (!result) return false;
394   }
395   if (constraints->stack_limit() != NULL) {
396     uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
397     i::StackGuard::SetStackLimit(limit);
398   }
399   return true;
400 }
401 
402 
GlobalizeReference(i::Object ** obj)403 i::Object** V8::GlobalizeReference(i::Object** obj) {
404   if (IsDeadCheck("V8::Persistent::New")) return NULL;
405   LOG_API("Persistent::New");
406   i::Handle<i::Object> result =
407       i::GlobalHandles::Create(*obj);
408   return result.location();
409 }
410 
411 
MakeWeak(i::Object ** object,void * parameters,WeakReferenceCallback callback)412 void V8::MakeWeak(i::Object** object, void* parameters,
413                   WeakReferenceCallback callback) {
414   LOG_API("MakeWeak");
415   i::GlobalHandles::MakeWeak(object, parameters, callback);
416 }
417 
418 
ClearWeak(i::Object ** obj)419 void V8::ClearWeak(i::Object** obj) {
420   LOG_API("ClearWeak");
421   i::GlobalHandles::ClearWeakness(obj);
422 }
423 
424 
IsGlobalNearDeath(i::Object ** obj)425 bool V8::IsGlobalNearDeath(i::Object** obj) {
426   LOG_API("IsGlobalNearDeath");
427   if (!i::V8::IsRunning()) return false;
428   return i::GlobalHandles::IsNearDeath(obj);
429 }
430 
431 
IsGlobalWeak(i::Object ** obj)432 bool V8::IsGlobalWeak(i::Object** obj) {
433   LOG_API("IsGlobalWeak");
434   if (!i::V8::IsRunning()) return false;
435   return i::GlobalHandles::IsWeak(obj);
436 }
437 
438 
DisposeGlobal(i::Object ** obj)439 void V8::DisposeGlobal(i::Object** obj) {
440   LOG_API("DisposeGlobal");
441   if (!i::V8::IsRunning()) return;
442   if ((*obj)->IsGlobalContext()) i::Heap::NotifyContextDisposed();
443   i::GlobalHandles::Destroy(obj);
444 }
445 
446 // --- H a n d l e s ---
447 
448 
HandleScope()449 HandleScope::HandleScope() : is_closed_(false) {
450   API_ENTRY_CHECK("HandleScope::HandleScope");
451   i::HandleScope::Enter(&previous_);
452 }
453 
454 
~HandleScope()455 HandleScope::~HandleScope() {
456   if (!is_closed_) {
457     i::HandleScope::Leave(&previous_);
458   }
459 }
460 
461 
NumberOfHandles()462 int HandleScope::NumberOfHandles() {
463   return i::HandleScope::NumberOfHandles();
464 }
465 
466 
CreateHandle(i::Object * value)467 i::Object** v8::HandleScope::CreateHandle(i::Object* value) {
468   return i::HandleScope::CreateHandle(value);
469 }
470 
471 
Enter()472 void Context::Enter() {
473   if (IsDeadCheck("v8::Context::Enter()")) return;
474   ENTER_V8;
475   i::Handle<i::Context> env = Utils::OpenHandle(this);
476   thread_local.EnterContext(env);
477 
478   thread_local.SaveContext(i::Top::context());
479   i::Top::set_context(*env);
480 }
481 
482 
Exit()483 void Context::Exit() {
484   if (!i::V8::IsRunning()) return;
485   if (!ApiCheck(thread_local.LeaveLastContext(),
486                 "v8::Context::Exit()",
487                 "Cannot exit non-entered context")) {
488     return;
489   }
490 
491   // Content of 'last_context' could be NULL.
492   i::Context* last_context = thread_local.RestoreContext();
493   i::Top::set_context(last_context);
494 }
495 
496 
SetData(v8::Handle<String> data)497 void Context::SetData(v8::Handle<String> data) {
498   if (IsDeadCheck("v8::Context::SetData()")) return;
499   ENTER_V8;
500   {
501     HandleScope scope;
502     i::Handle<i::Context> env = Utils::OpenHandle(this);
503     i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
504     ASSERT(env->IsGlobalContext());
505     if (env->IsGlobalContext()) {
506       env->set_data(*raw_data);
507     }
508   }
509 }
510 
511 
GetData()512 v8::Local<v8::Value> Context::GetData() {
513   if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
514   ENTER_V8;
515   i::Object* raw_result = NULL;
516   {
517     HandleScope scope;
518     i::Handle<i::Context> env = Utils::OpenHandle(this);
519     ASSERT(env->IsGlobalContext());
520     if (env->IsGlobalContext()) {
521       raw_result = env->data();
522     } else {
523       return Local<Value>();
524     }
525   }
526   i::Handle<i::Object> result(raw_result);
527   return Utils::ToLocal(result);
528 }
529 
530 
RawClose(i::Object ** value)531 i::Object** v8::HandleScope::RawClose(i::Object** value) {
532   if (!ApiCheck(!is_closed_,
533                 "v8::HandleScope::Close()",
534                 "Local scope has already been closed")) {
535     return 0;
536   }
537   LOG_API("CloseHandleScope");
538 
539   // Read the result before popping the handle block.
540   i::Object* result = *value;
541   is_closed_ = true;
542   i::HandleScope::Leave(&previous_);
543 
544   // Allocate a new handle on the previous handle block.
545   i::Handle<i::Object> handle(result);
546   return handle.location();
547 }
548 
549 
550 // --- N e a n d e r ---
551 
552 
553 // A constructor cannot easily return an error value, therefore it is necessary
554 // to check for a dead VM with ON_BAILOUT before constructing any Neander
555 // objects.  To remind you about this there is no HandleScope in the
556 // NeanderObject constructor.  When you add one to the site calling the
557 // constructor you should check that you ensured the VM was not dead first.
NeanderObject(int size)558 NeanderObject::NeanderObject(int size) {
559   EnsureInitialized("v8::Nowhere");
560   ENTER_V8;
561   value_ = i::Factory::NewNeanderObject();
562   i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
563   value_->set_elements(*elements);
564 }
565 
566 
size()567 int NeanderObject::size() {
568   return i::FixedArray::cast(value_->elements())->length();
569 }
570 
571 
NeanderArray()572 NeanderArray::NeanderArray() : obj_(2) {
573   obj_.set(0, i::Smi::FromInt(0));
574 }
575 
576 
length()577 int NeanderArray::length() {
578   return i::Smi::cast(obj_.get(0))->value();
579 }
580 
581 
get(int offset)582 i::Object* NeanderArray::get(int offset) {
583   ASSERT(0 <= offset);
584   ASSERT(offset < length());
585   return obj_.get(offset + 1);
586 }
587 
588 
589 // This method cannot easily return an error value, therefore it is necessary
590 // to check for a dead VM with ON_BAILOUT before calling it.  To remind you
591 // about this there is no HandleScope in this method.  When you add one to the
592 // site calling this method you should check that you ensured the VM was not
593 // dead first.
add(i::Handle<i::Object> value)594 void NeanderArray::add(i::Handle<i::Object> value) {
595   int length = this->length();
596   int size = obj_.size();
597   if (length == size - 1) {
598     i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
599     for (int i = 0; i < length; i++)
600       new_elms->set(i + 1, get(i));
601     obj_.value()->set_elements(*new_elms);
602   }
603   obj_.set(length + 1, *value);
604   obj_.set(0, i::Smi::FromInt(length + 1));
605 }
606 
607 
set(int index,i::Object * value)608 void NeanderArray::set(int index, i::Object* value) {
609   if (index < 0 || index >= this->length()) return;
610   obj_.set(index + 1, value);
611 }
612 
613 
614 // --- T e m p l a t e ---
615 
616 
InitializeTemplate(i::Handle<i::TemplateInfo> that,int type)617 static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
618   that->set_tag(i::Smi::FromInt(type));
619 }
620 
621 
Set(v8::Handle<String> name,v8::Handle<Data> value,v8::PropertyAttribute attribute)622 void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
623                    v8::PropertyAttribute attribute) {
624   if (IsDeadCheck("v8::Template::SetProperty()")) return;
625   ENTER_V8;
626   HandleScope scope;
627   i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
628   if (list->IsUndefined()) {
629     list = NeanderArray().value();
630     Utils::OpenHandle(this)->set_property_list(*list);
631   }
632   NeanderArray array(list);
633   array.add(Utils::OpenHandle(*name));
634   array.add(Utils::OpenHandle(*value));
635   array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
636 }
637 
638 
639 // --- F u n c t i o n   T e m p l a t e ---
InitializeFunctionTemplate(i::Handle<i::FunctionTemplateInfo> info)640 static void InitializeFunctionTemplate(
641       i::Handle<i::FunctionTemplateInfo> info) {
642   info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
643   info->set_flag(0);
644 }
645 
646 
PrototypeTemplate()647 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
648   if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
649     return Local<ObjectTemplate>();
650   }
651   ENTER_V8;
652   i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
653   if (result->IsUndefined()) {
654     result = Utils::OpenHandle(*ObjectTemplate::New());
655     Utils::OpenHandle(this)->set_prototype_template(*result);
656   }
657   return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
658 }
659 
660 
Inherit(v8::Handle<FunctionTemplate> value)661 void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
662   if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
663   ENTER_V8;
664   Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
665 }
666 
667 
668 // To distinguish the function templates, so that we can find them in the
669 // function cache of the global context.
670 static int next_serial_number = 0;
671 
672 
New(InvocationCallback callback,v8::Handle<Value> data,v8::Handle<Signature> signature)673 Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
674     v8::Handle<Value> data, v8::Handle<Signature> signature) {
675   EnsureInitialized("v8::FunctionTemplate::New()");
676   LOG_API("FunctionTemplate::New");
677   ENTER_V8;
678   i::Handle<i::Struct> struct_obj =
679       i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
680   i::Handle<i::FunctionTemplateInfo> obj =
681       i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
682   InitializeFunctionTemplate(obj);
683   obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
684   if (callback != 0) {
685     if (data.IsEmpty()) data = v8::Undefined();
686     Utils::ToLocal(obj)->SetCallHandler(callback, data);
687   }
688   obj->set_undetectable(false);
689   obj->set_needs_access_check(false);
690 
691   if (!signature.IsEmpty())
692     obj->set_signature(*Utils::OpenHandle(*signature));
693   return Utils::ToLocal(obj);
694 }
695 
696 
New(Handle<FunctionTemplate> receiver,int argc,Handle<FunctionTemplate> argv[])697 Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
698       int argc, Handle<FunctionTemplate> argv[]) {
699   EnsureInitialized("v8::Signature::New()");
700   LOG_API("Signature::New");
701   ENTER_V8;
702   i::Handle<i::Struct> struct_obj =
703       i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
704   i::Handle<i::SignatureInfo> obj =
705       i::Handle<i::SignatureInfo>::cast(struct_obj);
706   if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
707   if (argc > 0) {
708     i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
709     for (int i = 0; i < argc; i++) {
710       if (!argv[i].IsEmpty())
711         args->set(i, *Utils::OpenHandle(*argv[i]));
712     }
713     obj->set_args(*args);
714   }
715   return Utils::ToLocal(obj);
716 }
717 
718 
New(Handle<FunctionTemplate> type)719 Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
720   Handle<FunctionTemplate> types[1] = { type };
721   return TypeSwitch::New(1, types);
722 }
723 
724 
New(int argc,Handle<FunctionTemplate> types[])725 Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
726   EnsureInitialized("v8::TypeSwitch::New()");
727   LOG_API("TypeSwitch::New");
728   ENTER_V8;
729   i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
730   for (int i = 0; i < argc; i++)
731     vector->set(i, *Utils::OpenHandle(*types[i]));
732   i::Handle<i::Struct> struct_obj =
733       i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
734   i::Handle<i::TypeSwitchInfo> obj =
735       i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
736   obj->set_types(*vector);
737   return Utils::ToLocal(obj);
738 }
739 
740 
match(v8::Handle<Value> value)741 int TypeSwitch::match(v8::Handle<Value> value) {
742   LOG_API("TypeSwitch::match");
743   i::Handle<i::Object> obj = Utils::OpenHandle(*value);
744   i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
745   i::FixedArray* types = i::FixedArray::cast(info->types());
746   for (int i = 0; i < types->length(); i++) {
747     if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
748       return i + 1;
749   }
750   return 0;
751 }
752 
753 
SetCallHandler(InvocationCallback callback,v8::Handle<Value> data)754 void FunctionTemplate::SetCallHandler(InvocationCallback callback,
755                                       v8::Handle<Value> data) {
756   if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
757   ENTER_V8;
758   HandleScope scope;
759   i::Handle<i::Struct> struct_obj =
760       i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
761   i::Handle<i::CallHandlerInfo> obj =
762       i::Handle<i::CallHandlerInfo>::cast(struct_obj);
763   obj->set_callback(*FromCData(callback));
764   if (data.IsEmpty()) data = v8::Undefined();
765   obj->set_data(*Utils::OpenHandle(*data));
766   Utils::OpenHandle(this)->set_call_code(*obj);
767 }
768 
769 
AddInstancePropertyAccessor(v8::Handle<String> name,AccessorGetter getter,AccessorSetter setter,v8::Handle<Value> data,v8::AccessControl settings,v8::PropertyAttribute attributes)770 void FunctionTemplate::AddInstancePropertyAccessor(
771       v8::Handle<String> name,
772       AccessorGetter getter,
773       AccessorSetter setter,
774       v8::Handle<Value> data,
775       v8::AccessControl settings,
776       v8::PropertyAttribute attributes) {
777   if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
778     return;
779   }
780   ENTER_V8;
781   HandleScope scope;
782   i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
783   ASSERT(getter != NULL);
784   obj->set_getter(*FromCData(getter));
785   obj->set_setter(*FromCData(setter));
786   if (data.IsEmpty()) data = v8::Undefined();
787   obj->set_data(*Utils::OpenHandle(*data));
788   obj->set_name(*Utils::OpenHandle(*name));
789   if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
790   if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
791   if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
792   obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
793 
794   i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
795   if (list->IsUndefined()) {
796     list = NeanderArray().value();
797     Utils::OpenHandle(this)->set_property_accessors(*list);
798   }
799   NeanderArray array(list);
800   array.add(obj);
801 }
802 
803 
InstanceTemplate()804 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
805   if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
806       || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
807     return Local<ObjectTemplate>();
808   ENTER_V8;
809   if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
810     Local<ObjectTemplate> templ =
811         ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
812     Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
813   }
814   i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
815         Utils::OpenHandle(this)->instance_template()));
816   return Utils::ToLocal(result);
817 }
818 
819 
SetClassName(Handle<String> name)820 void FunctionTemplate::SetClassName(Handle<String> name) {
821   if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
822   ENTER_V8;
823   Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
824 }
825 
826 
SetHiddenPrototype(bool value)827 void FunctionTemplate::SetHiddenPrototype(bool value) {
828   if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
829   ENTER_V8;
830   Utils::OpenHandle(this)->set_hidden_prototype(value);
831 }
832 
833 
SetNamedInstancePropertyHandler(NamedPropertyGetter getter,NamedPropertySetter setter,NamedPropertyQuery query,NamedPropertyDeleter remover,NamedPropertyEnumerator enumerator,Handle<Value> data)834 void FunctionTemplate::SetNamedInstancePropertyHandler(
835       NamedPropertyGetter getter,
836       NamedPropertySetter setter,
837       NamedPropertyQuery query,
838       NamedPropertyDeleter remover,
839       NamedPropertyEnumerator enumerator,
840       Handle<Value> data) {
841   if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
842     return;
843   }
844   ENTER_V8;
845   HandleScope scope;
846   i::Handle<i::Struct> struct_obj =
847       i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
848   i::Handle<i::InterceptorInfo> obj =
849       i::Handle<i::InterceptorInfo>::cast(struct_obj);
850   if (getter != 0) obj->set_getter(*FromCData(getter));
851   if (setter != 0) obj->set_setter(*FromCData(setter));
852   if (query != 0) obj->set_query(*FromCData(query));
853   if (remover != 0) obj->set_deleter(*FromCData(remover));
854   if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
855   if (data.IsEmpty()) data = v8::Undefined();
856   obj->set_data(*Utils::OpenHandle(*data));
857   Utils::OpenHandle(this)->set_named_property_handler(*obj);
858 }
859 
860 
SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter,IndexedPropertySetter setter,IndexedPropertyQuery query,IndexedPropertyDeleter remover,IndexedPropertyEnumerator enumerator,Handle<Value> data)861 void FunctionTemplate::SetIndexedInstancePropertyHandler(
862       IndexedPropertyGetter getter,
863       IndexedPropertySetter setter,
864       IndexedPropertyQuery query,
865       IndexedPropertyDeleter remover,
866       IndexedPropertyEnumerator enumerator,
867       Handle<Value> data) {
868   if (IsDeadCheck(
869         "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
870     return;
871   }
872   ENTER_V8;
873   HandleScope scope;
874   i::Handle<i::Struct> struct_obj =
875       i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
876   i::Handle<i::InterceptorInfo> obj =
877       i::Handle<i::InterceptorInfo>::cast(struct_obj);
878   if (getter != 0) obj->set_getter(*FromCData(getter));
879   if (setter != 0) obj->set_setter(*FromCData(setter));
880   if (query != 0) obj->set_query(*FromCData(query));
881   if (remover != 0) obj->set_deleter(*FromCData(remover));
882   if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
883   if (data.IsEmpty()) data = v8::Undefined();
884   obj->set_data(*Utils::OpenHandle(*data));
885   Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
886 }
887 
888 
SetInstanceCallAsFunctionHandler(InvocationCallback callback,Handle<Value> data)889 void FunctionTemplate::SetInstanceCallAsFunctionHandler(
890       InvocationCallback callback,
891       Handle<Value> data) {
892   if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
893     return;
894   }
895   ENTER_V8;
896   HandleScope scope;
897   i::Handle<i::Struct> struct_obj =
898       i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
899   i::Handle<i::CallHandlerInfo> obj =
900       i::Handle<i::CallHandlerInfo>::cast(struct_obj);
901   obj->set_callback(*FromCData(callback));
902   if (data.IsEmpty()) data = v8::Undefined();
903   obj->set_data(*Utils::OpenHandle(*data));
904   Utils::OpenHandle(this)->set_instance_call_handler(*obj);
905 }
906 
907 
908 // --- O b j e c t T e m p l a t e ---
909 
910 
New()911 Local<ObjectTemplate> ObjectTemplate::New() {
912   return New(Local<FunctionTemplate>());
913 }
914 
915 
New(v8::Handle<FunctionTemplate> constructor)916 Local<ObjectTemplate> ObjectTemplate::New(
917       v8::Handle<FunctionTemplate> constructor) {
918   if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
919   EnsureInitialized("v8::ObjectTemplate::New()");
920   LOG_API("ObjectTemplate::New");
921   ENTER_V8;
922   i::Handle<i::Struct> struct_obj =
923       i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
924   i::Handle<i::ObjectTemplateInfo> obj =
925       i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
926   InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
927   if (!constructor.IsEmpty())
928     obj->set_constructor(*Utils::OpenHandle(*constructor));
929   obj->set_internal_field_count(i::Smi::FromInt(0));
930   return Utils::ToLocal(obj);
931 }
932 
933 
934 // Ensure that the object template has a constructor.  If no
935 // constructor is available we create one.
EnsureConstructor(ObjectTemplate * object_template)936 static void EnsureConstructor(ObjectTemplate* object_template) {
937   if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
938     Local<FunctionTemplate> templ = FunctionTemplate::New();
939     i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
940     constructor->set_instance_template(*Utils::OpenHandle(object_template));
941     Utils::OpenHandle(object_template)->set_constructor(*constructor);
942   }
943 }
944 
945 
SetAccessor(v8::Handle<String> name,AccessorGetter getter,AccessorSetter setter,v8::Handle<Value> data,AccessControl settings,PropertyAttribute attribute)946 void ObjectTemplate::SetAccessor(v8::Handle<String> name,
947                                  AccessorGetter getter,
948                                  AccessorSetter setter,
949                                  v8::Handle<Value> data,
950                                  AccessControl settings,
951                                  PropertyAttribute attribute) {
952   if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
953   ENTER_V8;
954   HandleScope scope;
955   EnsureConstructor(this);
956   i::FunctionTemplateInfo* constructor =
957       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
958   i::Handle<i::FunctionTemplateInfo> cons(constructor);
959   Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
960                                                     getter,
961                                                     setter,
962                                                     data,
963                                                     settings,
964                                                     attribute);
965 }
966 
967 
SetNamedPropertyHandler(NamedPropertyGetter getter,NamedPropertySetter setter,NamedPropertyQuery query,NamedPropertyDeleter remover,NamedPropertyEnumerator enumerator,Handle<Value> data)968 void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
969                                              NamedPropertySetter setter,
970                                              NamedPropertyQuery query,
971                                              NamedPropertyDeleter remover,
972                                              NamedPropertyEnumerator enumerator,
973                                              Handle<Value> data) {
974   if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
975   ENTER_V8;
976   HandleScope scope;
977   EnsureConstructor(this);
978   i::FunctionTemplateInfo* constructor =
979       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
980   i::Handle<i::FunctionTemplateInfo> cons(constructor);
981   Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
982                                                         setter,
983                                                         query,
984                                                         remover,
985                                                         enumerator,
986                                                         data);
987 }
988 
989 
MarkAsUndetectable()990 void ObjectTemplate::MarkAsUndetectable() {
991   if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
992   ENTER_V8;
993   HandleScope scope;
994   EnsureConstructor(this);
995   i::FunctionTemplateInfo* constructor =
996       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
997   i::Handle<i::FunctionTemplateInfo> cons(constructor);
998   cons->set_undetectable(true);
999 }
1000 
1001 
SetAccessCheckCallbacks(NamedSecurityCallback named_callback,IndexedSecurityCallback indexed_callback,Handle<Value> data,bool turned_on_by_default)1002 void ObjectTemplate::SetAccessCheckCallbacks(
1003       NamedSecurityCallback named_callback,
1004       IndexedSecurityCallback indexed_callback,
1005       Handle<Value> data,
1006       bool turned_on_by_default) {
1007   if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
1008   ENTER_V8;
1009   HandleScope scope;
1010   EnsureConstructor(this);
1011 
1012   i::Handle<i::Struct> struct_info =
1013       i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1014   i::Handle<i::AccessCheckInfo> info =
1015       i::Handle<i::AccessCheckInfo>::cast(struct_info);
1016   info->set_named_callback(*FromCData(named_callback));
1017   info->set_indexed_callback(*FromCData(indexed_callback));
1018   if (data.IsEmpty()) data = v8::Undefined();
1019   info->set_data(*Utils::OpenHandle(*data));
1020 
1021   i::FunctionTemplateInfo* constructor =
1022       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1023   i::Handle<i::FunctionTemplateInfo> cons(constructor);
1024   cons->set_access_check_info(*info);
1025   cons->set_needs_access_check(turned_on_by_default);
1026 }
1027 
1028 
SetIndexedPropertyHandler(IndexedPropertyGetter getter,IndexedPropertySetter setter,IndexedPropertyQuery query,IndexedPropertyDeleter remover,IndexedPropertyEnumerator enumerator,Handle<Value> data)1029 void ObjectTemplate::SetIndexedPropertyHandler(
1030       IndexedPropertyGetter getter,
1031       IndexedPropertySetter setter,
1032       IndexedPropertyQuery query,
1033       IndexedPropertyDeleter remover,
1034       IndexedPropertyEnumerator enumerator,
1035       Handle<Value> data) {
1036   if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
1037   ENTER_V8;
1038   HandleScope scope;
1039   EnsureConstructor(this);
1040   i::FunctionTemplateInfo* constructor =
1041       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1042   i::Handle<i::FunctionTemplateInfo> cons(constructor);
1043   Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
1044                                                           setter,
1045                                                           query,
1046                                                           remover,
1047                                                           enumerator,
1048                                                           data);
1049 }
1050 
1051 
SetCallAsFunctionHandler(InvocationCallback callback,Handle<Value> data)1052 void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1053                                               Handle<Value> data) {
1054   if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
1055   ENTER_V8;
1056   HandleScope scope;
1057   EnsureConstructor(this);
1058   i::FunctionTemplateInfo* constructor =
1059       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1060   i::Handle<i::FunctionTemplateInfo> cons(constructor);
1061   Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1062 }
1063 
1064 
InternalFieldCount()1065 int ObjectTemplate::InternalFieldCount() {
1066   if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
1067     return 0;
1068   }
1069   return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1070 }
1071 
1072 
SetInternalFieldCount(int value)1073 void ObjectTemplate::SetInternalFieldCount(int value) {
1074   if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
1075   if (!ApiCheck(i::Smi::IsValid(value),
1076                 "v8::ObjectTemplate::SetInternalFieldCount()",
1077                 "Invalid internal field count")) {
1078     return;
1079   }
1080   ENTER_V8;
1081   if (value > 0) {
1082     // The internal field count is set by the constructor function's
1083     // construct code, so we ensure that there is a constructor
1084     // function to do the setting.
1085     EnsureConstructor(this);
1086   }
1087   Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1088 }
1089 
1090 
1091 // --- S c r i p t D a t a ---
1092 
1093 
PreCompile(const char * input,int length)1094 ScriptData* ScriptData::PreCompile(const char* input, int length) {
1095   unibrow::Utf8InputBuffer<> buf(input, length);
1096   return i::PreParse(i::Handle<i::String>(), &buf, NULL);
1097 }
1098 
1099 
New(unsigned * data,int length)1100 ScriptData* ScriptData::New(unsigned* data, int length) {
1101   return new i::ScriptDataImpl(i::Vector<unsigned>(data, length));
1102 }
1103 
1104 
1105 // --- S c r i p t ---
1106 
1107 
New(v8::Handle<String> source,v8::ScriptOrigin * origin,v8::ScriptData * pre_data,v8::Handle<String> script_data)1108 Local<Script> Script::New(v8::Handle<String> source,
1109                           v8::ScriptOrigin* origin,
1110                           v8::ScriptData* pre_data,
1111                           v8::Handle<String> script_data) {
1112   ON_BAILOUT("v8::Script::New()", return Local<Script>());
1113   LOG_API("Script::New");
1114   ENTER_V8;
1115   i::Handle<i::String> str = Utils::OpenHandle(*source);
1116   i::Handle<i::Object> name_obj;
1117   int line_offset = 0;
1118   int column_offset = 0;
1119   if (origin != NULL) {
1120     if (!origin->ResourceName().IsEmpty()) {
1121       name_obj = Utils::OpenHandle(*origin->ResourceName());
1122     }
1123     if (!origin->ResourceLineOffset().IsEmpty()) {
1124       line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1125     }
1126     if (!origin->ResourceColumnOffset().IsEmpty()) {
1127       column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1128     }
1129   }
1130   EXCEPTION_PREAMBLE();
1131   i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
1132   // We assert that the pre-data is sane, even though we can actually
1133   // handle it if it turns out not to be in release mode.
1134   ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
1135   // If the pre-data isn't sane we simply ignore it
1136   if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
1137     pre_data_impl = NULL;
1138   }
1139   i::Handle<i::JSFunction> boilerplate =
1140       i::Compiler::Compile(str,
1141                            name_obj,
1142                            line_offset,
1143                            column_offset,
1144                            NULL,
1145                            pre_data_impl,
1146                            Utils::OpenHandle(*script_data),
1147                            i::NOT_NATIVES_CODE);
1148   has_pending_exception = boilerplate.is_null();
1149   EXCEPTION_BAILOUT_CHECK(Local<Script>());
1150   return Local<Script>(ToApi<Script>(boilerplate));
1151 }
1152 
1153 
New(v8::Handle<String> source,v8::Handle<Value> file_name)1154 Local<Script> Script::New(v8::Handle<String> source,
1155                           v8::Handle<Value> file_name) {
1156   ScriptOrigin origin(file_name);
1157   return New(source, &origin);
1158 }
1159 
1160 
Compile(v8::Handle<String> source,v8::ScriptOrigin * origin,v8::ScriptData * pre_data,v8::Handle<String> script_data)1161 Local<Script> Script::Compile(v8::Handle<String> source,
1162                               v8::ScriptOrigin* origin,
1163                               v8::ScriptData* pre_data,
1164                               v8::Handle<String> script_data) {
1165   ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1166   LOG_API("Script::Compile");
1167   ENTER_V8;
1168   Local<Script> generic = New(source, origin, pre_data, script_data);
1169   if (generic.IsEmpty())
1170     return generic;
1171   i::Handle<i::JSFunction> boilerplate = Utils::OpenHandle(*generic);
1172   i::Handle<i::JSFunction> result =
1173       i::Factory::NewFunctionFromBoilerplate(boilerplate,
1174                                              i::Top::global_context());
1175   return Local<Script>(ToApi<Script>(result));
1176 }
1177 
1178 
Compile(v8::Handle<String> source,v8::Handle<Value> file_name,v8::Handle<String> script_data)1179 Local<Script> Script::Compile(v8::Handle<String> source,
1180                               v8::Handle<Value> file_name,
1181                               v8::Handle<String> script_data) {
1182   ScriptOrigin origin(file_name);
1183   return Compile(source, &origin, 0, script_data);
1184 }
1185 
1186 
Run()1187 Local<Value> Script::Run() {
1188   ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1189   LOG_API("Script::Run");
1190   ENTER_V8;
1191   i::Object* raw_result = NULL;
1192   {
1193     HandleScope scope;
1194     i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
1195     if (fun->IsBoilerplate()) {
1196       fun = i::Factory::NewFunctionFromBoilerplate(fun,
1197                                                    i::Top::global_context());
1198     }
1199     EXCEPTION_PREAMBLE();
1200     i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
1201     i::Handle<i::Object> result =
1202         i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
1203     EXCEPTION_BAILOUT_CHECK(Local<Value>());
1204     raw_result = *result;
1205   }
1206   i::Handle<i::Object> result(raw_result);
1207   return Utils::ToLocal(result);
1208 }
1209 
1210 
Id()1211 Local<Value> Script::Id() {
1212   ON_BAILOUT("v8::Script::Id()", return Local<Value>());
1213   LOG_API("Script::Id");
1214   i::Object* raw_id = NULL;
1215   {
1216     HandleScope scope;
1217     i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
1218     i::Handle<i::Script> script(i::Script::cast(fun->shared()->script()));
1219     i::Handle<i::Object> id(script->id());
1220     raw_id = *id;
1221   }
1222   i::Handle<i::Object> id(raw_id);
1223   return Utils::ToLocal(id);
1224 }
1225 
1226 
SetData(v8::Handle<String> data)1227 void Script::SetData(v8::Handle<String> data) {
1228   ON_BAILOUT("v8::Script::SetData()", return);
1229   LOG_API("Script::SetData");
1230   {
1231     HandleScope scope;
1232     i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
1233     i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
1234     i::Handle<i::Script> script(i::Script::cast(fun->shared()->script()));
1235     script->set_data(*raw_data);
1236   }
1237 }
1238 
1239 
1240 // --- E x c e p t i o n s ---
1241 
1242 
TryCatch()1243 v8::TryCatch::TryCatch()
1244     : next_(i::Top::try_catch_handler_address()),
1245       exception_(i::Heap::the_hole_value()),
1246       message_(i::Smi::FromInt(0)),
1247       is_verbose_(false),
1248       can_continue_(true),
1249       capture_message_(true),
1250       rethrow_(false) {
1251   i::Top::RegisterTryCatchHandler(this);
1252 }
1253 
1254 
~TryCatch()1255 v8::TryCatch::~TryCatch() {
1256   if (rethrow_) {
1257     v8::HandleScope scope;
1258     v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
1259     i::Top::UnregisterTryCatchHandler(this);
1260     v8::ThrowException(exc);
1261   } else {
1262     i::Top::UnregisterTryCatchHandler(this);
1263   }
1264 }
1265 
1266 
HasCaught() const1267 bool v8::TryCatch::HasCaught() const {
1268   return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1269 }
1270 
1271 
CanContinue() const1272 bool v8::TryCatch::CanContinue() const {
1273   return can_continue_;
1274 }
1275 
1276 
ReThrow()1277 v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1278   if (!HasCaught()) return v8::Local<v8::Value>();
1279   rethrow_ = true;
1280   return v8::Undefined();
1281 }
1282 
1283 
Exception() const1284 v8::Local<Value> v8::TryCatch::Exception() const {
1285   if (HasCaught()) {
1286     // Check for out of memory exception.
1287     i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1288     return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1289   } else {
1290     return v8::Local<Value>();
1291   }
1292 }
1293 
1294 
StackTrace() const1295 v8::Local<Value> v8::TryCatch::StackTrace() const {
1296   if (HasCaught()) {
1297     i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1298     if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1299     v8::HandleScope scope;
1300     i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
1301     i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
1302     if (!obj->HasProperty(*name))
1303       return v8::Local<Value>();
1304     return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
1305   } else {
1306     return v8::Local<Value>();
1307   }
1308 }
1309 
1310 
Message() const1311 v8::Local<v8::Message> v8::TryCatch::Message() const {
1312   if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1313     i::Object* message = reinterpret_cast<i::Object*>(message_);
1314     return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1315   } else {
1316     return v8::Local<v8::Message>();
1317   }
1318 }
1319 
1320 
Reset()1321 void v8::TryCatch::Reset() {
1322   exception_ = i::Heap::the_hole_value();
1323   message_ = i::Smi::FromInt(0);
1324 }
1325 
1326 
SetVerbose(bool value)1327 void v8::TryCatch::SetVerbose(bool value) {
1328   is_verbose_ = value;
1329 }
1330 
1331 
SetCaptureMessage(bool value)1332 void v8::TryCatch::SetCaptureMessage(bool value) {
1333   capture_message_ = value;
1334 }
1335 
1336 
1337 // --- M e s s a g e ---
1338 
1339 
Get() const1340 Local<String> Message::Get() const {
1341   ON_BAILOUT("v8::Message::Get()", return Local<String>());
1342   ENTER_V8;
1343   HandleScope scope;
1344   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1345   i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1346   Local<String> result = Utils::ToLocal(raw_result);
1347   return scope.Close(result);
1348 }
1349 
1350 
GetScriptResourceName() const1351 v8::Handle<Value> Message::GetScriptResourceName() const {
1352   if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1353     return Local<String>();
1354   }
1355   ENTER_V8;
1356   HandleScope scope;
1357   i::Handle<i::JSObject> obj =
1358       i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1359   // Return this.script.name.
1360   i::Handle<i::JSValue> script =
1361       i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1362   i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
1363   return scope.Close(Utils::ToLocal(resource_name));
1364 }
1365 
1366 
GetScriptData() const1367 v8::Handle<Value> Message::GetScriptData() const {
1368   if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
1369     return Local<Value>();
1370   }
1371   ENTER_V8;
1372   HandleScope scope;
1373   i::Handle<i::JSObject> obj =
1374       i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1375   // Return this.script.data.
1376   i::Handle<i::JSValue> script =
1377       i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1378   i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1379   return scope.Close(Utils::ToLocal(data));
1380 }
1381 
1382 
CallV8HeapFunction(const char * name,i::Handle<i::Object> recv,int argc,i::Object ** argv[],bool * has_pending_exception)1383 static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1384                                                i::Handle<i::Object> recv,
1385                                                int argc,
1386                                                i::Object** argv[],
1387                                                bool* has_pending_exception) {
1388   i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
1389   i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
1390   i::Handle<i::JSFunction> fun =
1391       i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1392   i::Handle<i::Object> value =
1393       i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1394   return value;
1395 }
1396 
1397 
CallV8HeapFunction(const char * name,i::Handle<i::Object> data,bool * has_pending_exception)1398 static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1399                                                i::Handle<i::Object> data,
1400                                                bool* has_pending_exception) {
1401   i::Object** argv[1] = { data.location() };
1402   return CallV8HeapFunction(name,
1403                             i::Top::builtins(),
1404                             1,
1405                             argv,
1406                             has_pending_exception);
1407 }
1408 
1409 
GetLineNumber() const1410 int Message::GetLineNumber() const {
1411   ON_BAILOUT("v8::Message::GetLineNumber()", return -1);
1412   ENTER_V8;
1413   HandleScope scope;
1414   EXCEPTION_PREAMBLE();
1415   i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1416                                                    Utils::OpenHandle(this),
1417                                                    &has_pending_exception);
1418   EXCEPTION_BAILOUT_CHECK(0);
1419   return static_cast<int>(result->Number());
1420 }
1421 
1422 
GetStartPosition() const1423 int Message::GetStartPosition() const {
1424   if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1425   ENTER_V8;
1426   HandleScope scope;
1427 
1428   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1429   return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1430 }
1431 
1432 
GetEndPosition() const1433 int Message::GetEndPosition() const {
1434   if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1435   ENTER_V8;
1436   HandleScope scope;
1437   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1438   return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1439 }
1440 
1441 
GetStartColumn() const1442 int Message::GetStartColumn() const {
1443   if (IsDeadCheck("v8::Message::GetStartColumn()")) return 0;
1444   ENTER_V8;
1445   HandleScope scope;
1446   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1447   EXCEPTION_PREAMBLE();
1448   i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1449       "GetPositionInLine",
1450       data_obj,
1451       &has_pending_exception);
1452   EXCEPTION_BAILOUT_CHECK(0);
1453   return static_cast<int>(start_col_obj->Number());
1454 }
1455 
1456 
GetEndColumn() const1457 int Message::GetEndColumn() const {
1458   if (IsDeadCheck("v8::Message::GetEndColumn()")) return 0;
1459   ENTER_V8;
1460   HandleScope scope;
1461   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1462   EXCEPTION_PREAMBLE();
1463   i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1464       "GetPositionInLine",
1465       data_obj,
1466       &has_pending_exception);
1467   EXCEPTION_BAILOUT_CHECK(0);
1468   int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1469   int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1470   return static_cast<int>(start_col_obj->Number()) + (end - start);
1471 }
1472 
1473 
GetSourceLine() const1474 Local<String> Message::GetSourceLine() const {
1475   ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
1476   ENTER_V8;
1477   HandleScope scope;
1478   EXCEPTION_PREAMBLE();
1479   i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1480                                                    Utils::OpenHandle(this),
1481                                                    &has_pending_exception);
1482   EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1483   if (result->IsString()) {
1484     return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1485   } else {
1486     return Local<String>();
1487   }
1488 }
1489 
1490 
PrintCurrentStackTrace(FILE * out)1491 void Message::PrintCurrentStackTrace(FILE* out) {
1492   if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1493   ENTER_V8;
1494   i::Top::PrintCurrentStackTrace(out);
1495 }
1496 
1497 
1498 // --- D a t a ---
1499 
IsUndefined() const1500 bool Value::IsUndefined() const {
1501   if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1502   return Utils::OpenHandle(this)->IsUndefined();
1503 }
1504 
1505 
IsNull() const1506 bool Value::IsNull() const {
1507   if (IsDeadCheck("v8::Value::IsNull()")) return false;
1508   return Utils::OpenHandle(this)->IsNull();
1509 }
1510 
1511 
IsTrue() const1512 bool Value::IsTrue() const {
1513   if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1514   return Utils::OpenHandle(this)->IsTrue();
1515 }
1516 
1517 
IsFalse() const1518 bool Value::IsFalse() const {
1519   if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1520   return Utils::OpenHandle(this)->IsFalse();
1521 }
1522 
1523 
IsFunction() const1524 bool Value::IsFunction() const {
1525   if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1526   return Utils::OpenHandle(this)->IsJSFunction();
1527 }
1528 
1529 
FullIsString() const1530 bool Value::FullIsString() const {
1531   if (IsDeadCheck("v8::Value::IsString()")) return false;
1532   bool result = Utils::OpenHandle(this)->IsString();
1533   ASSERT_EQ(result, QuickIsString());
1534   return result;
1535 }
1536 
1537 
IsArray() const1538 bool Value::IsArray() const {
1539   if (IsDeadCheck("v8::Value::IsArray()")) return false;
1540   return Utils::OpenHandle(this)->IsJSArray();
1541 }
1542 
1543 
IsObject() const1544 bool Value::IsObject() const {
1545   if (IsDeadCheck("v8::Value::IsObject()")) return false;
1546   return Utils::OpenHandle(this)->IsJSObject();
1547 }
1548 
1549 
IsNumber() const1550 bool Value::IsNumber() const {
1551   if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1552   return Utils::OpenHandle(this)->IsNumber();
1553 }
1554 
1555 
IsBoolean() const1556 bool Value::IsBoolean() const {
1557   if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1558   return Utils::OpenHandle(this)->IsBoolean();
1559 }
1560 
1561 
IsExternal() const1562 bool Value::IsExternal() const {
1563   if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1564   return Utils::OpenHandle(this)->IsProxy();
1565 }
1566 
1567 
IsInt32() const1568 bool Value::IsInt32() const {
1569   if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1570   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1571   if (obj->IsSmi()) return true;
1572   if (obj->IsNumber()) {
1573     double value = obj->Number();
1574     return i::FastI2D(i::FastD2I(value)) == value;
1575   }
1576   return false;
1577 }
1578 
1579 
IsDate() const1580 bool Value::IsDate() const {
1581   if (IsDeadCheck("v8::Value::IsDate()")) return false;
1582   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1583   return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1584 }
1585 
1586 
ToString() const1587 Local<String> Value::ToString() const {
1588   if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1589   LOG_API("ToString");
1590   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1591   i::Handle<i::Object> str;
1592   if (obj->IsString()) {
1593     str = obj;
1594   } else {
1595     ENTER_V8;
1596     EXCEPTION_PREAMBLE();
1597     str = i::Execution::ToString(obj, &has_pending_exception);
1598     EXCEPTION_BAILOUT_CHECK(Local<String>());
1599   }
1600   return Local<String>(ToApi<String>(str));
1601 }
1602 
1603 
ToDetailString() const1604 Local<String> Value::ToDetailString() const {
1605   if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1606   LOG_API("ToDetailString");
1607   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1608   i::Handle<i::Object> str;
1609   if (obj->IsString()) {
1610     str = obj;
1611   } else {
1612     ENTER_V8;
1613     EXCEPTION_PREAMBLE();
1614     str = i::Execution::ToDetailString(obj, &has_pending_exception);
1615     EXCEPTION_BAILOUT_CHECK(Local<String>());
1616   }
1617   return Local<String>(ToApi<String>(str));
1618 }
1619 
1620 
ToObject() const1621 Local<v8::Object> Value::ToObject() const {
1622   if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1623   LOG_API("ToObject");
1624   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1625   i::Handle<i::Object> val;
1626   if (obj->IsJSObject()) {
1627     val = obj;
1628   } else {
1629     ENTER_V8;
1630     EXCEPTION_PREAMBLE();
1631     val = i::Execution::ToObject(obj, &has_pending_exception);
1632     EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1633   }
1634   return Local<v8::Object>(ToApi<Object>(val));
1635 }
1636 
1637 
ToBoolean() const1638 Local<Boolean> Value::ToBoolean() const {
1639   if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1640   LOG_API("ToBoolean");
1641   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1642   if (obj->IsBoolean()) {
1643     return Local<Boolean>(ToApi<Boolean>(obj));
1644   } else {
1645     ENTER_V8;
1646     i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1647     return Local<Boolean>(ToApi<Boolean>(val));
1648   }
1649 }
1650 
1651 
ToNumber() const1652 Local<Number> Value::ToNumber() const {
1653   if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1654   LOG_API("ToNumber");
1655   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1656   i::Handle<i::Object> num;
1657   if (obj->IsNumber()) {
1658     num = obj;
1659   } else {
1660     ENTER_V8;
1661     EXCEPTION_PREAMBLE();
1662     num = i::Execution::ToNumber(obj, &has_pending_exception);
1663     EXCEPTION_BAILOUT_CHECK(Local<Number>());
1664   }
1665   return Local<Number>(ToApi<Number>(num));
1666 }
1667 
1668 
ToInteger() const1669 Local<Integer> Value::ToInteger() const {
1670   if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1671   LOG_API("ToInteger");
1672   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1673   i::Handle<i::Object> num;
1674   if (obj->IsSmi()) {
1675     num = obj;
1676   } else {
1677     ENTER_V8;
1678     EXCEPTION_PREAMBLE();
1679     num = i::Execution::ToInteger(obj, &has_pending_exception);
1680     EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1681   }
1682   return Local<Integer>(ToApi<Integer>(num));
1683 }
1684 
1685 
CheckCast(v8::Value * that)1686 void External::CheckCast(v8::Value* that) {
1687   if (IsDeadCheck("v8::External::Cast()")) return;
1688   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1689   ApiCheck(obj->IsProxy(),
1690            "v8::External::Cast()",
1691            "Could not convert to external");
1692 }
1693 
1694 
CheckCast(Value * that)1695 void v8::Object::CheckCast(Value* that) {
1696   if (IsDeadCheck("v8::Object::Cast()")) return;
1697   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1698   ApiCheck(obj->IsJSObject(),
1699            "v8::Object::Cast()",
1700            "Could not convert to object");
1701 }
1702 
1703 
CheckCast(Value * that)1704 void v8::Function::CheckCast(Value* that) {
1705   if (IsDeadCheck("v8::Function::Cast()")) return;
1706   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1707   ApiCheck(obj->IsJSFunction(),
1708            "v8::Function::Cast()",
1709            "Could not convert to function");
1710 }
1711 
1712 
CheckCast(v8::Value * that)1713 void v8::String::CheckCast(v8::Value* that) {
1714   if (IsDeadCheck("v8::String::Cast()")) return;
1715   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1716   ApiCheck(obj->IsString(),
1717            "v8::String::Cast()",
1718            "Could not convert to string");
1719 }
1720 
1721 
CheckCast(v8::Value * that)1722 void v8::Number::CheckCast(v8::Value* that) {
1723   if (IsDeadCheck("v8::Number::Cast()")) return;
1724   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1725   ApiCheck(obj->IsNumber(),
1726            "v8::Number::Cast()",
1727            "Could not convert to number");
1728 }
1729 
1730 
CheckCast(v8::Value * that)1731 void v8::Integer::CheckCast(v8::Value* that) {
1732   if (IsDeadCheck("v8::Integer::Cast()")) return;
1733   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1734   ApiCheck(obj->IsNumber(),
1735            "v8::Integer::Cast()",
1736            "Could not convert to number");
1737 }
1738 
1739 
CheckCast(Value * that)1740 void v8::Array::CheckCast(Value* that) {
1741   if (IsDeadCheck("v8::Array::Cast()")) return;
1742   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1743   ApiCheck(obj->IsJSArray(),
1744            "v8::Array::Cast()",
1745            "Could not convert to array");
1746 }
1747 
1748 
CheckCast(v8::Value * that)1749 void v8::Date::CheckCast(v8::Value* that) {
1750   if (IsDeadCheck("v8::Date::Cast()")) return;
1751   i::Handle<i::Object> obj = Utils::OpenHandle(that);
1752   ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
1753            "v8::Date::Cast()",
1754            "Could not convert to date");
1755 }
1756 
1757 
BooleanValue() const1758 bool Value::BooleanValue() const {
1759   if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
1760   LOG_API("BooleanValue");
1761   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1762   if (obj->IsBoolean()) {
1763     return obj->IsTrue();
1764   } else {
1765     ENTER_V8;
1766     i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
1767     return value->IsTrue();
1768   }
1769 }
1770 
1771 
NumberValue() const1772 double Value::NumberValue() const {
1773   if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
1774   LOG_API("NumberValue");
1775   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1776   i::Handle<i::Object> num;
1777   if (obj->IsNumber()) {
1778     num = obj;
1779   } else {
1780     ENTER_V8;
1781     EXCEPTION_PREAMBLE();
1782     num = i::Execution::ToNumber(obj, &has_pending_exception);
1783     EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
1784   }
1785   return num->Number();
1786 }
1787 
1788 
IntegerValue() const1789 int64_t Value::IntegerValue() const {
1790   if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
1791   LOG_API("IntegerValue");
1792   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1793   i::Handle<i::Object> num;
1794   if (obj->IsNumber()) {
1795     num = obj;
1796   } else {
1797     ENTER_V8;
1798     EXCEPTION_PREAMBLE();
1799     num = i::Execution::ToInteger(obj, &has_pending_exception);
1800     EXCEPTION_BAILOUT_CHECK(0);
1801   }
1802   if (num->IsSmi()) {
1803     return i::Smi::cast(*num)->value();
1804   } else {
1805     return static_cast<int64_t>(num->Number());
1806   }
1807 }
1808 
1809 
ToInt32() const1810 Local<Int32> Value::ToInt32() const {
1811   if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
1812   LOG_API("ToInt32");
1813   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1814   i::Handle<i::Object> num;
1815   if (obj->IsSmi()) {
1816     num = obj;
1817   } else {
1818     ENTER_V8;
1819     EXCEPTION_PREAMBLE();
1820     num = i::Execution::ToInt32(obj, &has_pending_exception);
1821     EXCEPTION_BAILOUT_CHECK(Local<Int32>());
1822   }
1823   return Local<Int32>(ToApi<Int32>(num));
1824 }
1825 
1826 
ToUint32() const1827 Local<Uint32> Value::ToUint32() const {
1828   if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
1829   LOG_API("ToUInt32");
1830   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1831   i::Handle<i::Object> num;
1832   if (obj->IsSmi()) {
1833     num = obj;
1834   } else {
1835     ENTER_V8;
1836     EXCEPTION_PREAMBLE();
1837     num = i::Execution::ToUint32(obj, &has_pending_exception);
1838     EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
1839   }
1840   return Local<Uint32>(ToApi<Uint32>(num));
1841 }
1842 
1843 
ToArrayIndex() const1844 Local<Uint32> Value::ToArrayIndex() const {
1845   if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
1846   LOG_API("ToArrayIndex");
1847   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1848   if (obj->IsSmi()) {
1849     if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
1850     return Local<Uint32>();
1851   }
1852   ENTER_V8;
1853   EXCEPTION_PREAMBLE();
1854   i::Handle<i::Object> string_obj =
1855       i::Execution::ToString(obj, &has_pending_exception);
1856   EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
1857   i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
1858   uint32_t index;
1859   if (str->AsArrayIndex(&index)) {
1860     i::Handle<i::Object> value;
1861     if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
1862       value = i::Handle<i::Object>(i::Smi::FromInt(index));
1863     } else {
1864       value = i::Factory::NewNumber(index);
1865     }
1866     return Utils::Uint32ToLocal(value);
1867   }
1868   return Local<Uint32>();
1869 }
1870 
1871 
Int32Value() const1872 int32_t Value::Int32Value() const {
1873   if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
1874   LOG_API("Int32Value");
1875   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1876   if (obj->IsSmi()) {
1877     return i::Smi::cast(*obj)->value();
1878   } else {
1879     LOG_API("Int32Value (slow)");
1880     ENTER_V8;
1881     EXCEPTION_PREAMBLE();
1882     i::Handle<i::Object> num =
1883         i::Execution::ToInt32(obj, &has_pending_exception);
1884     EXCEPTION_BAILOUT_CHECK(0);
1885     if (num->IsSmi()) {
1886       return i::Smi::cast(*num)->value();
1887     } else {
1888       return static_cast<int32_t>(num->Number());
1889     }
1890   }
1891 }
1892 
1893 
Equals(Handle<Value> that) const1894 bool Value::Equals(Handle<Value> that) const {
1895   if (IsDeadCheck("v8::Value::Equals()")
1896       || EmptyCheck("v8::Value::Equals()", this)
1897       || EmptyCheck("v8::Value::Equals()", that)) {
1898     return false;
1899   }
1900   LOG_API("Equals");
1901   ENTER_V8;
1902   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1903   i::Handle<i::Object> other = Utils::OpenHandle(*that);
1904   i::Object** args[1] = { other.location() };
1905   EXCEPTION_PREAMBLE();
1906   i::Handle<i::Object> result =
1907       CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
1908   EXCEPTION_BAILOUT_CHECK(false);
1909   return *result == i::Smi::FromInt(i::EQUAL);
1910 }
1911 
1912 
StrictEquals(Handle<Value> that) const1913 bool Value::StrictEquals(Handle<Value> that) const {
1914   if (IsDeadCheck("v8::Value::StrictEquals()")
1915       || EmptyCheck("v8::Value::StrictEquals()", this)
1916       || EmptyCheck("v8::Value::StrictEquals()", that)) {
1917     return false;
1918   }
1919   LOG_API("StrictEquals");
1920   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1921   i::Handle<i::Object> other = Utils::OpenHandle(*that);
1922   // Must check HeapNumber first, since NaN !== NaN.
1923   if (obj->IsHeapNumber()) {
1924     if (!other->IsNumber()) return false;
1925     double x = obj->Number();
1926     double y = other->Number();
1927     // Must check explicitly for NaN:s on Windows, but -0 works fine.
1928     return x == y && !isnan(x) && !isnan(y);
1929   } else if (*obj == *other) {  // Also covers Booleans.
1930     return true;
1931   } else if (obj->IsSmi()) {
1932     return other->IsNumber() && obj->Number() == other->Number();
1933   } else if (obj->IsString()) {
1934     return other->IsString() &&
1935       i::String::cast(*obj)->Equals(i::String::cast(*other));
1936   } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
1937     return other->IsUndefined() || other->IsUndetectableObject();
1938   } else {
1939     return false;
1940   }
1941 }
1942 
1943 
Uint32Value() const1944 uint32_t Value::Uint32Value() const {
1945   if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
1946   LOG_API("Uint32Value");
1947   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1948   if (obj->IsSmi()) {
1949     return i::Smi::cast(*obj)->value();
1950   } else {
1951     ENTER_V8;
1952     EXCEPTION_PREAMBLE();
1953     i::Handle<i::Object> num =
1954         i::Execution::ToUint32(obj, &has_pending_exception);
1955     EXCEPTION_BAILOUT_CHECK(0);
1956     if (num->IsSmi()) {
1957       return i::Smi::cast(*num)->value();
1958     } else {
1959       return static_cast<uint32_t>(num->Number());
1960     }
1961   }
1962 }
1963 
1964 
Set(v8::Handle<Value> key,v8::Handle<Value> value,v8::PropertyAttribute attribs)1965 bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
1966                      v8::PropertyAttribute attribs) {
1967   ON_BAILOUT("v8::Object::Set()", return false);
1968   ENTER_V8;
1969   HandleScope scope;
1970   i::Handle<i::Object> self = Utils::OpenHandle(this);
1971   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
1972   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
1973   EXCEPTION_PREAMBLE();
1974   i::Handle<i::Object> obj = i::SetProperty(
1975       self,
1976       key_obj,
1977       value_obj,
1978       static_cast<PropertyAttributes>(attribs));
1979   has_pending_exception = obj.is_null();
1980   EXCEPTION_BAILOUT_CHECK(false);
1981   return true;
1982 }
1983 
1984 
ForceSet(v8::Handle<Value> key,v8::Handle<Value> value,v8::PropertyAttribute attribs)1985 bool v8::Object::ForceSet(v8::Handle<Value> key,
1986                           v8::Handle<Value> value,
1987                           v8::PropertyAttribute attribs) {
1988   ON_BAILOUT("v8::Object::ForceSet()", return false);
1989   ENTER_V8;
1990   HandleScope scope;
1991   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1992   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
1993   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
1994   EXCEPTION_PREAMBLE();
1995   i::Handle<i::Object> obj = i::ForceSetProperty(
1996       self,
1997       key_obj,
1998       value_obj,
1999       static_cast<PropertyAttributes>(attribs));
2000   has_pending_exception = obj.is_null();
2001   EXCEPTION_BAILOUT_CHECK(false);
2002   return true;
2003 }
2004 
2005 
ForceDelete(v8::Handle<Value> key)2006 bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2007   ON_BAILOUT("v8::Object::ForceDelete()", return false);
2008   ENTER_V8;
2009   HandleScope scope;
2010   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2011   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2012   EXCEPTION_PREAMBLE();
2013   i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2014   has_pending_exception = obj.is_null();
2015   EXCEPTION_BAILOUT_CHECK(false);
2016   return obj->IsTrue();
2017 }
2018 
2019 
Get(v8::Handle<Value> key)2020 Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2021   ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2022   ENTER_V8;
2023   i::Handle<i::Object> self = Utils::OpenHandle(this);
2024   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2025   EXCEPTION_PREAMBLE();
2026   i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2027   has_pending_exception = result.is_null();
2028   EXCEPTION_BAILOUT_CHECK(Local<Value>());
2029   return Utils::ToLocal(result);
2030 }
2031 
2032 
GetPrototype()2033 Local<Value> v8::Object::GetPrototype() {
2034   ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
2035   ENTER_V8;
2036   i::Handle<i::Object> self = Utils::OpenHandle(this);
2037   i::Handle<i::Object> result = i::GetPrototype(self);
2038   return Utils::ToLocal(result);
2039 }
2040 
2041 
SetPrototype(Handle<Value> value)2042 bool v8::Object::SetPrototype(Handle<Value> value) {
2043   ON_BAILOUT("v8::Object::SetPrototype()", return false);
2044   ENTER_V8;
2045   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2046   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2047   EXCEPTION_PREAMBLE();
2048   i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2049   has_pending_exception = result.is_null();
2050   EXCEPTION_BAILOUT_CHECK(false);
2051   return true;
2052 }
2053 
2054 
FindInstanceInPrototypeChain(v8::Handle<FunctionTemplate> tmpl)2055 Local<Object> v8::Object::FindInstanceInPrototypeChain(
2056     v8::Handle<FunctionTemplate> tmpl) {
2057   ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
2058              return Local<v8::Object>());
2059   ENTER_V8;
2060   i::JSObject* object = *Utils::OpenHandle(this);
2061   i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2062   while (!object->IsInstanceOf(tmpl_info)) {
2063     i::Object* prototype = object->GetPrototype();
2064     if (!prototype->IsJSObject()) return Local<Object>();
2065     object = i::JSObject::cast(prototype);
2066   }
2067   return Utils::ToLocal(i::Handle<i::JSObject>(object));
2068 }
2069 
2070 
GetPropertyNames()2071 Local<Array> v8::Object::GetPropertyNames() {
2072   ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
2073   ENTER_V8;
2074   v8::HandleScope scope;
2075   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2076   i::Handle<i::FixedArray> value =
2077       i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2078   // Because we use caching to speed up enumeration it is important
2079   // to never change the result of the basic enumeration function so
2080   // we clone the result.
2081   i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
2082   i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
2083   return scope.Close(Utils::ToLocal(result));
2084 }
2085 
2086 
ObjectProtoToString()2087 Local<String> v8::Object::ObjectProtoToString() {
2088   ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2089   ENTER_V8;
2090   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2091 
2092   i::Handle<i::Object> name(self->class_name());
2093 
2094   // Native implementation of Object.prototype.toString (v8natives.js):
2095   //   var c = %ClassOf(this);
2096   //   if (c === 'Arguments') c  = 'Object';
2097   //   return "[object " + c + "]";
2098 
2099   if (!name->IsString()) {
2100     return v8::String::New("[object ]");
2101 
2102   } else {
2103     i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2104     if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2105       return v8::String::New("[object Object]");
2106 
2107     } else {
2108       const char* prefix = "[object ";
2109       Local<String> str = Utils::ToLocal(class_name);
2110       const char* postfix = "]";
2111 
2112       int prefix_len = i::StrLength(prefix);
2113       int str_len = str->Length();
2114       int postfix_len = i::StrLength(postfix);
2115 
2116       int buf_len = prefix_len + str_len + postfix_len;
2117       char* buf = i::NewArray<char>(buf_len);
2118 
2119       // Write prefix.
2120       char* ptr = buf;
2121       memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2122       ptr += prefix_len;
2123 
2124       // Write real content.
2125       str->WriteAscii(ptr, 0, str_len);
2126       ptr += str_len;
2127 
2128       // Write postfix.
2129       memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2130 
2131       // Copy the buffer into a heap-allocated string and return it.
2132       Local<String> result = v8::String::New(buf, buf_len);
2133       i::DeleteArray(buf);
2134       return result;
2135     }
2136   }
2137 }
2138 
2139 
Delete(v8::Handle<String> key)2140 bool v8::Object::Delete(v8::Handle<String> key) {
2141   ON_BAILOUT("v8::Object::Delete()", return false);
2142   ENTER_V8;
2143   HandleScope scope;
2144   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2145   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2146   return i::DeleteProperty(self, key_obj)->IsTrue();
2147 }
2148 
2149 
Has(v8::Handle<String> key)2150 bool v8::Object::Has(v8::Handle<String> key) {
2151   ON_BAILOUT("v8::Object::Has()", return false);
2152   ENTER_V8;
2153   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2154   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2155   return self->HasProperty(*key_obj);
2156 }
2157 
2158 
Delete(uint32_t index)2159 bool v8::Object::Delete(uint32_t index) {
2160   ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2161   ENTER_V8;
2162   HandleScope scope;
2163   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2164   return i::DeleteElement(self, index)->IsTrue();
2165 }
2166 
2167 
Has(uint32_t index)2168 bool v8::Object::Has(uint32_t index) {
2169   ON_BAILOUT("v8::Object::HasProperty()", return false);
2170   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2171   return self->HasElement(index);
2172 }
2173 
2174 
HasRealNamedProperty(Handle<String> key)2175 bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2176   ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2177   return Utils::OpenHandle(this)->HasRealNamedProperty(
2178       *Utils::OpenHandle(*key));
2179 }
2180 
2181 
HasRealIndexedProperty(uint32_t index)2182 bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2183   ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2184   return Utils::OpenHandle(this)->HasRealElementProperty(index);
2185 }
2186 
2187 
HasRealNamedCallbackProperty(Handle<String> key)2188 bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2189   ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2190   ENTER_V8;
2191   return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2192       *Utils::OpenHandle(*key));
2193 }
2194 
2195 
HasNamedLookupInterceptor()2196 bool v8::Object::HasNamedLookupInterceptor() {
2197   ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2198   return Utils::OpenHandle(this)->HasNamedInterceptor();
2199 }
2200 
2201 
HasIndexedLookupInterceptor()2202 bool v8::Object::HasIndexedLookupInterceptor() {
2203   ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2204   return Utils::OpenHandle(this)->HasIndexedInterceptor();
2205 }
2206 
2207 
GetRealNamedPropertyInPrototypeChain(Handle<String> key)2208 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2209       Handle<String> key) {
2210   ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2211              return Local<Value>());
2212   ENTER_V8;
2213   i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2214   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2215   i::LookupResult lookup;
2216   self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
2217   if (lookup.IsProperty()) {
2218     PropertyAttributes attributes;
2219     i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2220                                                       &lookup,
2221                                                       *key_obj,
2222                                                       &attributes));
2223     return Utils::ToLocal(result);
2224   }
2225   return Local<Value>();  // No real property was found in prototype chain.
2226 }
2227 
2228 
GetRealNamedProperty(Handle<String> key)2229 Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2230   ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
2231   ENTER_V8;
2232   i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2233   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2234   i::LookupResult lookup;
2235   self_obj->LookupRealNamedProperty(*key_obj, &lookup);
2236   if (lookup.IsProperty()) {
2237     PropertyAttributes attributes;
2238     i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2239                                                       &lookup,
2240                                                       *key_obj,
2241                                                       &attributes));
2242     return Utils::ToLocal(result);
2243   }
2244   return Local<Value>();  // No real property was found in prototype chain.
2245 }
2246 
2247 
2248 // Turns on access checks by copying the map and setting the check flag.
2249 // Because the object gets a new map, existing inline cache caching
2250 // the old map of this object will fail.
TurnOnAccessCheck()2251 void v8::Object::TurnOnAccessCheck() {
2252   ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2253   ENTER_V8;
2254   HandleScope scope;
2255   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2256 
2257   i::Handle<i::Map> new_map =
2258     i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2259   new_map->set_is_access_check_needed(true);
2260   obj->set_map(*new_map);
2261 }
2262 
2263 
IsDirty()2264 bool v8::Object::IsDirty() {
2265   return Utils::OpenHandle(this)->IsDirty();
2266 }
2267 
2268 
Clone()2269 Local<v8::Object> v8::Object::Clone() {
2270   ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2271   ENTER_V8;
2272   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2273   EXCEPTION_PREAMBLE();
2274   i::Handle<i::JSObject> result = i::Copy(self);
2275   has_pending_exception = result.is_null();
2276   EXCEPTION_BAILOUT_CHECK(Local<Object>());
2277   return Utils::ToLocal(result);
2278 }
2279 
2280 
GetIdentityHash()2281 int v8::Object::GetIdentityHash() {
2282   ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2283   ENTER_V8;
2284   HandleScope scope;
2285   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2286   i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2287   i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
2288   i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2289   int hash_value;
2290   if (hash->IsSmi()) {
2291     hash_value = i::Smi::cast(*hash)->value();
2292   } else {
2293     int attempts = 0;
2294     do {
2295       // Generate a random 32-bit hash value but limit range to fit
2296       // within a smi.
2297       hash_value = i::V8::Random() & i::Smi::kMaxValue;
2298       attempts++;
2299     } while (hash_value == 0 && attempts < 30);
2300     hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
2301     i::SetProperty(hidden_props,
2302                    hash_symbol,
2303                    i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2304                    static_cast<PropertyAttributes>(None));
2305   }
2306   return hash_value;
2307 }
2308 
2309 
SetHiddenValue(v8::Handle<v8::String> key,v8::Handle<v8::Value> value)2310 bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2311                                 v8::Handle<v8::Value> value) {
2312   ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
2313   ENTER_V8;
2314   HandleScope scope;
2315   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2316   i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2317   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2318   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2319   EXCEPTION_PREAMBLE();
2320   i::Handle<i::Object> obj = i::SetProperty(
2321       hidden_props,
2322       key_obj,
2323       value_obj,
2324       static_cast<PropertyAttributes>(None));
2325   has_pending_exception = obj.is_null();
2326   EXCEPTION_BAILOUT_CHECK(false);
2327   return true;
2328 }
2329 
2330 
GetHiddenValue(v8::Handle<v8::String> key)2331 v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2332   ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2333   ENTER_V8;
2334   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2335   i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2336   if (hidden_props->IsUndefined()) {
2337     return v8::Local<v8::Value>();
2338   }
2339   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2340   EXCEPTION_PREAMBLE();
2341   i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2342   has_pending_exception = result.is_null();
2343   EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2344   if (result->IsUndefined()) {
2345     return v8::Local<v8::Value>();
2346   }
2347   return Utils::ToLocal(result);
2348 }
2349 
2350 
DeleteHiddenValue(v8::Handle<v8::String> key)2351 bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2352   ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2353   ENTER_V8;
2354   HandleScope scope;
2355   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2356   i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2357   if (hidden_props->IsUndefined()) {
2358     return true;
2359   }
2360   i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2361   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2362   return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2363 }
2364 
2365 
SetIndexedPropertiesToPixelData(uint8_t * data,int length)2366 void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2367   ON_BAILOUT("v8::SetElementsToPixelData()", return);
2368   ENTER_V8;
2369   HandleScope scope;
2370   if (!ApiCheck(length <= i::PixelArray::kMaxLength,
2371                 "v8::Object::SetIndexedPropertiesToPixelData()",
2372                 "length exceeds max acceptable value")) {
2373     return;
2374   }
2375   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2376   if (!ApiCheck(!self->IsJSArray(),
2377                 "v8::Object::SetIndexedPropertiesToPixelData()",
2378                 "JSArray is not supported")) {
2379     return;
2380   }
2381   i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
2382   self->set_elements(*pixels);
2383 }
2384 
2385 
SetIndexedPropertiesToExternalArrayData(void * data,ExternalArrayType array_type,int length)2386 void v8::Object::SetIndexedPropertiesToExternalArrayData(
2387     void* data,
2388     ExternalArrayType array_type,
2389     int length) {
2390   ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
2391   ENTER_V8;
2392   HandleScope scope;
2393   if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
2394                 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2395                 "length exceeds max acceptable value")) {
2396     return;
2397   }
2398   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2399   if (!ApiCheck(!self->IsJSArray(),
2400                 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2401                 "JSArray is not supported")) {
2402     return;
2403   }
2404   i::Handle<i::ExternalArray> array =
2405       i::Factory::NewExternalArray(length, array_type, data);
2406   self->set_elements(*array);
2407 }
2408 
2409 
NewInstance() const2410 Local<v8::Object> Function::NewInstance() const {
2411   return NewInstance(0, NULL);
2412 }
2413 
2414 
NewInstance(int argc,v8::Handle<v8::Value> argv[]) const2415 Local<v8::Object> Function::NewInstance(int argc,
2416                                         v8::Handle<v8::Value> argv[]) const {
2417   ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2418   LOG_API("Function::NewInstance");
2419   ENTER_V8;
2420   HandleScope scope;
2421   i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2422   STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2423   i::Object*** args = reinterpret_cast<i::Object***>(argv);
2424   EXCEPTION_PREAMBLE();
2425   i::Handle<i::Object> returned =
2426       i::Execution::New(function, argc, args, &has_pending_exception);
2427   EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2428   return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2429 }
2430 
2431 
Call(v8::Handle<v8::Object> recv,int argc,v8::Handle<v8::Value> argv[])2432 Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2433                                 v8::Handle<v8::Value> argv[]) {
2434   ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2435   LOG_API("Function::Call");
2436   ENTER_V8;
2437   i::Object* raw_result = NULL;
2438   {
2439     HandleScope scope;
2440     i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2441     i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2442     STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2443     i::Object*** args = reinterpret_cast<i::Object***>(argv);
2444     EXCEPTION_PREAMBLE();
2445     i::Handle<i::Object> returned =
2446         i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2447     EXCEPTION_BAILOUT_CHECK(Local<Object>());
2448     raw_result = *returned;
2449   }
2450   i::Handle<i::Object> result(raw_result);
2451   return Utils::ToLocal(result);
2452 }
2453 
2454 
SetName(v8::Handle<v8::String> name)2455 void Function::SetName(v8::Handle<v8::String> name) {
2456   ENTER_V8;
2457   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2458   func->shared()->set_name(*Utils::OpenHandle(*name));
2459 }
2460 
2461 
GetName() const2462 Handle<Value> Function::GetName() const {
2463   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2464   return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2465 }
2466 
2467 
GetScriptOrigin() const2468 ScriptOrigin Function::GetScriptOrigin() const {
2469   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2470   if (func->shared()->script()->IsScript()) {
2471     i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2472     v8::ScriptOrigin origin(
2473       Utils::ToLocal(i::Handle<i::Object>(script->name())),
2474       v8::Integer::New(script->line_offset()->value()),
2475       v8::Integer::New(script->column_offset()->value()));
2476     return origin;
2477   }
2478   return v8::ScriptOrigin(Handle<Value>());
2479 }
2480 
2481 
2482 const int Function::kLineOffsetNotFound = -1;
2483 
2484 
GetScriptLineNumber() const2485 int Function::GetScriptLineNumber() const {
2486   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2487   if (func->shared()->script()->IsScript()) {
2488     i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2489     return i::GetScriptLineNumber(script, func->shared()->start_position());
2490   }
2491   return kLineOffsetNotFound;
2492 }
2493 
2494 
2495 namespace {
2496 
2497 // Tracks string usage to help make better decisions when
2498 // externalizing strings.
2499 //
2500 // Implementation note: internally this class only tracks fresh
2501 // strings and keeps a single use counter for them.
2502 class StringTracker {
2503  public:
2504   // Records that the given string's characters were copied to some
2505   // external buffer. If this happens often we should honor
2506   // externalization requests for the string.
RecordWrite(i::Handle<i::String> string)2507   static void RecordWrite(i::Handle<i::String> string) {
2508     i::Address address = reinterpret_cast<i::Address>(*string);
2509     i::Address top = i::Heap::NewSpaceTop();
2510     if (IsFreshString(address, top)) {
2511       IncrementUseCount(top);
2512     }
2513   }
2514 
2515   // Estimates freshness and use frequency of the given string based
2516   // on how close it is to the new space top and the recorded usage
2517   // history.
IsFreshUnusedString(i::Handle<i::String> string)2518   static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
2519     i::Address address = reinterpret_cast<i::Address>(*string);
2520     i::Address top = i::Heap::NewSpaceTop();
2521     return IsFreshString(address, top) && IsUseCountLow(top);
2522   }
2523 
2524  private:
IsFreshString(i::Address string,i::Address top)2525   static inline bool IsFreshString(i::Address string, i::Address top) {
2526     return top - kFreshnessLimit <= string && string <= top;
2527   }
2528 
IsUseCountLow(i::Address top)2529   static inline bool IsUseCountLow(i::Address top) {
2530     if (last_top_ != top) return true;
2531     return use_count_ < kUseLimit;
2532   }
2533 
IncrementUseCount(i::Address top)2534   static inline void IncrementUseCount(i::Address top) {
2535     if (last_top_ != top) {
2536       use_count_ = 0;
2537       last_top_ = top;
2538     }
2539     ++use_count_;
2540   }
2541 
2542   // How close to the new space top a fresh string has to be.
2543   static const int kFreshnessLimit = 1024;
2544 
2545   // The number of uses required to consider a string useful.
2546   static const int kUseLimit = 32;
2547 
2548   // Single use counter shared by all fresh strings.
2549   static int use_count_;
2550 
2551   // Last new space top when the use count above was valid.
2552   static i::Address last_top_;
2553 };
2554 
2555 int StringTracker::use_count_ = 0;
2556 i::Address StringTracker::last_top_ = NULL;
2557 
2558 }  // namespace
2559 
2560 
Length() const2561 int String::Length() const {
2562   if (IsDeadCheck("v8::String::Length()")) return 0;
2563   return Utils::OpenHandle(this)->length();
2564 }
2565 
2566 
Utf8Length() const2567 int String::Utf8Length() const {
2568   if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
2569   return Utils::OpenHandle(this)->Utf8Length();
2570 }
2571 
2572 
WriteUtf8(char * buffer,int capacity) const2573 int String::WriteUtf8(char* buffer, int capacity) const {
2574   if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
2575   LOG_API("String::WriteUtf8");
2576   ENTER_V8;
2577   i::Handle<i::String> str = Utils::OpenHandle(this);
2578   StringTracker::RecordWrite(str);
2579   write_input_buffer.Reset(0, *str);
2580   int len = str->length();
2581   // Encode the first K - 3 bytes directly into the buffer since we
2582   // know there's room for them.  If no capacity is given we copy all
2583   // of them here.
2584   int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
2585   int i;
2586   int pos = 0;
2587   for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
2588     i::uc32 c = write_input_buffer.GetNext();
2589     int written = unibrow::Utf8::Encode(buffer + pos, c);
2590     pos += written;
2591   }
2592   if (i < len) {
2593     // For the last characters we need to check the length for each one
2594     // because they may be longer than the remaining space in the
2595     // buffer.
2596     char intermediate[unibrow::Utf8::kMaxEncodedSize];
2597     for (; i < len && pos < capacity; i++) {
2598       i::uc32 c = write_input_buffer.GetNext();
2599       int written = unibrow::Utf8::Encode(intermediate, c);
2600       if (pos + written <= capacity) {
2601         for (int j = 0; j < written; j++)
2602           buffer[pos + j] = intermediate[j];
2603         pos += written;
2604       } else {
2605         // We've reached the end of the buffer
2606         break;
2607       }
2608     }
2609   }
2610   if (i == len && (capacity == -1 || pos < capacity))
2611     buffer[pos++] = '\0';
2612   return pos;
2613 }
2614 
2615 
WriteAscii(char * buffer,int start,int length) const2616 int String::WriteAscii(char* buffer, int start, int length) const {
2617   if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
2618   LOG_API("String::WriteAscii");
2619   ENTER_V8;
2620   ASSERT(start >= 0 && length >= -1);
2621   i::Handle<i::String> str = Utils::OpenHandle(this);
2622   StringTracker::RecordWrite(str);
2623   // Flatten the string for efficiency.  This applies whether we are
2624   // using StringInputBuffer or Get(i) to access the characters.
2625   str->TryFlattenIfNotFlat();
2626   int end = length;
2627   if ( (length == -1) || (length > str->length() - start) )
2628     end = str->length() - start;
2629   if (end < 0) return 0;
2630   write_input_buffer.Reset(start, *str);
2631   int i;
2632   for (i = 0; i < end; i++) {
2633     char c = static_cast<char>(write_input_buffer.GetNext());
2634     if (c == '\0') c = ' ';
2635     buffer[i] = c;
2636   }
2637   if (length == -1 || i < length)
2638     buffer[i] = '\0';
2639   return i;
2640 }
2641 
2642 
Write(uint16_t * buffer,int start,int length) const2643 int String::Write(uint16_t* buffer, int start, int length) const {
2644   if (IsDeadCheck("v8::String::Write()")) return 0;
2645   LOG_API("String::Write");
2646   ENTER_V8;
2647   ASSERT(start >= 0 && length >= -1);
2648   i::Handle<i::String> str = Utils::OpenHandle(this);
2649   StringTracker::RecordWrite(str);
2650   int end = length;
2651   if ( (length == -1) || (length > str->length() - start) )
2652     end = str->length() - start;
2653   if (end < 0) return 0;
2654   i::String::WriteToFlat(*str, buffer, start, end);
2655   if (length == -1 || end < length)
2656     buffer[end] = '\0';
2657   return end;
2658 }
2659 
2660 
IsExternal() const2661 bool v8::String::IsExternal() const {
2662   EnsureInitialized("v8::String::IsExternal()");
2663   i::Handle<i::String> str = Utils::OpenHandle(this);
2664   return i::StringShape(*str).IsExternalTwoByte();
2665 }
2666 
2667 
IsExternalAscii() const2668 bool v8::String::IsExternalAscii() const {
2669   EnsureInitialized("v8::String::IsExternalAscii()");
2670   i::Handle<i::String> str = Utils::OpenHandle(this);
2671   return i::StringShape(*str).IsExternalAscii();
2672 }
2673 
2674 
VerifyExternalStringResource(v8::String::ExternalStringResource * value) const2675 void v8::String::VerifyExternalStringResource(
2676     v8::String::ExternalStringResource* value) const {
2677   i::Handle<i::String> str = Utils::OpenHandle(this);
2678   v8::String::ExternalStringResource* expected;
2679   if (i::StringShape(*str).IsExternalTwoByte()) {
2680     void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
2681     expected = reinterpret_cast<ExternalStringResource*>(resource);
2682   } else {
2683     expected = NULL;
2684   }
2685   CHECK_EQ(expected, value);
2686 }
2687 
2688 
2689 v8::String::ExternalAsciiStringResource*
GetExternalAsciiStringResource() const2690       v8::String::GetExternalAsciiStringResource() const {
2691   EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
2692   i::Handle<i::String> str = Utils::OpenHandle(this);
2693   if (i::StringShape(*str).IsExternalAscii()) {
2694     void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
2695     return reinterpret_cast<ExternalAsciiStringResource*>(resource);
2696   } else {
2697     return NULL;
2698   }
2699 }
2700 
2701 
Value() const2702 double Number::Value() const {
2703   if (IsDeadCheck("v8::Number::Value()")) return 0;
2704   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2705   return obj->Number();
2706 }
2707 
2708 
Value() const2709 bool Boolean::Value() const {
2710   if (IsDeadCheck("v8::Boolean::Value()")) return false;
2711   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2712   return obj->IsTrue();
2713 }
2714 
2715 
Value() const2716 int64_t Integer::Value() const {
2717   if (IsDeadCheck("v8::Integer::Value()")) return 0;
2718   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2719   if (obj->IsSmi()) {
2720     return i::Smi::cast(*obj)->value();
2721   } else {
2722     return static_cast<int64_t>(obj->Number());
2723   }
2724 }
2725 
2726 
Value() const2727 int32_t Int32::Value() const {
2728   if (IsDeadCheck("v8::Int32::Value()")) return 0;
2729   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2730   if (obj->IsSmi()) {
2731     return i::Smi::cast(*obj)->value();
2732   } else {
2733     return static_cast<int32_t>(obj->Number());
2734   }
2735 }
2736 
2737 
InternalFieldCount()2738 int v8::Object::InternalFieldCount() {
2739   if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
2740   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2741   return obj->GetInternalFieldCount();
2742 }
2743 
2744 
CheckedGetInternalField(int index)2745 Local<Value> v8::Object::CheckedGetInternalField(int index) {
2746   if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
2747   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2748   if (!ApiCheck(index < obj->GetInternalFieldCount(),
2749                 "v8::Object::GetInternalField()",
2750                 "Reading internal field out of bounds")) {
2751     return Local<Value>();
2752   }
2753   i::Handle<i::Object> value(obj->GetInternalField(index));
2754   Local<Value> result = Utils::ToLocal(value);
2755 #ifdef DEBUG
2756   Local<Value> unchecked = UncheckedGetInternalField(index);
2757   ASSERT(unchecked.IsEmpty() || (unchecked == result));
2758 #endif
2759   return result;
2760 }
2761 
2762 
SetInternalField(int index,v8::Handle<Value> value)2763 void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
2764   if (IsDeadCheck("v8::Object::SetInternalField()")) return;
2765   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2766   if (!ApiCheck(index < obj->GetInternalFieldCount(),
2767                 "v8::Object::SetInternalField()",
2768                 "Writing internal field out of bounds")) {
2769     return;
2770   }
2771   ENTER_V8;
2772   i::Handle<i::Object> val = Utils::OpenHandle(*value);
2773   obj->SetInternalField(index, *val);
2774 }
2775 
2776 
SetPointerInInternalField(int index,void * value)2777 void v8::Object::SetPointerInInternalField(int index, void* value) {
2778   i::Object* as_object = reinterpret_cast<i::Object*>(value);
2779   if (as_object->IsSmi()) {
2780     Utils::OpenHandle(this)->SetInternalField(index, as_object);
2781     return;
2782   }
2783   HandleScope scope;
2784   i::Handle<i::Proxy> proxy =
2785       i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
2786   if (!proxy.is_null())
2787       Utils::OpenHandle(this)->SetInternalField(index, *proxy);
2788 }
2789 
2790 
2791 // --- E n v i r o n m e n t ---
2792 
Initialize()2793 bool v8::V8::Initialize() {
2794   if (i::V8::IsRunning()) return true;
2795   ENTER_V8;
2796   HandleScope scope;
2797   if (i::Snapshot::Initialize()) return true;
2798   return i::V8::Initialize(NULL);
2799 }
2800 
2801 
Dispose()2802 bool v8::V8::Dispose() {
2803   i::V8::TearDown();
2804   return true;
2805 }
2806 
2807 
HeapStatistics()2808 HeapStatistics::HeapStatistics(): total_heap_size_(0), used_heap_size_(0) { }
2809 
2810 
GetHeapStatistics(HeapStatistics * heap_statistics)2811 void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
2812   heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
2813   heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
2814 }
2815 
2816 
IdleNotification()2817 bool v8::V8::IdleNotification() {
2818   // Returning true tells the caller that it need not
2819   // continue to call IdleNotification.
2820   if (!i::V8::IsRunning()) return true;
2821   return i::V8::IdleNotification();
2822 }
2823 
2824 
LowMemoryNotification()2825 void v8::V8::LowMemoryNotification() {
2826   if (!i::V8::IsRunning()) return;
2827   i::Heap::CollectAllGarbage(true);
2828 }
2829 
2830 
GetVersion()2831 const char* v8::V8::GetVersion() {
2832   static v8::internal::EmbeddedVector<char, 128> buffer;
2833   v8::internal::Version::GetString(buffer);
2834   return buffer.start();
2835 }
2836 
2837 
2838 static i::Handle<i::FunctionTemplateInfo>
EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ)2839     EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
2840   if (templ->constructor()->IsUndefined()) {
2841     Local<FunctionTemplate> constructor = FunctionTemplate::New();
2842     Utils::OpenHandle(*constructor)->set_instance_template(*templ);
2843     templ->set_constructor(*Utils::OpenHandle(*constructor));
2844   }
2845   return i::Handle<i::FunctionTemplateInfo>(
2846     i::FunctionTemplateInfo::cast(templ->constructor()));
2847 }
2848 
2849 
New(v8::ExtensionConfiguration * extensions,v8::Handle<ObjectTemplate> global_template,v8::Handle<Value> global_object)2850 Persistent<Context> v8::Context::New(
2851     v8::ExtensionConfiguration* extensions,
2852     v8::Handle<ObjectTemplate> global_template,
2853     v8::Handle<Value> global_object) {
2854   EnsureInitialized("v8::Context::New()");
2855   LOG_API("Context::New");
2856   ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
2857 
2858 #if defined(ANDROID)
2859   // On mobile device, full GC is expensive, leave it to the system to
2860   // decide when should make a full GC.
2861 #else
2862   // Give the heap a chance to cleanup if we've disposed contexts.
2863   i::Heap::CollectAllGarbageIfContextDisposed();
2864 #endif
2865 
2866   // Enter V8 via an ENTER_V8 scope.
2867   i::Handle<i::Context> env;
2868   {
2869     ENTER_V8;
2870     v8::Handle<ObjectTemplate> proxy_template = global_template;
2871     i::Handle<i::FunctionTemplateInfo> proxy_constructor;
2872     i::Handle<i::FunctionTemplateInfo> global_constructor;
2873 
2874     if (!global_template.IsEmpty()) {
2875       // Make sure that the global_template has a constructor.
2876       global_constructor =
2877           EnsureConstructor(Utils::OpenHandle(*global_template));
2878 
2879       // Create a fresh template for the global proxy object.
2880       proxy_template = ObjectTemplate::New();
2881       proxy_constructor =
2882           EnsureConstructor(Utils::OpenHandle(*proxy_template));
2883 
2884       // Set the global template to be the prototype template of
2885       // global proxy template.
2886       proxy_constructor->set_prototype_template(
2887           *Utils::OpenHandle(*global_template));
2888 
2889       // Migrate security handlers from global_template to
2890       // proxy_template.  Temporarily removing access check
2891       // information from the global template.
2892       if (!global_constructor->access_check_info()->IsUndefined()) {
2893         proxy_constructor->set_access_check_info(
2894             global_constructor->access_check_info());
2895         proxy_constructor->set_needs_access_check(
2896             global_constructor->needs_access_check());
2897         global_constructor->set_needs_access_check(false);
2898         global_constructor->set_access_check_info(i::Heap::undefined_value());
2899       }
2900     }
2901 
2902     // Create the environment.
2903     env = i::Bootstrapper::CreateEnvironment(
2904         Utils::OpenHandle(*global_object),
2905         proxy_template,
2906         extensions);
2907 
2908     // Restore the access check info on the global template.
2909     if (!global_template.IsEmpty()) {
2910       ASSERT(!global_constructor.is_null());
2911       ASSERT(!proxy_constructor.is_null());
2912       global_constructor->set_access_check_info(
2913           proxy_constructor->access_check_info());
2914       global_constructor->set_needs_access_check(
2915           proxy_constructor->needs_access_check());
2916     }
2917   }
2918   // Leave V8.
2919 
2920   if (env.is_null())
2921     return Persistent<Context>();
2922   return Persistent<Context>(Utils::ToLocal(env));
2923 }
2924 
2925 
SetSecurityToken(Handle<Value> token)2926 void v8::Context::SetSecurityToken(Handle<Value> token) {
2927   if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
2928   ENTER_V8;
2929   i::Handle<i::Context> env = Utils::OpenHandle(this);
2930   i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
2931   env->set_security_token(*token_handle);
2932 }
2933 
2934 
UseDefaultSecurityToken()2935 void v8::Context::UseDefaultSecurityToken() {
2936   if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
2937   ENTER_V8;
2938   i::Handle<i::Context> env = Utils::OpenHandle(this);
2939   env->set_security_token(env->global());
2940 }
2941 
2942 
GetSecurityToken()2943 Handle<Value> v8::Context::GetSecurityToken() {
2944   if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
2945   i::Handle<i::Context> env = Utils::OpenHandle(this);
2946   i::Object* security_token = env->security_token();
2947   i::Handle<i::Object> token_handle(security_token);
2948   return Utils::ToLocal(token_handle);
2949 }
2950 
2951 
HasOutOfMemoryException()2952 bool Context::HasOutOfMemoryException() {
2953   i::Handle<i::Context> env = Utils::OpenHandle(this);
2954   return env->has_out_of_memory();
2955 }
2956 
2957 
InContext()2958 bool Context::InContext() {
2959   return i::Top::context() != NULL;
2960 }
2961 
2962 
GetEntered()2963 v8::Local<v8::Context> Context::GetEntered() {
2964   if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
2965   i::Handle<i::Object> last = thread_local.LastEnteredContext();
2966   if (last.is_null()) return Local<Context>();
2967   i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
2968   return Utils::ToLocal(context);
2969 }
2970 
2971 
GetCurrent()2972 v8::Local<v8::Context> Context::GetCurrent() {
2973   if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
2974   i::Handle<i::Object> current = i::Top::global_context();
2975   if (current.is_null()) return Local<Context>();
2976   i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
2977   return Utils::ToLocal(context);
2978 }
2979 
2980 
GetCalling()2981 v8::Local<v8::Context> Context::GetCalling() {
2982   if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
2983   i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
2984   if (calling.is_null()) return Local<Context>();
2985   i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
2986   return Utils::ToLocal(context);
2987 }
2988 
2989 
Global()2990 v8::Local<v8::Object> Context::Global() {
2991   if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
2992   i::Object** ctx = reinterpret_cast<i::Object**>(this);
2993   i::Handle<i::Context> context =
2994       i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
2995   i::Handle<i::Object> global(context->global_proxy());
2996   return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
2997 }
2998 
2999 
DetachGlobal()3000 void Context::DetachGlobal() {
3001   if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
3002   ENTER_V8;
3003   i::Object** ctx = reinterpret_cast<i::Object**>(this);
3004   i::Handle<i::Context> context =
3005       i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3006   i::Bootstrapper::DetachGlobal(context);
3007 }
3008 
3009 
ReattachGlobal(Handle<Object> global_object)3010 void Context::ReattachGlobal(Handle<Object> global_object) {
3011   if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
3012   ENTER_V8;
3013   i::Object** ctx = reinterpret_cast<i::Object**>(this);
3014   i::Handle<i::Context> context =
3015       i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3016   i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
3017 }
3018 
3019 
NewInstance()3020 Local<v8::Object> ObjectTemplate::NewInstance() {
3021   ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
3022   LOG_API("ObjectTemplate::NewInstance");
3023   ENTER_V8;
3024   EXCEPTION_PREAMBLE();
3025   i::Handle<i::Object> obj =
3026       i::Execution::InstantiateObject(Utils::OpenHandle(this),
3027                                       &has_pending_exception);
3028   EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
3029   return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3030 }
3031 
3032 
GetFunction()3033 Local<v8::Function> FunctionTemplate::GetFunction() {
3034   ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
3035              return Local<v8::Function>());
3036   LOG_API("FunctionTemplate::GetFunction");
3037   ENTER_V8;
3038   EXCEPTION_PREAMBLE();
3039   i::Handle<i::Object> obj =
3040       i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3041                                         &has_pending_exception);
3042   EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
3043   return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3044 }
3045 
3046 
HasInstance(v8::Handle<v8::Value> value)3047 bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3048   ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
3049   i::Object* obj = *Utils::OpenHandle(*value);
3050   return obj->IsInstanceOf(*Utils::OpenHandle(this));
3051 }
3052 
3053 
ExternalNewImpl(void * data)3054 static Local<External> ExternalNewImpl(void* data) {
3055   return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
3056 }
3057 
ExternalValueImpl(i::Handle<i::Object> obj)3058 static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3059   return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3060 }
3061 
3062 
Wrap(void * data)3063 Local<Value> v8::External::Wrap(void* data) {
3064   STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3065   LOG_API("External::Wrap");
3066   EnsureInitialized("v8::External::Wrap()");
3067   ENTER_V8;
3068   i::Object* as_object = reinterpret_cast<i::Object*>(data);
3069   if (as_object->IsSmi()) {
3070     return Utils::ToLocal(i::Handle<i::Object>(as_object));
3071   }
3072   return ExternalNewImpl(data);
3073 }
3074 
3075 
SlowGetPointerFromInternalField(int index)3076 void* v8::Object::SlowGetPointerFromInternalField(int index) {
3077   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3078   i::Object* value = obj->GetInternalField(index);
3079   if (value->IsSmi()) {
3080     return value;
3081   } else if (value->IsProxy()) {
3082     return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3083   } else {
3084     return NULL;
3085   }
3086 }
3087 
3088 
FullUnwrap(v8::Handle<v8::Value> wrapper)3089 void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3090   if (IsDeadCheck("v8::External::Unwrap()")) return 0;
3091   i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3092   void* result;
3093   if (obj->IsSmi()) {
3094     // The external value was an aligned pointer.
3095     result = *obj;
3096   } else if (obj->IsProxy()) {
3097     result = ExternalValueImpl(obj);
3098   } else {
3099     result = NULL;
3100   }
3101   ASSERT_EQ(result, QuickUnwrap(wrapper));
3102   return result;
3103 }
3104 
3105 
New(void * data)3106 Local<External> v8::External::New(void* data) {
3107   STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3108   LOG_API("External::New");
3109   EnsureInitialized("v8::External::New()");
3110   ENTER_V8;
3111   return ExternalNewImpl(data);
3112 }
3113 
3114 
Value() const3115 void* External::Value() const {
3116   if (IsDeadCheck("v8::External::Value()")) return 0;
3117   i::Handle<i::Object> obj = Utils::OpenHandle(this);
3118   return ExternalValueImpl(obj);
3119 }
3120 
3121 
Empty()3122 Local<String> v8::String::Empty() {
3123   EnsureInitialized("v8::String::Empty()");
3124   LOG_API("String::Empty()");
3125   return Utils::ToLocal(i::Factory::empty_symbol());
3126 }
3127 
3128 
New(const char * data,int length)3129 Local<String> v8::String::New(const char* data, int length) {
3130   EnsureInitialized("v8::String::New()");
3131   LOG_API("String::New(char)");
3132   if (length == 0) return Empty();
3133   ENTER_V8;
3134   if (length == -1) length = i::StrLength(data);
3135   i::Handle<i::String> result =
3136       i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3137   return Utils::ToLocal(result);
3138 }
3139 
3140 
Concat(Handle<String> left,Handle<String> right)3141 Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3142   EnsureInitialized("v8::String::New()");
3143   LOG_API("String::New(char)");
3144   ENTER_V8;
3145   i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3146   i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3147   i::Handle<i::String> result = i::Factory::NewConsString(left_string,
3148                                                           right_string);
3149   return Utils::ToLocal(result);
3150 }
3151 
3152 
NewUndetectable(const char * data,int length)3153 Local<String> v8::String::NewUndetectable(const char* data, int length) {
3154   EnsureInitialized("v8::String::NewUndetectable()");
3155   LOG_API("String::NewUndetectable(char)");
3156   ENTER_V8;
3157   if (length == -1) length = i::StrLength(data);
3158   i::Handle<i::String> result =
3159       i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3160   result->MarkAsUndetectable();
3161   return Utils::ToLocal(result);
3162 }
3163 
3164 
TwoByteStringLength(const uint16_t * data)3165 static int TwoByteStringLength(const uint16_t* data) {
3166   int length = 0;
3167   while (data[length] != '\0') length++;
3168   return length;
3169 }
3170 
3171 
New(const uint16_t * data,int length)3172 Local<String> v8::String::New(const uint16_t* data, int length) {
3173   EnsureInitialized("v8::String::New()");
3174   LOG_API("String::New(uint16_)");
3175   if (length == 0) return Empty();
3176   ENTER_V8;
3177   if (length == -1) length = TwoByteStringLength(data);
3178   i::Handle<i::String> result =
3179       i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3180   return Utils::ToLocal(result);
3181 }
3182 
3183 
NewUndetectable(const uint16_t * data,int length)3184 Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
3185   EnsureInitialized("v8::String::NewUndetectable()");
3186   LOG_API("String::NewUndetectable(uint16_)");
3187   ENTER_V8;
3188   if (length == -1) length = TwoByteStringLength(data);
3189   i::Handle<i::String> result =
3190       i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3191   result->MarkAsUndetectable();
3192   return Utils::ToLocal(result);
3193 }
3194 
3195 
NewExternalStringHandle(v8::String::ExternalStringResource * resource)3196 i::Handle<i::String> NewExternalStringHandle(
3197       v8::String::ExternalStringResource* resource) {
3198   i::Handle<i::String> result =
3199       i::Factory::NewExternalStringFromTwoByte(resource);
3200   return result;
3201 }
3202 
3203 
NewExternalAsciiStringHandle(v8::String::ExternalAsciiStringResource * resource)3204 i::Handle<i::String> NewExternalAsciiStringHandle(
3205       v8::String::ExternalAsciiStringResource* resource) {
3206   i::Handle<i::String> result =
3207       i::Factory::NewExternalStringFromAscii(resource);
3208   return result;
3209 }
3210 
3211 
NewExternal(v8::String::ExternalStringResource * resource)3212 Local<String> v8::String::NewExternal(
3213       v8::String::ExternalStringResource* resource) {
3214   EnsureInitialized("v8::String::NewExternal()");
3215   LOG_API("String::NewExternal");
3216   ENTER_V8;
3217   i::Handle<i::String> result = NewExternalStringHandle(resource);
3218   i::ExternalStringTable::AddString(*result);
3219   return Utils::ToLocal(result);
3220 }
3221 
3222 
MakeExternal(v8::String::ExternalStringResource * resource)3223 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3224   if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3225   if (this->IsExternal()) return false;  // Already an external string.
3226   ENTER_V8;
3227   i::Handle<i::String> obj = Utils::OpenHandle(this);
3228   if (StringTracker::IsFreshUnusedString(obj)) return false;
3229   bool result = obj->MakeExternal(resource);
3230   if (result && !obj->IsSymbol()) {
3231     i::ExternalStringTable::AddString(*obj);
3232   }
3233   return result;
3234 }
3235 
3236 
NewExternal(v8::String::ExternalAsciiStringResource * resource)3237 Local<String> v8::String::NewExternal(
3238       v8::String::ExternalAsciiStringResource* resource) {
3239   EnsureInitialized("v8::String::NewExternal()");
3240   LOG_API("String::NewExternal");
3241   ENTER_V8;
3242   i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
3243   i::ExternalStringTable::AddString(*result);
3244   return Utils::ToLocal(result);
3245 }
3246 
3247 
MakeExternal(v8::String::ExternalAsciiStringResource * resource)3248 bool v8::String::MakeExternal(
3249     v8::String::ExternalAsciiStringResource* resource) {
3250   if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3251   if (this->IsExternal()) return false;  // Already an external string.
3252   ENTER_V8;
3253   i::Handle<i::String> obj = Utils::OpenHandle(this);
3254   if (StringTracker::IsFreshUnusedString(obj)) return false;
3255   bool result = obj->MakeExternal(resource);
3256   if (result && !obj->IsSymbol()) {
3257     i::ExternalStringTable::AddString(*obj);
3258   }
3259   return result;
3260 }
3261 
3262 
CanMakeExternal()3263 bool v8::String::CanMakeExternal() {
3264   if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3265   i::Handle<i::String> obj = Utils::OpenHandle(this);
3266   if (StringTracker::IsFreshUnusedString(obj)) return false;
3267   int size = obj->Size();  // Byte size of the original string.
3268   if (size < i::ExternalString::kSize)
3269     return false;
3270   i::StringShape shape(*obj);
3271   return !shape.IsExternal();
3272 }
3273 
3274 
New()3275 Local<v8::Object> v8::Object::New() {
3276   EnsureInitialized("v8::Object::New()");
3277   LOG_API("Object::New");
3278   ENTER_V8;
3279   i::Handle<i::JSObject> obj =
3280       i::Factory::NewJSObject(i::Top::object_function());
3281   return Utils::ToLocal(obj);
3282 }
3283 
3284 
New(double time)3285 Local<v8::Value> v8::Date::New(double time) {
3286   EnsureInitialized("v8::Date::New()");
3287   LOG_API("Date::New");
3288   if (isnan(time)) {
3289     // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3290     time = i::OS::nan_value();
3291   }
3292   ENTER_V8;
3293   EXCEPTION_PREAMBLE();
3294   i::Handle<i::Object> obj =
3295       i::Execution::NewDate(time, &has_pending_exception);
3296   EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3297   return Utils::ToLocal(obj);
3298 }
3299 
3300 
NumberValue() const3301 double v8::Date::NumberValue() const {
3302   if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3303   LOG_API("Date::NumberValue");
3304   i::Handle<i::Object> obj = Utils::OpenHandle(this);
3305   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3306   return jsvalue->value()->Number();
3307 }
3308 
3309 
New(int length)3310 Local<v8::Array> v8::Array::New(int length) {
3311   EnsureInitialized("v8::Array::New()");
3312   LOG_API("Array::New");
3313   ENTER_V8;
3314   i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3315   return Utils::ToLocal(obj);
3316 }
3317 
3318 
Length() const3319 uint32_t v8::Array::Length() const {
3320   if (IsDeadCheck("v8::Array::Length()")) return 0;
3321   i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3322   i::Object* length = obj->length();
3323   if (length->IsSmi()) {
3324     return i::Smi::cast(length)->value();
3325   } else {
3326     return static_cast<uint32_t>(length->Number());
3327   }
3328 }
3329 
3330 
CloneElementAt(uint32_t index)3331 Local<Object> Array::CloneElementAt(uint32_t index) {
3332   ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3333   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3334   if (!self->HasFastElements()) {
3335     return Local<Object>();
3336   }
3337   i::FixedArray* elms = i::FixedArray::cast(self->elements());
3338   i::Object* paragon = elms->get(index);
3339   if (!paragon->IsJSObject()) {
3340     return Local<Object>();
3341   }
3342   i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3343   EXCEPTION_PREAMBLE();
3344   i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3345   has_pending_exception = result.is_null();
3346   EXCEPTION_BAILOUT_CHECK(Local<Object>());
3347   return Utils::ToLocal(result);
3348 }
3349 
3350 
NewSymbol(const char * data,int length)3351 Local<String> v8::String::NewSymbol(const char* data, int length) {
3352   EnsureInitialized("v8::String::NewSymbol()");
3353   LOG_API("String::NewSymbol(char)");
3354   ENTER_V8;
3355   if (length == -1) length = i::StrLength(data);
3356   i::Handle<i::String> result =
3357       i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3358   return Utils::ToLocal(result);
3359 }
3360 
3361 
New(double value)3362 Local<Number> v8::Number::New(double value) {
3363   EnsureInitialized("v8::Number::New()");
3364   if (isnan(value)) {
3365     // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3366     value = i::OS::nan_value();
3367   }
3368   ENTER_V8;
3369   i::Handle<i::Object> result = i::Factory::NewNumber(value);
3370   return Utils::NumberToLocal(result);
3371 }
3372 
3373 
New(int32_t value)3374 Local<Integer> v8::Integer::New(int32_t value) {
3375   EnsureInitialized("v8::Integer::New()");
3376   if (i::Smi::IsValid(value)) {
3377     return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3378   }
3379   ENTER_V8;
3380   i::Handle<i::Object> result = i::Factory::NewNumber(value);
3381   return Utils::IntegerToLocal(result);
3382 }
3383 
3384 
NewFromUnsigned(uint32_t value)3385 Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
3386   bool fits_into_int32_t = (value & (1 << 31)) == 0;
3387   if (fits_into_int32_t) {
3388     return Integer::New(static_cast<int32_t>(value));
3389   }
3390   ENTER_V8;
3391   i::Handle<i::Object> result = i::Factory::NewNumber(value);
3392   return Utils::IntegerToLocal(result);
3393 }
3394 
3395 
IgnoreOutOfMemoryException()3396 void V8::IgnoreOutOfMemoryException() {
3397   thread_local.set_ignore_out_of_memory(true);
3398 }
3399 
3400 
AddMessageListener(MessageCallback that,Handle<Value> data)3401 bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
3402   EnsureInitialized("v8::V8::AddMessageListener()");
3403   ON_BAILOUT("v8::V8::AddMessageListener()", return false);
3404   ENTER_V8;
3405   HandleScope scope;
3406   NeanderArray listeners(i::Factory::message_listeners());
3407   NeanderObject obj(2);
3408   obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
3409   obj.set(1, data.IsEmpty() ?
3410              i::Heap::undefined_value() :
3411              *Utils::OpenHandle(*data));
3412   listeners.add(obj.value());
3413   return true;
3414 }
3415 
3416 
RemoveMessageListeners(MessageCallback that)3417 void V8::RemoveMessageListeners(MessageCallback that) {
3418   EnsureInitialized("v8::V8::RemoveMessageListener()");
3419   ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
3420   ENTER_V8;
3421   HandleScope scope;
3422   NeanderArray listeners(i::Factory::message_listeners());
3423   for (int i = 0; i < listeners.length(); i++) {
3424     if (listeners.get(i)->IsUndefined()) continue;  // skip deleted ones
3425 
3426     NeanderObject listener(i::JSObject::cast(listeners.get(i)));
3427     i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
3428     if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
3429       listeners.set(i, i::Heap::undefined_value());
3430     }
3431   }
3432 }
3433 
3434 
SetCounterFunction(CounterLookupCallback callback)3435 void V8::SetCounterFunction(CounterLookupCallback callback) {
3436   if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
3437   i::StatsTable::SetCounterFunction(callback);
3438 }
3439 
SetCreateHistogramFunction(CreateHistogramCallback callback)3440 void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
3441   if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
3442   i::StatsTable::SetCreateHistogramFunction(callback);
3443 }
3444 
SetAddHistogramSampleFunction(AddHistogramSampleCallback callback)3445 void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
3446   if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
3447   i::StatsTable::SetAddHistogramSampleFunction(callback);
3448 }
3449 
EnableSlidingStateWindow()3450 void V8::EnableSlidingStateWindow() {
3451   if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
3452   i::Logger::EnableSlidingStateWindow();
3453 }
3454 
3455 
SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback callback)3456 void V8::SetFailedAccessCheckCallbackFunction(
3457       FailedAccessCheckCallback callback) {
3458   if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
3459   i::Top::SetFailedAccessCheckCallback(callback);
3460 }
3461 
3462 
AddObjectGroup(Persistent<Value> * objects,size_t length)3463 void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
3464   if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
3465   STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
3466   i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
3467 }
3468 
3469 
AdjustAmountOfExternalAllocatedMemory(int change_in_bytes)3470 int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
3471   if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
3472   return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
3473 }
3474 
3475 
SetGlobalGCPrologueCallback(GCCallback callback)3476 void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
3477   if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
3478   i::Heap::SetGlobalGCPrologueCallback(callback);
3479 }
3480 
3481 
SetGlobalGCEpilogueCallback(GCCallback callback)3482 void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
3483   if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
3484   i::Heap::SetGlobalGCEpilogueCallback(callback);
3485 }
3486 
3487 
PauseProfiler()3488 void V8::PauseProfiler() {
3489 #ifdef ENABLE_LOGGING_AND_PROFILING
3490   PauseProfilerEx(PROFILER_MODULE_CPU);
3491 #endif
3492 }
3493 
3494 
ResumeProfiler()3495 void V8::ResumeProfiler() {
3496 #ifdef ENABLE_LOGGING_AND_PROFILING
3497   ResumeProfilerEx(PROFILER_MODULE_CPU);
3498 #endif
3499 }
3500 
3501 
IsProfilerPaused()3502 bool V8::IsProfilerPaused() {
3503 #ifdef ENABLE_LOGGING_AND_PROFILING
3504   return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
3505 #else
3506   return true;
3507 #endif
3508 }
3509 
3510 
ResumeProfilerEx(int flags,int tag)3511 void V8::ResumeProfilerEx(int flags, int tag) {
3512 #ifdef ENABLE_LOGGING_AND_PROFILING
3513   if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
3514     // Snapshot mode: resume modules, perform GC, then pause only
3515     // those modules which haven't been started prior to making a
3516     // snapshot.
3517 
3518     // Reset snapshot flag and CPU module flags.
3519     flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
3520     const int current_flags = i::Logger::GetActiveProfilerModules();
3521     i::Logger::ResumeProfiler(flags, tag);
3522     i::Heap::CollectAllGarbage(false);
3523     i::Logger::PauseProfiler(~current_flags & flags, tag);
3524   } else {
3525     i::Logger::ResumeProfiler(flags, tag);
3526   }
3527 #endif
3528 }
3529 
3530 
PauseProfilerEx(int flags,int tag)3531 void V8::PauseProfilerEx(int flags, int tag) {
3532 #ifdef ENABLE_LOGGING_AND_PROFILING
3533   i::Logger::PauseProfiler(flags, tag);
3534 #endif
3535 }
3536 
3537 
GetActiveProfilerModules()3538 int V8::GetActiveProfilerModules() {
3539 #ifdef ENABLE_LOGGING_AND_PROFILING
3540   return i::Logger::GetActiveProfilerModules();
3541 #else
3542   return PROFILER_MODULE_NONE;
3543 #endif
3544 }
3545 
3546 
GetLogLines(int from_pos,char * dest_buf,int max_size)3547 int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
3548 #ifdef ENABLE_LOGGING_AND_PROFILING
3549   return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
3550 #endif
3551   return 0;
3552 }
3553 
3554 
GetCurrentThreadId()3555 int V8::GetCurrentThreadId() {
3556   API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3557   EnsureInitialized("V8::GetCurrentThreadId()");
3558   return i::Top::thread_id();
3559 }
3560 
3561 
TerminateExecution(int thread_id)3562 void V8::TerminateExecution(int thread_id) {
3563   if (!i::V8::IsRunning()) return;
3564   API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3565   // If the thread_id identifies the current thread just terminate
3566   // execution right away.  Otherwise, ask the thread manager to
3567   // terminate the thread with the given id if any.
3568   if (thread_id == i::Top::thread_id()) {
3569     i::StackGuard::TerminateExecution();
3570   } else {
3571     i::ThreadManager::TerminateExecution(thread_id);
3572   }
3573 }
3574 
3575 
TerminateExecution()3576 void V8::TerminateExecution() {
3577   if (!i::V8::IsRunning()) return;
3578   i::StackGuard::TerminateExecution();
3579 }
3580 
3581 
Utf8Value(v8::Handle<v8::Value> obj)3582 String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
3583   EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
3584   if (obj.IsEmpty()) {
3585     str_ = NULL;
3586     length_ = 0;
3587     return;
3588   }
3589   ENTER_V8;
3590   HandleScope scope;
3591   TryCatch try_catch;
3592   Handle<String> str = obj->ToString();
3593   if (str.IsEmpty()) {
3594     str_ = NULL;
3595     length_ = 0;
3596   } else {
3597     length_ = str->Utf8Length();
3598     str_ = i::NewArray<char>(length_ + 1);
3599     str->WriteUtf8(str_);
3600   }
3601 }
3602 
3603 
~Utf8Value()3604 String::Utf8Value::~Utf8Value() {
3605   i::DeleteArray(str_);
3606 }
3607 
3608 
AsciiValue(v8::Handle<v8::Value> obj)3609 String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
3610   EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
3611   if (obj.IsEmpty()) {
3612     str_ = NULL;
3613     length_ = 0;
3614     return;
3615   }
3616   ENTER_V8;
3617   HandleScope scope;
3618   TryCatch try_catch;
3619   Handle<String> str = obj->ToString();
3620   if (str.IsEmpty()) {
3621     str_ = NULL;
3622     length_ = 0;
3623   } else {
3624     length_ = str->Length();
3625     str_ = i::NewArray<char>(length_ + 1);
3626     str->WriteAscii(str_);
3627   }
3628 }
3629 
3630 
~AsciiValue()3631 String::AsciiValue::~AsciiValue() {
3632   i::DeleteArray(str_);
3633 }
3634 
3635 
Value(v8::Handle<v8::Value> obj)3636 String::Value::Value(v8::Handle<v8::Value> obj) {
3637   EnsureInitialized("v8::String::Value::Value()");
3638   if (obj.IsEmpty()) {
3639     str_ = NULL;
3640     length_ = 0;
3641     return;
3642   }
3643   ENTER_V8;
3644   HandleScope scope;
3645   TryCatch try_catch;
3646   Handle<String> str = obj->ToString();
3647   if (str.IsEmpty()) {
3648     str_ = NULL;
3649     length_ = 0;
3650   } else {
3651     length_ = str->Length();
3652     str_ = i::NewArray<uint16_t>(length_ + 1);
3653     str->Write(str_);
3654   }
3655 }
3656 
3657 
~Value()3658 String::Value::~Value() {
3659   i::DeleteArray(str_);
3660 }
3661 
RangeError(v8::Handle<v8::String> raw_message)3662 Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
3663   LOG_API("RangeError");
3664   ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
3665   ENTER_V8;
3666   i::Object* error;
3667   {
3668     HandleScope scope;
3669     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3670     i::Handle<i::Object> result = i::Factory::NewRangeError(message);
3671     error = *result;
3672   }
3673   i::Handle<i::Object> result(error);
3674   return Utils::ToLocal(result);
3675 }
3676 
ReferenceError(v8::Handle<v8::String> raw_message)3677 Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
3678   LOG_API("ReferenceError");
3679   ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
3680   ENTER_V8;
3681   i::Object* error;
3682   {
3683     HandleScope scope;
3684     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3685     i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
3686     error = *result;
3687   }
3688   i::Handle<i::Object> result(error);
3689   return Utils::ToLocal(result);
3690 }
3691 
SyntaxError(v8::Handle<v8::String> raw_message)3692 Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
3693   LOG_API("SyntaxError");
3694   ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
3695   ENTER_V8;
3696   i::Object* error;
3697   {
3698     HandleScope scope;
3699     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3700     i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
3701     error = *result;
3702   }
3703   i::Handle<i::Object> result(error);
3704   return Utils::ToLocal(result);
3705 }
3706 
TypeError(v8::Handle<v8::String> raw_message)3707 Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
3708   LOG_API("TypeError");
3709   ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
3710   ENTER_V8;
3711   i::Object* error;
3712   {
3713     HandleScope scope;
3714     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3715     i::Handle<i::Object> result = i::Factory::NewTypeError(message);
3716     error = *result;
3717   }
3718   i::Handle<i::Object> result(error);
3719   return Utils::ToLocal(result);
3720 }
3721 
Error(v8::Handle<v8::String> raw_message)3722 Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
3723   LOG_API("Error");
3724   ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
3725   ENTER_V8;
3726   i::Object* error;
3727   {
3728     HandleScope scope;
3729     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3730     i::Handle<i::Object> result = i::Factory::NewError(message);
3731     error = *result;
3732   }
3733   i::Handle<i::Object> result(error);
3734   return Utils::ToLocal(result);
3735 }
3736 
3737 
3738 // --- D e b u g   S u p p o r t ---
3739 
3740 #ifdef ENABLE_DEBUGGER_SUPPORT
SetDebugEventListener(EventCallback that,Handle<Value> data)3741 bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
3742   EnsureInitialized("v8::Debug::SetDebugEventListener()");
3743   ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
3744   ENTER_V8;
3745   HandleScope scope;
3746   i::Handle<i::Object> proxy = i::Factory::undefined_value();
3747   if (that != NULL) {
3748     proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
3749   }
3750   i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
3751   return true;
3752 }
3753 
3754 
SetDebugEventListener(v8::Handle<v8::Object> that,Handle<Value> data)3755 bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
3756                                   Handle<Value> data) {
3757   ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
3758   ENTER_V8;
3759   i::Debugger::SetEventListener(Utils::OpenHandle(*that),
3760                                 Utils::OpenHandle(*data));
3761   return true;
3762 }
3763 
3764 
DebugBreak()3765 void Debug::DebugBreak() {
3766   if (!i::V8::IsRunning()) return;
3767   i::StackGuard::DebugBreak();
3768 }
3769 
3770 
3771 static v8::Debug::MessageHandler message_handler = NULL;
3772 
MessageHandlerWrapper(const v8::Debug::Message & message)3773 static void MessageHandlerWrapper(const v8::Debug::Message& message) {
3774   if (message_handler) {
3775     v8::String::Value json(message.GetJSON());
3776     message_handler(*json, json.length(), message.GetClientData());
3777   }
3778 }
3779 
3780 
SetMessageHandler(v8::Debug::MessageHandler handler,bool message_handler_thread)3781 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
3782                               bool message_handler_thread) {
3783   EnsureInitialized("v8::Debug::SetMessageHandler");
3784   ENTER_V8;
3785   // Message handler thread not supported any more. Parameter temporally left in
3786   // the API for client compatability reasons.
3787   CHECK(!message_handler_thread);
3788 
3789   // TODO(sgjesse) support the old message handler API through a simple wrapper.
3790   message_handler = handler;
3791   if (message_handler != NULL) {
3792     i::Debugger::SetMessageHandler(MessageHandlerWrapper);
3793   } else {
3794     i::Debugger::SetMessageHandler(NULL);
3795   }
3796 }
3797 
3798 
SetMessageHandler2(v8::Debug::MessageHandler2 handler)3799 void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
3800   EnsureInitialized("v8::Debug::SetMessageHandler");
3801   ENTER_V8;
3802   i::Debugger::SetMessageHandler(handler);
3803 }
3804 
3805 
SendCommand(const uint16_t * command,int length,ClientData * client_data)3806 void Debug::SendCommand(const uint16_t* command, int length,
3807                         ClientData* client_data) {
3808   if (!i::V8::IsRunning()) return;
3809   i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
3810                               client_data);
3811 }
3812 
3813 
SetHostDispatchHandler(HostDispatchHandler handler,int period)3814 void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
3815                                    int period) {
3816   EnsureInitialized("v8::Debug::SetHostDispatchHandler");
3817   ENTER_V8;
3818   i::Debugger::SetHostDispatchHandler(handler, period);
3819 }
3820 
3821 
SetDebugMessageDispatchHandler(DebugMessageDispatchHandler handler,bool provide_locker)3822 void Debug::SetDebugMessageDispatchHandler(
3823     DebugMessageDispatchHandler handler, bool provide_locker) {
3824   EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
3825   ENTER_V8;
3826   i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
3827 }
3828 
3829 
Call(v8::Handle<v8::Function> fun,v8::Handle<v8::Value> data)3830 Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
3831                          v8::Handle<v8::Value> data) {
3832   if (!i::V8::IsRunning()) return Local<Value>();
3833   ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
3834   ENTER_V8;
3835   i::Handle<i::Object> result;
3836   EXCEPTION_PREAMBLE();
3837   if (data.IsEmpty()) {
3838     result = i::Debugger::Call(Utils::OpenHandle(*fun),
3839                                i::Factory::undefined_value(),
3840                                &has_pending_exception);
3841   } else {
3842     result = i::Debugger::Call(Utils::OpenHandle(*fun),
3843                                Utils::OpenHandle(*data),
3844                                &has_pending_exception);
3845   }
3846   EXCEPTION_BAILOUT_CHECK(Local<Value>());
3847   return Utils::ToLocal(result);
3848 }
3849 
3850 
GetMirror(v8::Handle<v8::Value> obj)3851 Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
3852   if (!i::V8::IsRunning()) return Local<Value>();
3853   ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
3854   ENTER_V8;
3855   v8::HandleScope scope;
3856   i::Debug::Load();
3857   i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
3858   i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
3859   i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
3860   i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
3861   v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
3862   const int kArgc = 1;
3863   v8::Handle<v8::Value> argv[kArgc] = { obj };
3864   EXCEPTION_PREAMBLE();
3865   v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
3866                                               kArgc,
3867                                               argv);
3868   EXCEPTION_BAILOUT_CHECK(Local<Value>());
3869   return scope.Close(result);
3870 }
3871 
3872 
EnableAgent(const char * name,int port,bool wait_for_connection)3873 bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
3874   return i::Debugger::StartAgent(name, port, wait_for_connection);
3875 }
3876 
ProcessDebugMessages()3877 void Debug::ProcessDebugMessages() {
3878   i::Execution::ProcessDebugMesssages(true);
3879 }
3880 
3881 #endif  // ENABLE_DEBUGGER_SUPPORT
3882 
3883 namespace internal {
3884 
3885 
instance()3886 HandleScopeImplementer* HandleScopeImplementer::instance() {
3887   return &thread_local;
3888 }
3889 
3890 
FreeThreadResources()3891 void HandleScopeImplementer::FreeThreadResources() {
3892   thread_local.Free();
3893 }
3894 
3895 
ArchiveThread(char * storage)3896 char* HandleScopeImplementer::ArchiveThread(char* storage) {
3897   return thread_local.ArchiveThreadHelper(storage);
3898 }
3899 
3900 
ArchiveThreadHelper(char * storage)3901 char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
3902   v8::ImplementationUtilities::HandleScopeData* current =
3903       v8::ImplementationUtilities::CurrentHandleScope();
3904   handle_scope_data_ = *current;
3905   memcpy(storage, this, sizeof(*this));
3906 
3907   ResetAfterArchive();
3908   current->Initialize();
3909 
3910   return storage + ArchiveSpacePerThread();
3911 }
3912 
3913 
ArchiveSpacePerThread()3914 int HandleScopeImplementer::ArchiveSpacePerThread() {
3915   return sizeof(thread_local);
3916 }
3917 
3918 
RestoreThread(char * storage)3919 char* HandleScopeImplementer::RestoreThread(char* storage) {
3920   return thread_local.RestoreThreadHelper(storage);
3921 }
3922 
3923 
RestoreThreadHelper(char * storage)3924 char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
3925   memcpy(this, storage, sizeof(*this));
3926   *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
3927   return storage + ArchiveSpacePerThread();
3928 }
3929 
3930 
IterateThis(ObjectVisitor * v)3931 void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
3932   // Iterate over all handles in the blocks except for the last.
3933   for (int i = blocks()->length() - 2; i >= 0; --i) {
3934     Object** block = blocks()->at(i);
3935     v->VisitPointers(block, &block[kHandleBlockSize]);
3936   }
3937 
3938   // Iterate over live handles in the last block (if any).
3939   if (!blocks()->is_empty()) {
3940     v->VisitPointers(blocks()->last(), handle_scope_data_.next);
3941   }
3942 
3943   if (!saved_contexts_.is_empty()) {
3944     Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
3945     v->VisitPointers(start, start + saved_contexts_.length());
3946   }
3947 }
3948 
3949 
Iterate(ObjectVisitor * v)3950 void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
3951   v8::ImplementationUtilities::HandleScopeData* current =
3952       v8::ImplementationUtilities::CurrentHandleScope();
3953   thread_local.handle_scope_data_ = *current;
3954   thread_local.IterateThis(v);
3955 }
3956 
3957 
Iterate(ObjectVisitor * v,char * storage)3958 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
3959   HandleScopeImplementer* thread_local =
3960       reinterpret_cast<HandleScopeImplementer*>(storage);
3961   thread_local->IterateThis(v);
3962   return storage + ArchiveSpacePerThread();
3963 }
3964 
3965 } }  // namespace v8::internal
3966