blob: 4fdc95f5ee8a7b27bf01da11f72a6e3a1cd23136 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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"
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010037#include "heap-profiler.h"
Steve Block6ded16b2010-05-10 14:33:55 +010038#include "messages.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000039#include "platform.h"
Steve Block6ded16b2010-05-10 14:33:55 +010040#include "profile-generator-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000041#include "serialize.h"
42#include "snapshot.h"
Steve Block6ded16b2010-05-10 14:33:55 +010043#include "top.h"
Steve Blockd0582a62009-12-15 09:54:21 +000044#include "utils.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000045#include "v8threads.h"
46#include "version.h"
47
Steve Block6ded16b2010-05-10 14:33:55 +010048#include "../include/v8-profiler.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000049
50#define LOG_API(expr) LOG(ApiEntryCall(expr))
51
Leon Clarkef7060e22010-06-03 12:02:55 +010052#ifdef ENABLE_VMSTATE_TRACKING
Steve Blocka7e24c12009-10-30 11:49:00 +000053#define ENTER_V8 i::VMState __state__(i::OTHER)
54#define LEAVE_V8 i::VMState __state__(i::EXTERNAL)
55#else
56#define ENTER_V8 ((void) 0)
57#define LEAVE_V8 ((void) 0)
58#endif
59
60namespace v8 {
61
Leon Clarkef7060e22010-06-03 12:02:55 +010062#define ON_BAILOUT(location, code) \
63 if (IsDeadCheck(location) || v8::V8::IsExecutionTerminating()) { \
64 code; \
65 UNREACHABLE(); \
Steve Blocka7e24c12009-10-30 11:49:00 +000066 }
67
68
69#define EXCEPTION_PREAMBLE() \
70 thread_local.IncrementCallDepth(); \
71 ASSERT(!i::Top::external_caught_exception()); \
72 bool has_pending_exception = false
73
74
75#define EXCEPTION_BAILOUT_CHECK(value) \
76 do { \
77 thread_local.DecrementCallDepth(); \
78 if (has_pending_exception) { \
79 if (thread_local.CallDepthIsZero() && i::Top::is_out_of_memory()) { \
80 if (!thread_local.ignore_out_of_memory()) \
81 i::V8::FatalProcessOutOfMemory(NULL); \
82 } \
83 bool call_depth_is_zero = thread_local.CallDepthIsZero(); \
84 i::Top::OptionalRescheduleException(call_depth_is_zero); \
85 return value; \
86 } \
87 } while (false)
88
89
90#define API_ENTRY_CHECK(msg) \
91 do { \
92 if (v8::Locker::IsActive()) { \
93 ApiCheck(i::ThreadManager::IsLockedByCurrentThread(), \
94 msg, \
95 "Entering the V8 API without proper locking in place"); \
96 } \
97 } while (false)
98
99// --- 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 ---
100
101
102static i::HandleScopeImplementer thread_local;
103
104
105// --- E x c e p t i o n B e h a v i o r ---
106
107
108static FatalErrorCallback exception_behavior = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000109
110static void DefaultFatalErrorHandler(const char* location,
111 const char* message) {
112 ENTER_V8;
113 API_Fatal(location, message);
114}
115
116
117
118static 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.
Ben Murdochbb769b22010-08-11 14:56:33 +0100129void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
Steve Blockd0582a62009-12-15 09:54:21 +0000130 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;
Ben Murdochbb769b22010-08-11 14:56:33 +0100169 int memory_allocator_size;
170 heap_stats.memory_allocator_size = &memory_allocator_size;
171 int memory_allocator_capacity;
172 heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
173 int objects_per_type[LAST_TYPE + 1] = {0};
174 heap_stats.objects_per_type = objects_per_type;
175 int size_per_type[LAST_TYPE + 1] = {0};
176 heap_stats.size_per_type = size_per_type;
Steve Blockd0582a62009-12-15 09:54:21 +0000177 int end_marker;
178 heap_stats.end_marker = &end_marker;
Ben Murdochbb769b22010-08-11 14:56:33 +0100179 i::Heap::RecordStats(&heap_stats, take_snapshot);
Steve Blocka7e24c12009-10-30 11:49:00 +0000180 i::V8::SetFatalError();
181 FatalErrorCallback callback = GetFatalErrorHandler();
182 {
183 LEAVE_V8;
184 callback(location, "Allocation failed - process out of memory");
185 }
186 // If the callback returns, we stop execution.
187 UNREACHABLE();
188}
189
190
191void V8::SetFatalErrorHandler(FatalErrorCallback that) {
192 exception_behavior = that;
193}
194
195
196bool Utils::ReportApiFailure(const char* location, const char* message) {
197 FatalErrorCallback callback = GetFatalErrorHandler();
198 callback(location, message);
199 i::V8::SetFatalError();
200 return false;
201}
202
203
204bool V8::IsDead() {
205 return i::V8::IsDead();
206}
207
208
209static inline bool ApiCheck(bool condition,
210 const char* location,
211 const char* message) {
212 return condition ? true : Utils::ReportApiFailure(location, message);
213}
214
215
216static bool ReportV8Dead(const char* location) {
217 FatalErrorCallback callback = GetFatalErrorHandler();
218 callback(location, "V8 is no longer usable");
219 return true;
220}
221
222
223static bool ReportEmptyHandle(const char* location) {
224 FatalErrorCallback callback = GetFatalErrorHandler();
225 callback(location, "Reading from empty handle");
226 return true;
227}
228
229
230/**
231 * IsDeadCheck checks that the vm is usable. If, for instance, the vm has been
232 * out of memory at some point this check will fail. It should be called on
233 * entry to all methods that touch anything in the heap, except destructors
234 * which you sometimes can't avoid calling after the vm has crashed. Functions
235 * that call EnsureInitialized or ON_BAILOUT don't have to also call
236 * IsDeadCheck. ON_BAILOUT has the advantage over EnsureInitialized that you
237 * can arrange to return if the VM is dead. This is needed to ensure that no VM
238 * heap allocations are attempted on a dead VM. EnsureInitialized has the
239 * advantage over ON_BAILOUT that it actually initializes the VM if this has not
240 * yet been done.
241 */
242static inline bool IsDeadCheck(const char* location) {
243 return !i::V8::IsRunning()
244 && i::V8::IsDead() ? ReportV8Dead(location) : false;
245}
246
247
248static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
249 return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
250}
251
252
253static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
254 return (obj == 0) ? ReportEmptyHandle(location) : false;
255}
256
257// --- S t a t i c s ---
258
259
260static i::StringInputBuffer write_input_buffer;
261
262
263static inline bool EnsureInitialized(const char* location) {
264 if (i::V8::IsRunning()) {
265 return true;
266 }
267 if (IsDeadCheck(location)) {
268 return false;
269 }
270 return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
271}
272
273
274ImplementationUtilities::HandleScopeData*
275 ImplementationUtilities::CurrentHandleScope() {
276 return &i::HandleScope::current_;
277}
278
279
280#ifdef DEBUG
281void ImplementationUtilities::ZapHandleRange(i::Object** begin,
282 i::Object** end) {
283 i::HandleScope::ZapRange(begin, end);
284}
285#endif
286
287
288v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
289 if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
290 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
291}
292
293
294v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
295 if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
296 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
297}
298
299
300v8::Handle<v8::Boolean> ImplementationUtilities::True() {
301 if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
302 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
303}
304
305
306v8::Handle<v8::Boolean> ImplementationUtilities::False() {
307 if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
308 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
309}
310
311
312void V8::SetFlagsFromString(const char* str, int length) {
313 i::FlagList::SetFlagsFromString(str, length);
314}
315
316
317void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
318 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
319}
320
321
322v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
323 if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
324 ENTER_V8;
325 // If we're passed an empty handle, we throw an undefined exception
326 // to deal more gracefully with out of memory situations.
327 if (value.IsEmpty()) {
328 i::Top::ScheduleThrow(i::Heap::undefined_value());
329 } else {
330 i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
331 }
332 return v8::Undefined();
333}
334
335
336RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
337
338
339RegisteredExtension::RegisteredExtension(Extension* extension)
340 : extension_(extension), state_(UNVISITED) { }
341
342
343void RegisteredExtension::Register(RegisteredExtension* that) {
344 that->next_ = RegisteredExtension::first_extension_;
345 RegisteredExtension::first_extension_ = that;
346}
347
348
349void RegisterExtension(Extension* that) {
350 RegisteredExtension* extension = new RegisteredExtension(that);
351 RegisteredExtension::Register(extension);
352}
353
354
355Extension::Extension(const char* name,
356 const char* source,
357 int dep_count,
358 const char** deps)
359 : name_(name),
360 source_(source),
361 dep_count_(dep_count),
362 deps_(deps),
363 auto_enable_(false) { }
364
365
366v8::Handle<Primitive> Undefined() {
367 LOG_API("Undefined");
368 return ImplementationUtilities::Undefined();
369}
370
371
372v8::Handle<Primitive> Null() {
373 LOG_API("Null");
374 return ImplementationUtilities::Null();
375}
376
377
378v8::Handle<Boolean> True() {
379 LOG_API("True");
380 return ImplementationUtilities::True();
381}
382
383
384v8::Handle<Boolean> False() {
385 LOG_API("False");
386 return ImplementationUtilities::False();
387}
388
389
390ResourceConstraints::ResourceConstraints()
391 : max_young_space_size_(0),
392 max_old_space_size_(0),
393 stack_limit_(NULL) { }
394
395
396bool SetResourceConstraints(ResourceConstraints* constraints) {
Steve Block3ce2e202009-11-05 08:53:23 +0000397 int young_space_size = constraints->max_young_space_size();
Steve Blocka7e24c12009-10-30 11:49:00 +0000398 int old_gen_size = constraints->max_old_space_size();
Steve Block3ce2e202009-11-05 08:53:23 +0000399 if (young_space_size != 0 || old_gen_size != 0) {
400 bool result = i::Heap::ConfigureHeap(young_space_size / 2, old_gen_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000401 if (!result) return false;
402 }
403 if (constraints->stack_limit() != NULL) {
404 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
405 i::StackGuard::SetStackLimit(limit);
406 }
407 return true;
408}
409
410
411i::Object** V8::GlobalizeReference(i::Object** obj) {
412 if (IsDeadCheck("V8::Persistent::New")) return NULL;
413 LOG_API("Persistent::New");
414 i::Handle<i::Object> result =
415 i::GlobalHandles::Create(*obj);
416 return result.location();
417}
418
419
420void V8::MakeWeak(i::Object** object, void* parameters,
421 WeakReferenceCallback callback) {
422 LOG_API("MakeWeak");
423 i::GlobalHandles::MakeWeak(object, parameters, callback);
424}
425
426
427void V8::ClearWeak(i::Object** obj) {
428 LOG_API("ClearWeak");
429 i::GlobalHandles::ClearWeakness(obj);
430}
431
432
433bool V8::IsGlobalNearDeath(i::Object** obj) {
434 LOG_API("IsGlobalNearDeath");
435 if (!i::V8::IsRunning()) return false;
436 return i::GlobalHandles::IsNearDeath(obj);
437}
438
439
440bool V8::IsGlobalWeak(i::Object** obj) {
441 LOG_API("IsGlobalWeak");
442 if (!i::V8::IsRunning()) return false;
443 return i::GlobalHandles::IsWeak(obj);
444}
445
446
447void V8::DisposeGlobal(i::Object** obj) {
448 LOG_API("DisposeGlobal");
449 if (!i::V8::IsRunning()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000450 i::GlobalHandles::Destroy(obj);
451}
452
453// --- H a n d l e s ---
454
455
456HandleScope::HandleScope() : is_closed_(false) {
457 API_ENTRY_CHECK("HandleScope::HandleScope");
458 i::HandleScope::Enter(&previous_);
459}
460
461
462HandleScope::~HandleScope() {
463 if (!is_closed_) {
464 i::HandleScope::Leave(&previous_);
465 }
466}
467
468
469int HandleScope::NumberOfHandles() {
470 return i::HandleScope::NumberOfHandles();
471}
472
473
474i::Object** v8::HandleScope::CreateHandle(i::Object* value) {
475 return i::HandleScope::CreateHandle(value);
476}
477
478
479void Context::Enter() {
480 if (IsDeadCheck("v8::Context::Enter()")) return;
481 ENTER_V8;
482 i::Handle<i::Context> env = Utils::OpenHandle(this);
483 thread_local.EnterContext(env);
484
485 thread_local.SaveContext(i::Top::context());
486 i::Top::set_context(*env);
487}
488
489
490void Context::Exit() {
491 if (!i::V8::IsRunning()) return;
492 if (!ApiCheck(thread_local.LeaveLastContext(),
493 "v8::Context::Exit()",
494 "Cannot exit non-entered context")) {
495 return;
496 }
497
498 // Content of 'last_context' could be NULL.
499 i::Context* last_context = thread_local.RestoreContext();
500 i::Top::set_context(last_context);
501}
502
503
Steve Blockd0582a62009-12-15 09:54:21 +0000504void Context::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000505 if (IsDeadCheck("v8::Context::SetData()")) return;
506 ENTER_V8;
507 {
508 HandleScope scope;
509 i::Handle<i::Context> env = Utils::OpenHandle(this);
510 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
511 ASSERT(env->IsGlobalContext());
512 if (env->IsGlobalContext()) {
513 env->set_data(*raw_data);
514 }
515 }
516}
517
518
519v8::Local<v8::Value> Context::GetData() {
520 if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
521 ENTER_V8;
522 i::Object* raw_result = NULL;
523 {
524 HandleScope scope;
525 i::Handle<i::Context> env = Utils::OpenHandle(this);
526 ASSERT(env->IsGlobalContext());
527 if (env->IsGlobalContext()) {
528 raw_result = env->data();
529 } else {
530 return Local<Value>();
531 }
532 }
533 i::Handle<i::Object> result(raw_result);
534 return Utils::ToLocal(result);
535}
536
537
538i::Object** v8::HandleScope::RawClose(i::Object** value) {
539 if (!ApiCheck(!is_closed_,
540 "v8::HandleScope::Close()",
541 "Local scope has already been closed")) {
542 return 0;
543 }
544 LOG_API("CloseHandleScope");
545
546 // Read the result before popping the handle block.
Steve Block6ded16b2010-05-10 14:33:55 +0100547 i::Object* result = NULL;
548 if (value != NULL) {
549 result = *value;
550 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000551 is_closed_ = true;
552 i::HandleScope::Leave(&previous_);
553
Steve Block6ded16b2010-05-10 14:33:55 +0100554 if (value == NULL) {
555 return NULL;
556 }
557
Steve Blocka7e24c12009-10-30 11:49:00 +0000558 // Allocate a new handle on the previous handle block.
559 i::Handle<i::Object> handle(result);
560 return handle.location();
561}
562
563
564// --- N e a n d e r ---
565
566
567// A constructor cannot easily return an error value, therefore it is necessary
568// to check for a dead VM with ON_BAILOUT before constructing any Neander
569// objects. To remind you about this there is no HandleScope in the
570// NeanderObject constructor. When you add one to the site calling the
571// constructor you should check that you ensured the VM was not dead first.
572NeanderObject::NeanderObject(int size) {
573 EnsureInitialized("v8::Nowhere");
574 ENTER_V8;
575 value_ = i::Factory::NewNeanderObject();
576 i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
577 value_->set_elements(*elements);
578}
579
580
581int NeanderObject::size() {
582 return i::FixedArray::cast(value_->elements())->length();
583}
584
585
586NeanderArray::NeanderArray() : obj_(2) {
587 obj_.set(0, i::Smi::FromInt(0));
588}
589
590
591int NeanderArray::length() {
592 return i::Smi::cast(obj_.get(0))->value();
593}
594
595
596i::Object* NeanderArray::get(int offset) {
597 ASSERT(0 <= offset);
598 ASSERT(offset < length());
599 return obj_.get(offset + 1);
600}
601
602
603// This method cannot easily return an error value, therefore it is necessary
604// to check for a dead VM with ON_BAILOUT before calling it. To remind you
605// about this there is no HandleScope in this method. When you add one to the
606// site calling this method you should check that you ensured the VM was not
607// dead first.
608void NeanderArray::add(i::Handle<i::Object> value) {
609 int length = this->length();
610 int size = obj_.size();
611 if (length == size - 1) {
612 i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
613 for (int i = 0; i < length; i++)
614 new_elms->set(i + 1, get(i));
615 obj_.value()->set_elements(*new_elms);
616 }
617 obj_.set(length + 1, *value);
618 obj_.set(0, i::Smi::FromInt(length + 1));
619}
620
621
622void NeanderArray::set(int index, i::Object* value) {
623 if (index < 0 || index >= this->length()) return;
624 obj_.set(index + 1, value);
625}
626
627
628// --- T e m p l a t e ---
629
630
631static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
632 that->set_tag(i::Smi::FromInt(type));
633}
634
635
636void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
637 v8::PropertyAttribute attribute) {
638 if (IsDeadCheck("v8::Template::SetProperty()")) return;
639 ENTER_V8;
640 HandleScope scope;
641 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
642 if (list->IsUndefined()) {
643 list = NeanderArray().value();
644 Utils::OpenHandle(this)->set_property_list(*list);
645 }
646 NeanderArray array(list);
647 array.add(Utils::OpenHandle(*name));
648 array.add(Utils::OpenHandle(*value));
649 array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
650}
651
652
653// --- F u n c t i o n T e m p l a t e ---
654static void InitializeFunctionTemplate(
655 i::Handle<i::FunctionTemplateInfo> info) {
656 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
657 info->set_flag(0);
658}
659
660
661Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
662 if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
663 return Local<ObjectTemplate>();
664 }
665 ENTER_V8;
666 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
667 if (result->IsUndefined()) {
668 result = Utils::OpenHandle(*ObjectTemplate::New());
669 Utils::OpenHandle(this)->set_prototype_template(*result);
670 }
671 return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
672}
673
674
675void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
676 if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
677 ENTER_V8;
678 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
679}
680
681
682// To distinguish the function templates, so that we can find them in the
683// function cache of the global context.
684static int next_serial_number = 0;
685
686
687Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
688 v8::Handle<Value> data, v8::Handle<Signature> signature) {
689 EnsureInitialized("v8::FunctionTemplate::New()");
690 LOG_API("FunctionTemplate::New");
691 ENTER_V8;
692 i::Handle<i::Struct> struct_obj =
693 i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
694 i::Handle<i::FunctionTemplateInfo> obj =
695 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
696 InitializeFunctionTemplate(obj);
697 obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
698 if (callback != 0) {
699 if (data.IsEmpty()) data = v8::Undefined();
700 Utils::ToLocal(obj)->SetCallHandler(callback, data);
701 }
702 obj->set_undetectable(false);
703 obj->set_needs_access_check(false);
704
705 if (!signature.IsEmpty())
706 obj->set_signature(*Utils::OpenHandle(*signature));
707 return Utils::ToLocal(obj);
708}
709
710
711Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
712 int argc, Handle<FunctionTemplate> argv[]) {
713 EnsureInitialized("v8::Signature::New()");
714 LOG_API("Signature::New");
715 ENTER_V8;
716 i::Handle<i::Struct> struct_obj =
717 i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
718 i::Handle<i::SignatureInfo> obj =
719 i::Handle<i::SignatureInfo>::cast(struct_obj);
720 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
721 if (argc > 0) {
722 i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
723 for (int i = 0; i < argc; i++) {
724 if (!argv[i].IsEmpty())
725 args->set(i, *Utils::OpenHandle(*argv[i]));
726 }
727 obj->set_args(*args);
728 }
729 return Utils::ToLocal(obj);
730}
731
732
733Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
734 Handle<FunctionTemplate> types[1] = { type };
735 return TypeSwitch::New(1, types);
736}
737
738
739Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
740 EnsureInitialized("v8::TypeSwitch::New()");
741 LOG_API("TypeSwitch::New");
742 ENTER_V8;
743 i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
744 for (int i = 0; i < argc; i++)
745 vector->set(i, *Utils::OpenHandle(*types[i]));
746 i::Handle<i::Struct> struct_obj =
747 i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
748 i::Handle<i::TypeSwitchInfo> obj =
749 i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
750 obj->set_types(*vector);
751 return Utils::ToLocal(obj);
752}
753
754
755int TypeSwitch::match(v8::Handle<Value> value) {
756 LOG_API("TypeSwitch::match");
757 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
758 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
759 i::FixedArray* types = i::FixedArray::cast(info->types());
760 for (int i = 0; i < types->length(); i++) {
761 if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
762 return i + 1;
763 }
764 return 0;
765}
766
767
768void FunctionTemplate::SetCallHandler(InvocationCallback callback,
769 v8::Handle<Value> data) {
770 if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
771 ENTER_V8;
772 HandleScope scope;
773 i::Handle<i::Struct> struct_obj =
774 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
775 i::Handle<i::CallHandlerInfo> obj =
776 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
777 obj->set_callback(*FromCData(callback));
778 if (data.IsEmpty()) data = v8::Undefined();
779 obj->set_data(*Utils::OpenHandle(*data));
780 Utils::OpenHandle(this)->set_call_code(*obj);
781}
782
783
Leon Clarkef7060e22010-06-03 12:02:55 +0100784static i::Handle<i::AccessorInfo> MakeAccessorInfo(
785 v8::Handle<String> name,
786 AccessorGetter getter,
787 AccessorSetter setter,
788 v8::Handle<Value> data,
789 v8::AccessControl settings,
790 v8::PropertyAttribute attributes) {
791 i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
792 ASSERT(getter != NULL);
793 obj->set_getter(*FromCData(getter));
794 obj->set_setter(*FromCData(setter));
795 if (data.IsEmpty()) data = v8::Undefined();
796 obj->set_data(*Utils::OpenHandle(*data));
797 obj->set_name(*Utils::OpenHandle(*name));
798 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
799 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
800 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
801 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
802 return obj;
803}
804
805
Steve Blocka7e24c12009-10-30 11:49:00 +0000806void FunctionTemplate::AddInstancePropertyAccessor(
807 v8::Handle<String> name,
808 AccessorGetter getter,
809 AccessorSetter setter,
810 v8::Handle<Value> data,
811 v8::AccessControl settings,
812 v8::PropertyAttribute attributes) {
813 if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
814 return;
815 }
816 ENTER_V8;
817 HandleScope scope;
Steve Blocka7e24c12009-10-30 11:49:00 +0000818
Leon Clarkef7060e22010-06-03 12:02:55 +0100819 i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name,
820 getter, setter, data,
821 settings, attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000822 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
823 if (list->IsUndefined()) {
824 list = NeanderArray().value();
825 Utils::OpenHandle(this)->set_property_accessors(*list);
826 }
827 NeanderArray array(list);
828 array.add(obj);
829}
830
831
832Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
833 if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
834 || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
835 return Local<ObjectTemplate>();
836 ENTER_V8;
837 if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
838 Local<ObjectTemplate> templ =
839 ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
840 Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
841 }
842 i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
843 Utils::OpenHandle(this)->instance_template()));
844 return Utils::ToLocal(result);
845}
846
847
848void FunctionTemplate::SetClassName(Handle<String> name) {
849 if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
850 ENTER_V8;
851 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
852}
853
854
855void FunctionTemplate::SetHiddenPrototype(bool value) {
856 if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
857 ENTER_V8;
858 Utils::OpenHandle(this)->set_hidden_prototype(value);
859}
860
861
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100862void FunctionTemplate::SetNamedInstancePropertyHandler(
Steve Blocka7e24c12009-10-30 11:49:00 +0000863 NamedPropertyGetter getter,
864 NamedPropertySetter setter,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100865 NamedPropertyQuery query,
Steve Blocka7e24c12009-10-30 11:49:00 +0000866 NamedPropertyDeleter remover,
867 NamedPropertyEnumerator enumerator,
868 Handle<Value> data) {
869 if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
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_named_property_handler(*obj);
886}
887
888
889void FunctionTemplate::SetIndexedInstancePropertyHandler(
890 IndexedPropertyGetter getter,
891 IndexedPropertySetter setter,
892 IndexedPropertyQuery query,
893 IndexedPropertyDeleter remover,
894 IndexedPropertyEnumerator enumerator,
895 Handle<Value> data) {
896 if (IsDeadCheck(
897 "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
898 return;
899 }
900 ENTER_V8;
901 HandleScope scope;
902 i::Handle<i::Struct> struct_obj =
903 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
904 i::Handle<i::InterceptorInfo> obj =
905 i::Handle<i::InterceptorInfo>::cast(struct_obj);
906 if (getter != 0) obj->set_getter(*FromCData(getter));
907 if (setter != 0) obj->set_setter(*FromCData(setter));
908 if (query != 0) obj->set_query(*FromCData(query));
909 if (remover != 0) obj->set_deleter(*FromCData(remover));
910 if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
911 if (data.IsEmpty()) data = v8::Undefined();
912 obj->set_data(*Utils::OpenHandle(*data));
913 Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
914}
915
916
917void FunctionTemplate::SetInstanceCallAsFunctionHandler(
918 InvocationCallback callback,
919 Handle<Value> data) {
920 if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
921 return;
922 }
923 ENTER_V8;
924 HandleScope scope;
925 i::Handle<i::Struct> struct_obj =
926 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
927 i::Handle<i::CallHandlerInfo> obj =
928 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
929 obj->set_callback(*FromCData(callback));
930 if (data.IsEmpty()) data = v8::Undefined();
931 obj->set_data(*Utils::OpenHandle(*data));
932 Utils::OpenHandle(this)->set_instance_call_handler(*obj);
933}
934
935
936// --- O b j e c t T e m p l a t e ---
937
938
939Local<ObjectTemplate> ObjectTemplate::New() {
940 return New(Local<FunctionTemplate>());
941}
942
943
944Local<ObjectTemplate> ObjectTemplate::New(
945 v8::Handle<FunctionTemplate> constructor) {
946 if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
947 EnsureInitialized("v8::ObjectTemplate::New()");
948 LOG_API("ObjectTemplate::New");
949 ENTER_V8;
950 i::Handle<i::Struct> struct_obj =
951 i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
952 i::Handle<i::ObjectTemplateInfo> obj =
953 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
954 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
955 if (!constructor.IsEmpty())
956 obj->set_constructor(*Utils::OpenHandle(*constructor));
957 obj->set_internal_field_count(i::Smi::FromInt(0));
958 return Utils::ToLocal(obj);
959}
960
961
962// Ensure that the object template has a constructor. If no
963// constructor is available we create one.
964static void EnsureConstructor(ObjectTemplate* object_template) {
965 if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
966 Local<FunctionTemplate> templ = FunctionTemplate::New();
967 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
968 constructor->set_instance_template(*Utils::OpenHandle(object_template));
969 Utils::OpenHandle(object_template)->set_constructor(*constructor);
970 }
971}
972
973
974void ObjectTemplate::SetAccessor(v8::Handle<String> name,
975 AccessorGetter getter,
976 AccessorSetter setter,
977 v8::Handle<Value> data,
978 AccessControl settings,
979 PropertyAttribute attribute) {
980 if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
981 ENTER_V8;
982 HandleScope scope;
983 EnsureConstructor(this);
984 i::FunctionTemplateInfo* constructor =
985 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
986 i::Handle<i::FunctionTemplateInfo> cons(constructor);
987 Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
988 getter,
989 setter,
990 data,
991 settings,
992 attribute);
993}
994
995
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100996void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
997 NamedPropertySetter setter,
998 NamedPropertyQuery query,
999 NamedPropertyDeleter remover,
1000 NamedPropertyEnumerator enumerator,
1001 Handle<Value> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001002 if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
1003 ENTER_V8;
1004 HandleScope scope;
1005 EnsureConstructor(this);
1006 i::FunctionTemplateInfo* constructor =
1007 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1008 i::Handle<i::FunctionTemplateInfo> cons(constructor);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001009 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
1010 setter,
1011 query,
1012 remover,
1013 enumerator,
1014 data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001015}
1016
1017
1018void ObjectTemplate::MarkAsUndetectable() {
1019 if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
1020 ENTER_V8;
1021 HandleScope scope;
1022 EnsureConstructor(this);
1023 i::FunctionTemplateInfo* constructor =
1024 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1025 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1026 cons->set_undetectable(true);
1027}
1028
1029
1030void ObjectTemplate::SetAccessCheckCallbacks(
1031 NamedSecurityCallback named_callback,
1032 IndexedSecurityCallback indexed_callback,
1033 Handle<Value> data,
1034 bool turned_on_by_default) {
1035 if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
1036 ENTER_V8;
1037 HandleScope scope;
1038 EnsureConstructor(this);
1039
1040 i::Handle<i::Struct> struct_info =
1041 i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1042 i::Handle<i::AccessCheckInfo> info =
1043 i::Handle<i::AccessCheckInfo>::cast(struct_info);
1044 info->set_named_callback(*FromCData(named_callback));
1045 info->set_indexed_callback(*FromCData(indexed_callback));
1046 if (data.IsEmpty()) data = v8::Undefined();
1047 info->set_data(*Utils::OpenHandle(*data));
1048
1049 i::FunctionTemplateInfo* constructor =
1050 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1051 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1052 cons->set_access_check_info(*info);
1053 cons->set_needs_access_check(turned_on_by_default);
1054}
1055
1056
1057void ObjectTemplate::SetIndexedPropertyHandler(
1058 IndexedPropertyGetter getter,
1059 IndexedPropertySetter setter,
1060 IndexedPropertyQuery query,
1061 IndexedPropertyDeleter remover,
1062 IndexedPropertyEnumerator enumerator,
1063 Handle<Value> data) {
1064 if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
1065 ENTER_V8;
1066 HandleScope scope;
1067 EnsureConstructor(this);
1068 i::FunctionTemplateInfo* constructor =
1069 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1070 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1071 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
1072 setter,
1073 query,
1074 remover,
1075 enumerator,
1076 data);
1077}
1078
1079
1080void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1081 Handle<Value> data) {
1082 if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
1083 ENTER_V8;
1084 HandleScope scope;
1085 EnsureConstructor(this);
1086 i::FunctionTemplateInfo* constructor =
1087 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1088 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1089 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1090}
1091
1092
1093int ObjectTemplate::InternalFieldCount() {
1094 if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
1095 return 0;
1096 }
1097 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1098}
1099
1100
1101void ObjectTemplate::SetInternalFieldCount(int value) {
1102 if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
1103 if (!ApiCheck(i::Smi::IsValid(value),
1104 "v8::ObjectTemplate::SetInternalFieldCount()",
1105 "Invalid internal field count")) {
1106 return;
1107 }
1108 ENTER_V8;
1109 if (value > 0) {
1110 // The internal field count is set by the constructor function's
1111 // construct code, so we ensure that there is a constructor
1112 // function to do the setting.
1113 EnsureConstructor(this);
1114 }
1115 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1116}
1117
1118
1119// --- S c r i p t D a t a ---
1120
1121
1122ScriptData* ScriptData::PreCompile(const char* input, int length) {
1123 unibrow::Utf8InputBuffer<> buf(input, length);
1124 return i::PreParse(i::Handle<i::String>(), &buf, NULL);
1125}
1126
1127
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001128ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
1129 i::Handle<i::String> str = Utils::OpenHandle(*source);
1130 return i::PreParse(str, NULL, NULL);
1131}
1132
1133
Leon Clarkef7060e22010-06-03 12:02:55 +01001134ScriptData* ScriptData::New(const char* data, int length) {
1135 // Return an empty ScriptData if the length is obviously invalid.
1136 if (length % sizeof(unsigned) != 0) {
1137 return new i::ScriptDataImpl(i::Vector<unsigned>());
1138 }
1139
1140 // Copy the data to ensure it is properly aligned.
1141 int deserialized_data_length = length / sizeof(unsigned);
1142 unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
1143 memcpy(deserialized_data, data, length);
1144
1145 return new i::ScriptDataImpl(
1146 i::Vector<unsigned>(deserialized_data, deserialized_data_length));
Steve Blocka7e24c12009-10-30 11:49:00 +00001147}
1148
1149
1150// --- S c r i p t ---
1151
1152
1153Local<Script> Script::New(v8::Handle<String> source,
1154 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001155 v8::ScriptData* pre_data,
1156 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001157 ON_BAILOUT("v8::Script::New()", return Local<Script>());
1158 LOG_API("Script::New");
1159 ENTER_V8;
1160 i::Handle<i::String> str = Utils::OpenHandle(*source);
1161 i::Handle<i::Object> name_obj;
1162 int line_offset = 0;
1163 int column_offset = 0;
1164 if (origin != NULL) {
1165 if (!origin->ResourceName().IsEmpty()) {
1166 name_obj = Utils::OpenHandle(*origin->ResourceName());
1167 }
1168 if (!origin->ResourceLineOffset().IsEmpty()) {
1169 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1170 }
1171 if (!origin->ResourceColumnOffset().IsEmpty()) {
1172 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1173 }
1174 }
1175 EXCEPTION_PREAMBLE();
Andrei Popescu402d9372010-02-26 13:31:12 +00001176 i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001177 // We assert that the pre-data is sane, even though we can actually
1178 // handle it if it turns out not to be in release mode.
Andrei Popescu402d9372010-02-26 13:31:12 +00001179 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
Steve Blocka7e24c12009-10-30 11:49:00 +00001180 // If the pre-data isn't sane we simply ignore it
Andrei Popescu402d9372010-02-26 13:31:12 +00001181 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
1182 pre_data_impl = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001183 }
Steve Block6ded16b2010-05-10 14:33:55 +01001184 i::Handle<i::SharedFunctionInfo> result =
Andrei Popescu31002712010-02-23 13:46:05 +00001185 i::Compiler::Compile(str,
1186 name_obj,
1187 line_offset,
1188 column_offset,
1189 NULL,
Andrei Popescu402d9372010-02-26 13:31:12 +00001190 pre_data_impl,
1191 Utils::OpenHandle(*script_data),
Andrei Popescu31002712010-02-23 13:46:05 +00001192 i::NOT_NATIVES_CODE);
Steve Block6ded16b2010-05-10 14:33:55 +01001193 has_pending_exception = result.is_null();
Steve Blocka7e24c12009-10-30 11:49:00 +00001194 EXCEPTION_BAILOUT_CHECK(Local<Script>());
Steve Block6ded16b2010-05-10 14:33:55 +01001195 return Local<Script>(ToApi<Script>(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00001196}
1197
1198
1199Local<Script> Script::New(v8::Handle<String> source,
1200 v8::Handle<Value> file_name) {
1201 ScriptOrigin origin(file_name);
1202 return New(source, &origin);
1203}
1204
1205
1206Local<Script> Script::Compile(v8::Handle<String> source,
1207 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001208 v8::ScriptData* pre_data,
1209 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001210 ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1211 LOG_API("Script::Compile");
1212 ENTER_V8;
Andrei Popescu402d9372010-02-26 13:31:12 +00001213 Local<Script> generic = New(source, origin, pre_data, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001214 if (generic.IsEmpty())
1215 return generic;
Steve Block6ded16b2010-05-10 14:33:55 +01001216 i::Handle<i::Object> obj = Utils::OpenHandle(*generic);
1217 i::Handle<i::SharedFunctionInfo> function =
1218 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001219 i::Handle<i::JSFunction> result =
Steve Block6ded16b2010-05-10 14:33:55 +01001220 i::Factory::NewFunctionFromSharedFunctionInfo(function,
1221 i::Top::global_context());
Steve Blocka7e24c12009-10-30 11:49:00 +00001222 return Local<Script>(ToApi<Script>(result));
1223}
1224
1225
1226Local<Script> Script::Compile(v8::Handle<String> source,
Andrei Popescu402d9372010-02-26 13:31:12 +00001227 v8::Handle<Value> file_name,
1228 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001229 ScriptOrigin origin(file_name);
Andrei Popescu402d9372010-02-26 13:31:12 +00001230 return Compile(source, &origin, 0, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001231}
1232
1233
1234Local<Value> Script::Run() {
1235 ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1236 LOG_API("Script::Run");
1237 ENTER_V8;
1238 i::Object* raw_result = NULL;
1239 {
1240 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001241 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1242 i::Handle<i::JSFunction> fun;
1243 if (obj->IsSharedFunctionInfo()) {
1244 i::Handle<i::SharedFunctionInfo>
1245 function_info(i::SharedFunctionInfo::cast(*obj));
1246 fun = i::Factory::NewFunctionFromSharedFunctionInfo(
1247 function_info, i::Top::global_context());
1248 } else {
1249 fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001250 }
1251 EXCEPTION_PREAMBLE();
1252 i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
1253 i::Handle<i::Object> result =
1254 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
1255 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1256 raw_result = *result;
1257 }
1258 i::Handle<i::Object> result(raw_result);
1259 return Utils::ToLocal(result);
1260}
1261
1262
Steve Block6ded16b2010-05-10 14:33:55 +01001263static i::Handle<i::SharedFunctionInfo> OpenScript(Script* script) {
1264 i::Handle<i::Object> obj = Utils::OpenHandle(script);
1265 i::Handle<i::SharedFunctionInfo> result;
1266 if (obj->IsSharedFunctionInfo()) {
1267 result =
1268 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
1269 } else {
1270 result =
1271 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared());
1272 }
1273 return result;
1274}
1275
1276
Steve Blocka7e24c12009-10-30 11:49:00 +00001277Local<Value> Script::Id() {
1278 ON_BAILOUT("v8::Script::Id()", return Local<Value>());
1279 LOG_API("Script::Id");
1280 i::Object* raw_id = NULL;
1281 {
1282 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001283 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1284 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001285 i::Handle<i::Object> id(script->id());
1286 raw_id = *id;
1287 }
1288 i::Handle<i::Object> id(raw_id);
1289 return Utils::ToLocal(id);
1290}
1291
1292
Steve Blockd0582a62009-12-15 09:54:21 +00001293void Script::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001294 ON_BAILOUT("v8::Script::SetData()", return);
1295 LOG_API("Script::SetData");
1296 {
1297 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001298 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001299 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
Steve Block6ded16b2010-05-10 14:33:55 +01001300 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001301 script->set_data(*raw_data);
1302 }
1303}
1304
1305
1306// --- E x c e p t i o n s ---
1307
1308
1309v8::TryCatch::TryCatch()
Steve Blockd0582a62009-12-15 09:54:21 +00001310 : next_(i::Top::try_catch_handler_address()),
Steve Blocka7e24c12009-10-30 11:49:00 +00001311 exception_(i::Heap::the_hole_value()),
1312 message_(i::Smi::FromInt(0)),
1313 is_verbose_(false),
1314 can_continue_(true),
1315 capture_message_(true),
Steve Blockd0582a62009-12-15 09:54:21 +00001316 rethrow_(false) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001317 i::Top::RegisterTryCatchHandler(this);
1318}
1319
1320
1321v8::TryCatch::~TryCatch() {
Steve Blockd0582a62009-12-15 09:54:21 +00001322 if (rethrow_) {
1323 v8::HandleScope scope;
1324 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
1325 i::Top::UnregisterTryCatchHandler(this);
1326 v8::ThrowException(exc);
1327 } else {
1328 i::Top::UnregisterTryCatchHandler(this);
1329 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001330}
1331
1332
1333bool v8::TryCatch::HasCaught() const {
1334 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1335}
1336
1337
1338bool v8::TryCatch::CanContinue() const {
1339 return can_continue_;
1340}
1341
1342
Steve Blockd0582a62009-12-15 09:54:21 +00001343v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1344 if (!HasCaught()) return v8::Local<v8::Value>();
1345 rethrow_ = true;
1346 return v8::Undefined();
1347}
1348
1349
Steve Blocka7e24c12009-10-30 11:49:00 +00001350v8::Local<Value> v8::TryCatch::Exception() const {
1351 if (HasCaught()) {
1352 // Check for out of memory exception.
1353 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1354 return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1355 } else {
1356 return v8::Local<Value>();
1357 }
1358}
1359
1360
1361v8::Local<Value> v8::TryCatch::StackTrace() const {
1362 if (HasCaught()) {
1363 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1364 if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1365 v8::HandleScope scope;
1366 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
1367 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
1368 if (!obj->HasProperty(*name))
1369 return v8::Local<Value>();
1370 return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
1371 } else {
1372 return v8::Local<Value>();
1373 }
1374}
1375
1376
1377v8::Local<v8::Message> v8::TryCatch::Message() const {
1378 if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1379 i::Object* message = reinterpret_cast<i::Object*>(message_);
1380 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1381 } else {
1382 return v8::Local<v8::Message>();
1383 }
1384}
1385
1386
1387void v8::TryCatch::Reset() {
1388 exception_ = i::Heap::the_hole_value();
1389 message_ = i::Smi::FromInt(0);
1390}
1391
1392
1393void v8::TryCatch::SetVerbose(bool value) {
1394 is_verbose_ = value;
1395}
1396
1397
1398void v8::TryCatch::SetCaptureMessage(bool value) {
1399 capture_message_ = value;
1400}
1401
1402
1403// --- M e s s a g e ---
1404
1405
1406Local<String> Message::Get() const {
1407 ON_BAILOUT("v8::Message::Get()", return Local<String>());
1408 ENTER_V8;
1409 HandleScope scope;
1410 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1411 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1412 Local<String> result = Utils::ToLocal(raw_result);
1413 return scope.Close(result);
1414}
1415
1416
1417v8::Handle<Value> Message::GetScriptResourceName() const {
1418 if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1419 return Local<String>();
1420 }
1421 ENTER_V8;
1422 HandleScope scope;
1423 i::Handle<i::JSObject> obj =
1424 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1425 // Return this.script.name.
1426 i::Handle<i::JSValue> script =
1427 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1428 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
1429 return scope.Close(Utils::ToLocal(resource_name));
1430}
1431
1432
1433v8::Handle<Value> Message::GetScriptData() const {
1434 if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
1435 return Local<Value>();
1436 }
1437 ENTER_V8;
1438 HandleScope scope;
1439 i::Handle<i::JSObject> obj =
1440 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1441 // Return this.script.data.
1442 i::Handle<i::JSValue> script =
1443 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1444 i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1445 return scope.Close(Utils::ToLocal(data));
1446}
1447
1448
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001449v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
1450 if (IsDeadCheck("v8::Message::GetStackTrace()")) {
1451 return Local<v8::StackTrace>();
1452 }
1453 ENTER_V8;
1454 HandleScope scope;
1455 i::Handle<i::JSObject> obj =
1456 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1457 i::Handle<i::Object> stackFramesObj = GetProperty(obj, "stackFrames");
1458 if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
1459 i::Handle<i::JSArray> stackTrace =
1460 i::Handle<i::JSArray>::cast(stackFramesObj);
1461 return scope.Close(Utils::StackTraceToLocal(stackTrace));
1462}
1463
1464
Steve Blocka7e24c12009-10-30 11:49:00 +00001465static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1466 i::Handle<i::Object> recv,
1467 int argc,
1468 i::Object** argv[],
1469 bool* has_pending_exception) {
1470 i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
1471 i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
1472 i::Handle<i::JSFunction> fun =
1473 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1474 i::Handle<i::Object> value =
1475 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1476 return value;
1477}
1478
1479
1480static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1481 i::Handle<i::Object> data,
1482 bool* has_pending_exception) {
1483 i::Object** argv[1] = { data.location() };
1484 return CallV8HeapFunction(name,
1485 i::Top::builtins(),
1486 1,
1487 argv,
1488 has_pending_exception);
1489}
1490
1491
1492int Message::GetLineNumber() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001493 ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001494 ENTER_V8;
1495 HandleScope scope;
1496 EXCEPTION_PREAMBLE();
1497 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1498 Utils::OpenHandle(this),
1499 &has_pending_exception);
1500 EXCEPTION_BAILOUT_CHECK(0);
1501 return static_cast<int>(result->Number());
1502}
1503
1504
1505int Message::GetStartPosition() const {
1506 if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1507 ENTER_V8;
1508 HandleScope scope;
1509
1510 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1511 return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1512}
1513
1514
1515int Message::GetEndPosition() const {
1516 if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1517 ENTER_V8;
1518 HandleScope scope;
1519 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1520 return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1521}
1522
1523
1524int Message::GetStartColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001525 if (IsDeadCheck("v8::Message::GetStartColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001526 ENTER_V8;
1527 HandleScope scope;
1528 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1529 EXCEPTION_PREAMBLE();
1530 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1531 "GetPositionInLine",
1532 data_obj,
1533 &has_pending_exception);
1534 EXCEPTION_BAILOUT_CHECK(0);
1535 return static_cast<int>(start_col_obj->Number());
1536}
1537
1538
1539int Message::GetEndColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001540 if (IsDeadCheck("v8::Message::GetEndColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001541 ENTER_V8;
1542 HandleScope scope;
1543 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1544 EXCEPTION_PREAMBLE();
1545 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1546 "GetPositionInLine",
1547 data_obj,
1548 &has_pending_exception);
1549 EXCEPTION_BAILOUT_CHECK(0);
1550 int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1551 int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1552 return static_cast<int>(start_col_obj->Number()) + (end - start);
1553}
1554
1555
1556Local<String> Message::GetSourceLine() const {
1557 ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
1558 ENTER_V8;
1559 HandleScope scope;
1560 EXCEPTION_PREAMBLE();
1561 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1562 Utils::OpenHandle(this),
1563 &has_pending_exception);
1564 EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1565 if (result->IsString()) {
1566 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1567 } else {
1568 return Local<String>();
1569 }
1570}
1571
1572
1573void Message::PrintCurrentStackTrace(FILE* out) {
1574 if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1575 ENTER_V8;
1576 i::Top::PrintCurrentStackTrace(out);
1577}
1578
1579
Kristian Monsen25f61362010-05-21 11:50:48 +01001580// --- S t a c k T r a c e ---
1581
1582Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
1583 if (IsDeadCheck("v8::StackTrace::GetFrame()")) return Local<StackFrame>();
1584 ENTER_V8;
1585 HandleScope scope;
1586 i::Handle<i::JSArray> self = Utils::OpenHandle(this);
1587 i::Handle<i::JSObject> obj(i::JSObject::cast(self->GetElement(index)));
1588 return scope.Close(Utils::StackFrameToLocal(obj));
1589}
1590
1591
1592int StackTrace::GetFrameCount() const {
1593 if (IsDeadCheck("v8::StackTrace::GetFrameCount()")) return -1;
1594 ENTER_V8;
1595 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
1596}
1597
1598
1599Local<Array> StackTrace::AsArray() {
1600 if (IsDeadCheck("v8::StackTrace::AsArray()")) Local<Array>();
1601 ENTER_V8;
1602 return Utils::ToLocal(Utils::OpenHandle(this));
1603}
1604
1605
1606Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
1607 StackTraceOptions options) {
1608 if (IsDeadCheck("v8::StackTrace::CurrentStackTrace()")) Local<StackTrace>();
1609 ENTER_V8;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001610 i::Handle<i::JSArray> stackTrace =
1611 i::Top::CaptureCurrentStackTrace(frame_limit, options);
1612 return Utils::StackTraceToLocal(stackTrace);
Kristian Monsen25f61362010-05-21 11:50:48 +01001613}
1614
1615
1616// --- S t a c k F r a m e ---
1617
1618int StackFrame::GetLineNumber() const {
1619 if (IsDeadCheck("v8::StackFrame::GetLineNumber()")) {
1620 return Message::kNoLineNumberInfo;
1621 }
1622 ENTER_V8;
1623 i::HandleScope scope;
1624 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1625 i::Handle<i::Object> line = GetProperty(self, "lineNumber");
1626 if (!line->IsSmi()) {
1627 return Message::kNoLineNumberInfo;
1628 }
1629 return i::Smi::cast(*line)->value();
1630}
1631
1632
1633int StackFrame::GetColumn() const {
1634 if (IsDeadCheck("v8::StackFrame::GetColumn()")) {
1635 return Message::kNoColumnInfo;
1636 }
1637 ENTER_V8;
1638 i::HandleScope scope;
1639 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1640 i::Handle<i::Object> column = GetProperty(self, "column");
1641 if (!column->IsSmi()) {
1642 return Message::kNoColumnInfo;
1643 }
1644 return i::Smi::cast(*column)->value();
1645}
1646
1647
1648Local<String> StackFrame::GetScriptName() const {
1649 if (IsDeadCheck("v8::StackFrame::GetScriptName()")) return Local<String>();
1650 ENTER_V8;
1651 HandleScope scope;
1652 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1653 i::Handle<i::Object> name = GetProperty(self, "scriptName");
1654 if (!name->IsString()) {
1655 return Local<String>();
1656 }
1657 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1658}
1659
1660
1661Local<String> StackFrame::GetFunctionName() const {
1662 if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
1663 ENTER_V8;
1664 HandleScope scope;
1665 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1666 i::Handle<i::Object> name = GetProperty(self, "functionName");
1667 if (!name->IsString()) {
1668 return Local<String>();
1669 }
1670 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1671}
1672
1673
1674bool StackFrame::IsEval() const {
1675 if (IsDeadCheck("v8::StackFrame::IsEval()")) return false;
1676 ENTER_V8;
1677 i::HandleScope scope;
1678 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1679 i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
1680 return is_eval->IsTrue();
1681}
1682
1683
1684bool StackFrame::IsConstructor() const {
1685 if (IsDeadCheck("v8::StackFrame::IsConstructor()")) return false;
1686 ENTER_V8;
1687 i::HandleScope scope;
1688 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1689 i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
1690 return is_constructor->IsTrue();
1691}
1692
1693
Steve Blocka7e24c12009-10-30 11:49:00 +00001694// --- D a t a ---
1695
1696bool Value::IsUndefined() const {
1697 if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1698 return Utils::OpenHandle(this)->IsUndefined();
1699}
1700
1701
1702bool Value::IsNull() const {
1703 if (IsDeadCheck("v8::Value::IsNull()")) return false;
1704 return Utils::OpenHandle(this)->IsNull();
1705}
1706
1707
1708bool Value::IsTrue() const {
1709 if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1710 return Utils::OpenHandle(this)->IsTrue();
1711}
1712
1713
1714bool Value::IsFalse() const {
1715 if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1716 return Utils::OpenHandle(this)->IsFalse();
1717}
1718
1719
1720bool Value::IsFunction() const {
1721 if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1722 return Utils::OpenHandle(this)->IsJSFunction();
1723}
1724
1725
1726bool Value::FullIsString() const {
1727 if (IsDeadCheck("v8::Value::IsString()")) return false;
1728 bool result = Utils::OpenHandle(this)->IsString();
1729 ASSERT_EQ(result, QuickIsString());
1730 return result;
1731}
1732
1733
1734bool Value::IsArray() const {
1735 if (IsDeadCheck("v8::Value::IsArray()")) return false;
1736 return Utils::OpenHandle(this)->IsJSArray();
1737}
1738
1739
1740bool Value::IsObject() const {
1741 if (IsDeadCheck("v8::Value::IsObject()")) return false;
1742 return Utils::OpenHandle(this)->IsJSObject();
1743}
1744
1745
1746bool Value::IsNumber() const {
1747 if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1748 return Utils::OpenHandle(this)->IsNumber();
1749}
1750
1751
1752bool Value::IsBoolean() const {
1753 if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1754 return Utils::OpenHandle(this)->IsBoolean();
1755}
1756
1757
1758bool Value::IsExternal() const {
1759 if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1760 return Utils::OpenHandle(this)->IsProxy();
1761}
1762
1763
1764bool Value::IsInt32() const {
1765 if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1766 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1767 if (obj->IsSmi()) return true;
1768 if (obj->IsNumber()) {
1769 double value = obj->Number();
1770 return i::FastI2D(i::FastD2I(value)) == value;
1771 }
1772 return false;
1773}
1774
1775
Steve Block6ded16b2010-05-10 14:33:55 +01001776bool Value::IsUint32() const {
1777 if (IsDeadCheck("v8::Value::IsUint32()")) return false;
1778 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1779 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
1780 if (obj->IsNumber()) {
1781 double value = obj->Number();
1782 return i::FastUI2D(i::FastD2UI(value)) == value;
1783 }
1784 return false;
1785}
1786
1787
Steve Blocka7e24c12009-10-30 11:49:00 +00001788bool Value::IsDate() const {
1789 if (IsDeadCheck("v8::Value::IsDate()")) return false;
1790 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1791 return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1792}
1793
1794
1795Local<String> Value::ToString() const {
1796 if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1797 LOG_API("ToString");
1798 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1799 i::Handle<i::Object> str;
1800 if (obj->IsString()) {
1801 str = obj;
1802 } else {
1803 ENTER_V8;
1804 EXCEPTION_PREAMBLE();
1805 str = i::Execution::ToString(obj, &has_pending_exception);
1806 EXCEPTION_BAILOUT_CHECK(Local<String>());
1807 }
1808 return Local<String>(ToApi<String>(str));
1809}
1810
1811
1812Local<String> Value::ToDetailString() const {
1813 if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1814 LOG_API("ToDetailString");
1815 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1816 i::Handle<i::Object> str;
1817 if (obj->IsString()) {
1818 str = obj;
1819 } else {
1820 ENTER_V8;
1821 EXCEPTION_PREAMBLE();
1822 str = i::Execution::ToDetailString(obj, &has_pending_exception);
1823 EXCEPTION_BAILOUT_CHECK(Local<String>());
1824 }
1825 return Local<String>(ToApi<String>(str));
1826}
1827
1828
1829Local<v8::Object> Value::ToObject() const {
1830 if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1831 LOG_API("ToObject");
1832 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1833 i::Handle<i::Object> val;
1834 if (obj->IsJSObject()) {
1835 val = obj;
1836 } else {
1837 ENTER_V8;
1838 EXCEPTION_PREAMBLE();
1839 val = i::Execution::ToObject(obj, &has_pending_exception);
1840 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1841 }
1842 return Local<v8::Object>(ToApi<Object>(val));
1843}
1844
1845
1846Local<Boolean> Value::ToBoolean() const {
1847 if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1848 LOG_API("ToBoolean");
1849 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1850 if (obj->IsBoolean()) {
1851 return Local<Boolean>(ToApi<Boolean>(obj));
1852 } else {
1853 ENTER_V8;
1854 i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1855 return Local<Boolean>(ToApi<Boolean>(val));
1856 }
1857}
1858
1859
1860Local<Number> Value::ToNumber() const {
1861 if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1862 LOG_API("ToNumber");
1863 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1864 i::Handle<i::Object> num;
1865 if (obj->IsNumber()) {
1866 num = obj;
1867 } else {
1868 ENTER_V8;
1869 EXCEPTION_PREAMBLE();
1870 num = i::Execution::ToNumber(obj, &has_pending_exception);
1871 EXCEPTION_BAILOUT_CHECK(Local<Number>());
1872 }
1873 return Local<Number>(ToApi<Number>(num));
1874}
1875
1876
1877Local<Integer> Value::ToInteger() const {
1878 if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1879 LOG_API("ToInteger");
1880 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1881 i::Handle<i::Object> num;
1882 if (obj->IsSmi()) {
1883 num = obj;
1884 } else {
1885 ENTER_V8;
1886 EXCEPTION_PREAMBLE();
1887 num = i::Execution::ToInteger(obj, &has_pending_exception);
1888 EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1889 }
1890 return Local<Integer>(ToApi<Integer>(num));
1891}
1892
1893
1894void External::CheckCast(v8::Value* that) {
1895 if (IsDeadCheck("v8::External::Cast()")) return;
1896 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1897 ApiCheck(obj->IsProxy(),
1898 "v8::External::Cast()",
1899 "Could not convert to external");
1900}
1901
1902
1903void v8::Object::CheckCast(Value* that) {
1904 if (IsDeadCheck("v8::Object::Cast()")) return;
1905 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1906 ApiCheck(obj->IsJSObject(),
1907 "v8::Object::Cast()",
1908 "Could not convert to object");
1909}
1910
1911
1912void v8::Function::CheckCast(Value* that) {
1913 if (IsDeadCheck("v8::Function::Cast()")) return;
1914 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1915 ApiCheck(obj->IsJSFunction(),
1916 "v8::Function::Cast()",
1917 "Could not convert to function");
1918}
1919
1920
1921void v8::String::CheckCast(v8::Value* that) {
1922 if (IsDeadCheck("v8::String::Cast()")) return;
1923 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1924 ApiCheck(obj->IsString(),
1925 "v8::String::Cast()",
1926 "Could not convert to string");
1927}
1928
1929
1930void v8::Number::CheckCast(v8::Value* that) {
1931 if (IsDeadCheck("v8::Number::Cast()")) return;
1932 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1933 ApiCheck(obj->IsNumber(),
1934 "v8::Number::Cast()",
1935 "Could not convert to number");
1936}
1937
1938
1939void v8::Integer::CheckCast(v8::Value* that) {
1940 if (IsDeadCheck("v8::Integer::Cast()")) return;
1941 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1942 ApiCheck(obj->IsNumber(),
1943 "v8::Integer::Cast()",
1944 "Could not convert to number");
1945}
1946
1947
1948void v8::Array::CheckCast(Value* that) {
1949 if (IsDeadCheck("v8::Array::Cast()")) return;
1950 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1951 ApiCheck(obj->IsJSArray(),
1952 "v8::Array::Cast()",
1953 "Could not convert to array");
1954}
1955
1956
1957void v8::Date::CheckCast(v8::Value* that) {
1958 if (IsDeadCheck("v8::Date::Cast()")) return;
1959 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1960 ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
1961 "v8::Date::Cast()",
1962 "Could not convert to date");
1963}
1964
1965
1966bool Value::BooleanValue() const {
1967 if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
1968 LOG_API("BooleanValue");
1969 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1970 if (obj->IsBoolean()) {
1971 return obj->IsTrue();
1972 } else {
1973 ENTER_V8;
1974 i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
1975 return value->IsTrue();
1976 }
1977}
1978
1979
1980double Value::NumberValue() const {
1981 if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
1982 LOG_API("NumberValue");
1983 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1984 i::Handle<i::Object> num;
1985 if (obj->IsNumber()) {
1986 num = obj;
1987 } else {
1988 ENTER_V8;
1989 EXCEPTION_PREAMBLE();
1990 num = i::Execution::ToNumber(obj, &has_pending_exception);
1991 EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
1992 }
1993 return num->Number();
1994}
1995
1996
1997int64_t Value::IntegerValue() const {
1998 if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
1999 LOG_API("IntegerValue");
2000 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2001 i::Handle<i::Object> num;
2002 if (obj->IsNumber()) {
2003 num = obj;
2004 } else {
2005 ENTER_V8;
2006 EXCEPTION_PREAMBLE();
2007 num = i::Execution::ToInteger(obj, &has_pending_exception);
2008 EXCEPTION_BAILOUT_CHECK(0);
2009 }
2010 if (num->IsSmi()) {
2011 return i::Smi::cast(*num)->value();
2012 } else {
2013 return static_cast<int64_t>(num->Number());
2014 }
2015}
2016
2017
2018Local<Int32> Value::ToInt32() const {
2019 if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
2020 LOG_API("ToInt32");
2021 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2022 i::Handle<i::Object> num;
2023 if (obj->IsSmi()) {
2024 num = obj;
2025 } else {
2026 ENTER_V8;
2027 EXCEPTION_PREAMBLE();
2028 num = i::Execution::ToInt32(obj, &has_pending_exception);
2029 EXCEPTION_BAILOUT_CHECK(Local<Int32>());
2030 }
2031 return Local<Int32>(ToApi<Int32>(num));
2032}
2033
2034
2035Local<Uint32> Value::ToUint32() const {
2036 if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
2037 LOG_API("ToUInt32");
2038 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2039 i::Handle<i::Object> num;
2040 if (obj->IsSmi()) {
2041 num = obj;
2042 } else {
2043 ENTER_V8;
2044 EXCEPTION_PREAMBLE();
2045 num = i::Execution::ToUint32(obj, &has_pending_exception);
2046 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2047 }
2048 return Local<Uint32>(ToApi<Uint32>(num));
2049}
2050
2051
2052Local<Uint32> Value::ToArrayIndex() const {
2053 if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
2054 LOG_API("ToArrayIndex");
2055 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2056 if (obj->IsSmi()) {
2057 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2058 return Local<Uint32>();
2059 }
2060 ENTER_V8;
2061 EXCEPTION_PREAMBLE();
2062 i::Handle<i::Object> string_obj =
2063 i::Execution::ToString(obj, &has_pending_exception);
2064 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2065 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2066 uint32_t index;
2067 if (str->AsArrayIndex(&index)) {
2068 i::Handle<i::Object> value;
2069 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2070 value = i::Handle<i::Object>(i::Smi::FromInt(index));
2071 } else {
2072 value = i::Factory::NewNumber(index);
2073 }
2074 return Utils::Uint32ToLocal(value);
2075 }
2076 return Local<Uint32>();
2077}
2078
2079
2080int32_t Value::Int32Value() const {
2081 if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
2082 LOG_API("Int32Value");
2083 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2084 if (obj->IsSmi()) {
2085 return i::Smi::cast(*obj)->value();
2086 } else {
2087 LOG_API("Int32Value (slow)");
2088 ENTER_V8;
2089 EXCEPTION_PREAMBLE();
2090 i::Handle<i::Object> num =
2091 i::Execution::ToInt32(obj, &has_pending_exception);
2092 EXCEPTION_BAILOUT_CHECK(0);
2093 if (num->IsSmi()) {
2094 return i::Smi::cast(*num)->value();
2095 } else {
2096 return static_cast<int32_t>(num->Number());
2097 }
2098 }
2099}
2100
2101
2102bool Value::Equals(Handle<Value> that) const {
2103 if (IsDeadCheck("v8::Value::Equals()")
2104 || EmptyCheck("v8::Value::Equals()", this)
2105 || EmptyCheck("v8::Value::Equals()", that)) {
2106 return false;
2107 }
2108 LOG_API("Equals");
2109 ENTER_V8;
2110 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2111 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2112 i::Object** args[1] = { other.location() };
2113 EXCEPTION_PREAMBLE();
2114 i::Handle<i::Object> result =
2115 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
2116 EXCEPTION_BAILOUT_CHECK(false);
2117 return *result == i::Smi::FromInt(i::EQUAL);
2118}
2119
2120
2121bool Value::StrictEquals(Handle<Value> that) const {
2122 if (IsDeadCheck("v8::Value::StrictEquals()")
2123 || EmptyCheck("v8::Value::StrictEquals()", this)
2124 || EmptyCheck("v8::Value::StrictEquals()", that)) {
2125 return false;
2126 }
2127 LOG_API("StrictEquals");
2128 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2129 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2130 // Must check HeapNumber first, since NaN !== NaN.
2131 if (obj->IsHeapNumber()) {
2132 if (!other->IsNumber()) return false;
2133 double x = obj->Number();
2134 double y = other->Number();
2135 // Must check explicitly for NaN:s on Windows, but -0 works fine.
2136 return x == y && !isnan(x) && !isnan(y);
2137 } else if (*obj == *other) { // Also covers Booleans.
2138 return true;
2139 } else if (obj->IsSmi()) {
2140 return other->IsNumber() && obj->Number() == other->Number();
2141 } else if (obj->IsString()) {
2142 return other->IsString() &&
2143 i::String::cast(*obj)->Equals(i::String::cast(*other));
2144 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2145 return other->IsUndefined() || other->IsUndetectableObject();
2146 } else {
2147 return false;
2148 }
2149}
2150
2151
2152uint32_t Value::Uint32Value() const {
2153 if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
2154 LOG_API("Uint32Value");
2155 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2156 if (obj->IsSmi()) {
2157 return i::Smi::cast(*obj)->value();
2158 } else {
2159 ENTER_V8;
2160 EXCEPTION_PREAMBLE();
2161 i::Handle<i::Object> num =
2162 i::Execution::ToUint32(obj, &has_pending_exception);
2163 EXCEPTION_BAILOUT_CHECK(0);
2164 if (num->IsSmi()) {
2165 return i::Smi::cast(*num)->value();
2166 } else {
2167 return static_cast<uint32_t>(num->Number());
2168 }
2169 }
2170}
2171
2172
2173bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
2174 v8::PropertyAttribute attribs) {
2175 ON_BAILOUT("v8::Object::Set()", return false);
2176 ENTER_V8;
2177 HandleScope scope;
2178 i::Handle<i::Object> self = Utils::OpenHandle(this);
2179 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2180 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2181 EXCEPTION_PREAMBLE();
2182 i::Handle<i::Object> obj = i::SetProperty(
2183 self,
2184 key_obj,
2185 value_obj,
2186 static_cast<PropertyAttributes>(attribs));
2187 has_pending_exception = obj.is_null();
2188 EXCEPTION_BAILOUT_CHECK(false);
2189 return true;
2190}
2191
2192
Steve Block6ded16b2010-05-10 14:33:55 +01002193bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
2194 ON_BAILOUT("v8::Object::Set()", return false);
2195 ENTER_V8;
2196 HandleScope scope;
2197 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2198 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2199 EXCEPTION_PREAMBLE();
2200 i::Handle<i::Object> obj = i::SetElement(
2201 self,
2202 index,
2203 value_obj);
2204 has_pending_exception = obj.is_null();
2205 EXCEPTION_BAILOUT_CHECK(false);
2206 return true;
2207}
2208
2209
Steve Blocka7e24c12009-10-30 11:49:00 +00002210bool v8::Object::ForceSet(v8::Handle<Value> key,
2211 v8::Handle<Value> value,
2212 v8::PropertyAttribute attribs) {
2213 ON_BAILOUT("v8::Object::ForceSet()", return false);
2214 ENTER_V8;
2215 HandleScope scope;
2216 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2217 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2218 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2219 EXCEPTION_PREAMBLE();
2220 i::Handle<i::Object> obj = i::ForceSetProperty(
2221 self,
2222 key_obj,
2223 value_obj,
2224 static_cast<PropertyAttributes>(attribs));
2225 has_pending_exception = obj.is_null();
2226 EXCEPTION_BAILOUT_CHECK(false);
2227 return true;
2228}
2229
2230
2231bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2232 ON_BAILOUT("v8::Object::ForceDelete()", return false);
2233 ENTER_V8;
2234 HandleScope scope;
2235 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2236 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2237 EXCEPTION_PREAMBLE();
2238 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2239 has_pending_exception = obj.is_null();
2240 EXCEPTION_BAILOUT_CHECK(false);
2241 return obj->IsTrue();
2242}
2243
2244
2245Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2246 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2247 ENTER_V8;
2248 i::Handle<i::Object> self = Utils::OpenHandle(this);
2249 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2250 EXCEPTION_PREAMBLE();
2251 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2252 has_pending_exception = result.is_null();
2253 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2254 return Utils::ToLocal(result);
2255}
2256
2257
Steve Block6ded16b2010-05-10 14:33:55 +01002258Local<Value> v8::Object::Get(uint32_t index) {
2259 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2260 ENTER_V8;
2261 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2262 EXCEPTION_PREAMBLE();
2263 i::Handle<i::Object> result = i::GetElement(self, index);
2264 has_pending_exception = result.is_null();
2265 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2266 return Utils::ToLocal(result);
2267}
2268
2269
Steve Blocka7e24c12009-10-30 11:49:00 +00002270Local<Value> v8::Object::GetPrototype() {
2271 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
2272 ENTER_V8;
2273 i::Handle<i::Object> self = Utils::OpenHandle(this);
2274 i::Handle<i::Object> result = i::GetPrototype(self);
2275 return Utils::ToLocal(result);
2276}
2277
2278
Andrei Popescu402d9372010-02-26 13:31:12 +00002279bool v8::Object::SetPrototype(Handle<Value> value) {
2280 ON_BAILOUT("v8::Object::SetPrototype()", return false);
2281 ENTER_V8;
2282 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2283 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2284 EXCEPTION_PREAMBLE();
2285 i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2286 has_pending_exception = result.is_null();
2287 EXCEPTION_BAILOUT_CHECK(false);
2288 return true;
2289}
2290
2291
Steve Blocka7e24c12009-10-30 11:49:00 +00002292Local<Object> v8::Object::FindInstanceInPrototypeChain(
2293 v8::Handle<FunctionTemplate> tmpl) {
2294 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
2295 return Local<v8::Object>());
2296 ENTER_V8;
2297 i::JSObject* object = *Utils::OpenHandle(this);
2298 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2299 while (!object->IsInstanceOf(tmpl_info)) {
2300 i::Object* prototype = object->GetPrototype();
2301 if (!prototype->IsJSObject()) return Local<Object>();
2302 object = i::JSObject::cast(prototype);
2303 }
2304 return Utils::ToLocal(i::Handle<i::JSObject>(object));
2305}
2306
2307
2308Local<Array> v8::Object::GetPropertyNames() {
2309 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
2310 ENTER_V8;
2311 v8::HandleScope scope;
2312 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2313 i::Handle<i::FixedArray> value =
2314 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2315 // Because we use caching to speed up enumeration it is important
2316 // to never change the result of the basic enumeration function so
2317 // we clone the result.
2318 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
2319 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
2320 return scope.Close(Utils::ToLocal(result));
2321}
2322
2323
2324Local<String> v8::Object::ObjectProtoToString() {
2325 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2326 ENTER_V8;
2327 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2328
2329 i::Handle<i::Object> name(self->class_name());
2330
2331 // Native implementation of Object.prototype.toString (v8natives.js):
2332 // var c = %ClassOf(this);
2333 // if (c === 'Arguments') c = 'Object';
2334 // return "[object " + c + "]";
2335
2336 if (!name->IsString()) {
2337 return v8::String::New("[object ]");
2338
2339 } else {
2340 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2341 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2342 return v8::String::New("[object Object]");
2343
2344 } else {
2345 const char* prefix = "[object ";
2346 Local<String> str = Utils::ToLocal(class_name);
2347 const char* postfix = "]";
2348
Steve Blockd0582a62009-12-15 09:54:21 +00002349 int prefix_len = i::StrLength(prefix);
2350 int str_len = str->Length();
2351 int postfix_len = i::StrLength(postfix);
Steve Blocka7e24c12009-10-30 11:49:00 +00002352
Steve Blockd0582a62009-12-15 09:54:21 +00002353 int buf_len = prefix_len + str_len + postfix_len;
Kristian Monsen25f61362010-05-21 11:50:48 +01002354 i::ScopedVector<char> buf(buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002355
2356 // Write prefix.
Kristian Monsen25f61362010-05-21 11:50:48 +01002357 char* ptr = buf.start();
Steve Blocka7e24c12009-10-30 11:49:00 +00002358 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2359 ptr += prefix_len;
2360
2361 // Write real content.
2362 str->WriteAscii(ptr, 0, str_len);
2363 ptr += str_len;
2364
2365 // Write postfix.
2366 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2367
2368 // Copy the buffer into a heap-allocated string and return it.
Kristian Monsen25f61362010-05-21 11:50:48 +01002369 Local<String> result = v8::String::New(buf.start(), buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002370 return result;
2371 }
2372 }
2373}
2374
2375
2376bool v8::Object::Delete(v8::Handle<String> key) {
2377 ON_BAILOUT("v8::Object::Delete()", return false);
2378 ENTER_V8;
2379 HandleScope scope;
2380 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2381 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2382 return i::DeleteProperty(self, key_obj)->IsTrue();
2383}
2384
2385
2386bool v8::Object::Has(v8::Handle<String> key) {
2387 ON_BAILOUT("v8::Object::Has()", return false);
2388 ENTER_V8;
2389 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2390 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2391 return self->HasProperty(*key_obj);
2392}
2393
2394
2395bool v8::Object::Delete(uint32_t index) {
2396 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2397 ENTER_V8;
2398 HandleScope scope;
2399 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2400 return i::DeleteElement(self, index)->IsTrue();
2401}
2402
2403
2404bool v8::Object::Has(uint32_t index) {
2405 ON_BAILOUT("v8::Object::HasProperty()", return false);
2406 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2407 return self->HasElement(index);
2408}
2409
2410
Leon Clarkef7060e22010-06-03 12:02:55 +01002411bool Object::SetAccessor(Handle<String> name,
2412 AccessorGetter getter,
2413 AccessorSetter setter,
2414 v8::Handle<Value> data,
2415 AccessControl settings,
2416 PropertyAttribute attributes) {
2417 ON_BAILOUT("v8::Object::SetAccessor()", return false);
2418 ENTER_V8;
2419 HandleScope scope;
2420 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name,
2421 getter, setter, data,
2422 settings, attributes);
2423 i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info);
2424 return !result.is_null() && !result->IsUndefined();
2425}
2426
2427
Steve Blocka7e24c12009-10-30 11:49:00 +00002428bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2429 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2430 return Utils::OpenHandle(this)->HasRealNamedProperty(
2431 *Utils::OpenHandle(*key));
2432}
2433
2434
2435bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2436 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2437 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2438}
2439
2440
2441bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2442 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2443 ENTER_V8;
2444 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2445 *Utils::OpenHandle(*key));
2446}
2447
2448
2449bool v8::Object::HasNamedLookupInterceptor() {
2450 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2451 return Utils::OpenHandle(this)->HasNamedInterceptor();
2452}
2453
2454
2455bool v8::Object::HasIndexedLookupInterceptor() {
2456 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2457 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2458}
2459
2460
2461Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2462 Handle<String> key) {
2463 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2464 return Local<Value>());
2465 ENTER_V8;
2466 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2467 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2468 i::LookupResult lookup;
2469 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002470 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002471 PropertyAttributes attributes;
2472 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2473 &lookup,
2474 *key_obj,
2475 &attributes));
2476 return Utils::ToLocal(result);
2477 }
2478 return Local<Value>(); // No real property was found in prototype chain.
2479}
2480
2481
2482Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2483 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
2484 ENTER_V8;
2485 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2486 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2487 i::LookupResult lookup;
2488 self_obj->LookupRealNamedProperty(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002489 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002490 PropertyAttributes attributes;
2491 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2492 &lookup,
2493 *key_obj,
2494 &attributes));
2495 return Utils::ToLocal(result);
2496 }
2497 return Local<Value>(); // No real property was found in prototype chain.
2498}
2499
2500
2501// Turns on access checks by copying the map and setting the check flag.
2502// Because the object gets a new map, existing inline cache caching
2503// the old map of this object will fail.
2504void v8::Object::TurnOnAccessCheck() {
2505 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2506 ENTER_V8;
2507 HandleScope scope;
2508 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2509
2510 i::Handle<i::Map> new_map =
2511 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2512 new_map->set_is_access_check_needed(true);
2513 obj->set_map(*new_map);
2514}
2515
2516
2517bool v8::Object::IsDirty() {
2518 return Utils::OpenHandle(this)->IsDirty();
2519}
2520
2521
2522Local<v8::Object> v8::Object::Clone() {
2523 ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2524 ENTER_V8;
2525 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2526 EXCEPTION_PREAMBLE();
2527 i::Handle<i::JSObject> result = i::Copy(self);
2528 has_pending_exception = result.is_null();
2529 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2530 return Utils::ToLocal(result);
2531}
2532
2533
2534int v8::Object::GetIdentityHash() {
2535 ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2536 ENTER_V8;
2537 HandleScope scope;
2538 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2539 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2540 i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
2541 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2542 int hash_value;
2543 if (hash->IsSmi()) {
2544 hash_value = i::Smi::cast(*hash)->value();
2545 } else {
2546 int attempts = 0;
2547 do {
2548 // Generate a random 32-bit hash value but limit range to fit
2549 // within a smi.
2550 hash_value = i::V8::Random() & i::Smi::kMaxValue;
2551 attempts++;
2552 } while (hash_value == 0 && attempts < 30);
2553 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
2554 i::SetProperty(hidden_props,
2555 hash_symbol,
2556 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2557 static_cast<PropertyAttributes>(None));
2558 }
2559 return hash_value;
2560}
2561
2562
2563bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2564 v8::Handle<v8::Value> value) {
2565 ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
2566 ENTER_V8;
2567 HandleScope scope;
2568 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2569 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2570 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2571 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2572 EXCEPTION_PREAMBLE();
2573 i::Handle<i::Object> obj = i::SetProperty(
2574 hidden_props,
2575 key_obj,
2576 value_obj,
2577 static_cast<PropertyAttributes>(None));
2578 has_pending_exception = obj.is_null();
2579 EXCEPTION_BAILOUT_CHECK(false);
2580 return true;
2581}
2582
2583
2584v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2585 ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2586 ENTER_V8;
2587 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2588 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2589 if (hidden_props->IsUndefined()) {
2590 return v8::Local<v8::Value>();
2591 }
2592 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2593 EXCEPTION_PREAMBLE();
2594 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2595 has_pending_exception = result.is_null();
2596 EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2597 if (result->IsUndefined()) {
2598 return v8::Local<v8::Value>();
2599 }
2600 return Utils::ToLocal(result);
2601}
2602
2603
2604bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2605 ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2606 ENTER_V8;
2607 HandleScope scope;
2608 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2609 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2610 if (hidden_props->IsUndefined()) {
2611 return true;
2612 }
2613 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2614 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2615 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2616}
2617
2618
2619void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2620 ON_BAILOUT("v8::SetElementsToPixelData()", return);
2621 ENTER_V8;
2622 HandleScope scope;
Steve Block3ce2e202009-11-05 08:53:23 +00002623 if (!ApiCheck(length <= i::PixelArray::kMaxLength,
Steve Blocka7e24c12009-10-30 11:49:00 +00002624 "v8::Object::SetIndexedPropertiesToPixelData()",
2625 "length exceeds max acceptable value")) {
2626 return;
2627 }
2628 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2629 if (!ApiCheck(!self->IsJSArray(),
2630 "v8::Object::SetIndexedPropertiesToPixelData()",
2631 "JSArray is not supported")) {
2632 return;
2633 }
2634 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
Steve Block8defd9f2010-07-08 12:39:36 +01002635 self->set_map(
2636 *i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map())));
Steve Blocka7e24c12009-10-30 11:49:00 +00002637 self->set_elements(*pixels);
2638}
2639
2640
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002641bool v8::Object::HasIndexedPropertiesInPixelData() {
2642 ON_BAILOUT("v8::HasIndexedPropertiesInPixelData()", return false);
2643 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2644 return self->HasPixelElements();
2645}
2646
2647
2648uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
2649 ON_BAILOUT("v8::GetIndexedPropertiesPixelData()", return NULL);
2650 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2651 if (self->HasPixelElements()) {
2652 return i::PixelArray::cast(self->elements())->external_pointer();
2653 } else {
2654 return NULL;
2655 }
2656}
2657
2658
2659int v8::Object::GetIndexedPropertiesPixelDataLength() {
2660 ON_BAILOUT("v8::GetIndexedPropertiesPixelDataLength()", return -1);
2661 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2662 if (self->HasPixelElements()) {
2663 return i::PixelArray::cast(self->elements())->length();
2664 } else {
2665 return -1;
2666 }
2667}
2668
2669
Steve Block3ce2e202009-11-05 08:53:23 +00002670void v8::Object::SetIndexedPropertiesToExternalArrayData(
2671 void* data,
2672 ExternalArrayType array_type,
2673 int length) {
2674 ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
2675 ENTER_V8;
2676 HandleScope scope;
2677 if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
2678 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2679 "length exceeds max acceptable value")) {
2680 return;
2681 }
2682 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2683 if (!ApiCheck(!self->IsJSArray(),
2684 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2685 "JSArray is not supported")) {
2686 return;
2687 }
2688 i::Handle<i::ExternalArray> array =
2689 i::Factory::NewExternalArray(length, array_type, data);
Steve Block8defd9f2010-07-08 12:39:36 +01002690 self->set_map(
2691 *i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map())));
Steve Block3ce2e202009-11-05 08:53:23 +00002692 self->set_elements(*array);
2693}
2694
2695
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002696bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
2697 ON_BAILOUT("v8::HasIndexedPropertiesInExternalArrayData()", return false);
2698 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2699 return self->HasExternalArrayElements();
2700}
2701
2702
2703void* v8::Object::GetIndexedPropertiesExternalArrayData() {
2704 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayData()", return NULL);
2705 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2706 if (self->HasExternalArrayElements()) {
2707 return i::ExternalArray::cast(self->elements())->external_pointer();
2708 } else {
2709 return NULL;
2710 }
2711}
2712
2713
2714ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
2715 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataType()",
2716 return static_cast<ExternalArrayType>(-1));
2717 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2718 switch (self->elements()->map()->instance_type()) {
2719 case i::EXTERNAL_BYTE_ARRAY_TYPE:
2720 return kExternalByteArray;
2721 case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2722 return kExternalUnsignedByteArray;
2723 case i::EXTERNAL_SHORT_ARRAY_TYPE:
2724 return kExternalShortArray;
2725 case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2726 return kExternalUnsignedShortArray;
2727 case i::EXTERNAL_INT_ARRAY_TYPE:
2728 return kExternalIntArray;
2729 case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2730 return kExternalUnsignedIntArray;
2731 case i::EXTERNAL_FLOAT_ARRAY_TYPE:
2732 return kExternalFloatArray;
2733 default:
2734 return static_cast<ExternalArrayType>(-1);
2735 }
2736}
2737
2738
2739int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
2740 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataLength()", return 0);
2741 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2742 if (self->HasExternalArrayElements()) {
2743 return i::ExternalArray::cast(self->elements())->length();
2744 } else {
2745 return -1;
2746 }
2747}
2748
2749
Steve Blocka7e24c12009-10-30 11:49:00 +00002750Local<v8::Object> Function::NewInstance() const {
2751 return NewInstance(0, NULL);
2752}
2753
2754
2755Local<v8::Object> Function::NewInstance(int argc,
2756 v8::Handle<v8::Value> argv[]) const {
2757 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2758 LOG_API("Function::NewInstance");
2759 ENTER_V8;
2760 HandleScope scope;
2761 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2762 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2763 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2764 EXCEPTION_PREAMBLE();
2765 i::Handle<i::Object> returned =
2766 i::Execution::New(function, argc, args, &has_pending_exception);
2767 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2768 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2769}
2770
2771
2772Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2773 v8::Handle<v8::Value> argv[]) {
2774 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2775 LOG_API("Function::Call");
2776 ENTER_V8;
2777 i::Object* raw_result = NULL;
2778 {
2779 HandleScope scope;
2780 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2781 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2782 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2783 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2784 EXCEPTION_PREAMBLE();
2785 i::Handle<i::Object> returned =
2786 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2787 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2788 raw_result = *returned;
2789 }
2790 i::Handle<i::Object> result(raw_result);
2791 return Utils::ToLocal(result);
2792}
2793
2794
2795void Function::SetName(v8::Handle<v8::String> name) {
2796 ENTER_V8;
2797 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2798 func->shared()->set_name(*Utils::OpenHandle(*name));
2799}
2800
2801
2802Handle<Value> Function::GetName() const {
2803 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2804 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2805}
2806
2807
Andrei Popescu402d9372010-02-26 13:31:12 +00002808ScriptOrigin Function::GetScriptOrigin() const {
2809 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2810 if (func->shared()->script()->IsScript()) {
2811 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2812 v8::ScriptOrigin origin(
2813 Utils::ToLocal(i::Handle<i::Object>(script->name())),
2814 v8::Integer::New(script->line_offset()->value()),
2815 v8::Integer::New(script->column_offset()->value()));
2816 return origin;
2817 }
2818 return v8::ScriptOrigin(Handle<Value>());
2819}
2820
2821
2822const int Function::kLineOffsetNotFound = -1;
2823
2824
2825int Function::GetScriptLineNumber() const {
2826 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2827 if (func->shared()->script()->IsScript()) {
2828 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2829 return i::GetScriptLineNumber(script, func->shared()->start_position());
2830 }
2831 return kLineOffsetNotFound;
2832}
2833
2834
2835namespace {
2836
2837// Tracks string usage to help make better decisions when
2838// externalizing strings.
2839//
2840// Implementation note: internally this class only tracks fresh
2841// strings and keeps a single use counter for them.
2842class StringTracker {
2843 public:
2844 // Records that the given string's characters were copied to some
2845 // external buffer. If this happens often we should honor
2846 // externalization requests for the string.
2847 static void RecordWrite(i::Handle<i::String> string) {
2848 i::Address address = reinterpret_cast<i::Address>(*string);
2849 i::Address top = i::Heap::NewSpaceTop();
2850 if (IsFreshString(address, top)) {
2851 IncrementUseCount(top);
2852 }
2853 }
2854
2855 // Estimates freshness and use frequency of the given string based
2856 // on how close it is to the new space top and the recorded usage
2857 // history.
2858 static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
2859 i::Address address = reinterpret_cast<i::Address>(*string);
2860 i::Address top = i::Heap::NewSpaceTop();
2861 return IsFreshString(address, top) && IsUseCountLow(top);
2862 }
2863
2864 private:
2865 static inline bool IsFreshString(i::Address string, i::Address top) {
2866 return top - kFreshnessLimit <= string && string <= top;
2867 }
2868
2869 static inline bool IsUseCountLow(i::Address top) {
2870 if (last_top_ != top) return true;
2871 return use_count_ < kUseLimit;
2872 }
2873
2874 static inline void IncrementUseCount(i::Address top) {
2875 if (last_top_ != top) {
2876 use_count_ = 0;
2877 last_top_ = top;
2878 }
2879 ++use_count_;
2880 }
2881
2882 // How close to the new space top a fresh string has to be.
2883 static const int kFreshnessLimit = 1024;
2884
2885 // The number of uses required to consider a string useful.
2886 static const int kUseLimit = 32;
2887
2888 // Single use counter shared by all fresh strings.
2889 static int use_count_;
2890
2891 // Last new space top when the use count above was valid.
2892 static i::Address last_top_;
2893};
2894
2895int StringTracker::use_count_ = 0;
2896i::Address StringTracker::last_top_ = NULL;
2897
2898} // namespace
2899
2900
Steve Blocka7e24c12009-10-30 11:49:00 +00002901int String::Length() const {
2902 if (IsDeadCheck("v8::String::Length()")) return 0;
2903 return Utils::OpenHandle(this)->length();
2904}
2905
2906
2907int String::Utf8Length() const {
2908 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
2909 return Utils::OpenHandle(this)->Utf8Length();
2910}
2911
2912
Steve Block6ded16b2010-05-10 14:33:55 +01002913int String::WriteUtf8(char* buffer,
2914 int capacity,
2915 int* nchars_ref,
2916 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002917 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
2918 LOG_API("String::WriteUtf8");
2919 ENTER_V8;
2920 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002921 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002922 if (hints & HINT_MANY_WRITES_EXPECTED) {
2923 // Flatten the string for efficiency. This applies whether we are
2924 // using StringInputBuffer or Get(i) to access the characters.
2925 str->TryFlatten();
2926 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002927 write_input_buffer.Reset(0, *str);
2928 int len = str->length();
2929 // Encode the first K - 3 bytes directly into the buffer since we
2930 // know there's room for them. If no capacity is given we copy all
2931 // of them here.
2932 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
2933 int i;
2934 int pos = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01002935 int nchars = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002936 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
2937 i::uc32 c = write_input_buffer.GetNext();
2938 int written = unibrow::Utf8::Encode(buffer + pos, c);
2939 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002940 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002941 }
2942 if (i < len) {
2943 // For the last characters we need to check the length for each one
2944 // because they may be longer than the remaining space in the
2945 // buffer.
2946 char intermediate[unibrow::Utf8::kMaxEncodedSize];
2947 for (; i < len && pos < capacity; i++) {
2948 i::uc32 c = write_input_buffer.GetNext();
2949 int written = unibrow::Utf8::Encode(intermediate, c);
2950 if (pos + written <= capacity) {
2951 for (int j = 0; j < written; j++)
2952 buffer[pos + j] = intermediate[j];
2953 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002954 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002955 } else {
2956 // We've reached the end of the buffer
2957 break;
2958 }
2959 }
2960 }
Steve Block6ded16b2010-05-10 14:33:55 +01002961 if (nchars_ref != NULL) *nchars_ref = nchars;
Steve Blocka7e24c12009-10-30 11:49:00 +00002962 if (i == len && (capacity == -1 || pos < capacity))
2963 buffer[pos++] = '\0';
2964 return pos;
2965}
2966
2967
Steve Block6ded16b2010-05-10 14:33:55 +01002968int String::WriteAscii(char* buffer,
2969 int start,
2970 int length,
2971 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002972 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
2973 LOG_API("String::WriteAscii");
2974 ENTER_V8;
2975 ASSERT(start >= 0 && length >= -1);
2976 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002977 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002978 if (hints & HINT_MANY_WRITES_EXPECTED) {
2979 // Flatten the string for efficiency. This applies whether we are
2980 // using StringInputBuffer or Get(i) to access the characters.
2981 str->TryFlatten();
2982 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002983 int end = length;
2984 if ( (length == -1) || (length > str->length() - start) )
2985 end = str->length() - start;
2986 if (end < 0) return 0;
2987 write_input_buffer.Reset(start, *str);
2988 int i;
2989 for (i = 0; i < end; i++) {
2990 char c = static_cast<char>(write_input_buffer.GetNext());
2991 if (c == '\0') c = ' ';
2992 buffer[i] = c;
2993 }
2994 if (length == -1 || i < length)
2995 buffer[i] = '\0';
2996 return i;
2997}
2998
2999
Steve Block6ded16b2010-05-10 14:33:55 +01003000int String::Write(uint16_t* buffer,
3001 int start,
3002 int length,
3003 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003004 if (IsDeadCheck("v8::String::Write()")) return 0;
3005 LOG_API("String::Write");
3006 ENTER_V8;
3007 ASSERT(start >= 0 && length >= -1);
3008 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003009 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003010 if (hints & HINT_MANY_WRITES_EXPECTED) {
3011 // Flatten the string for efficiency. This applies whether we are
3012 // using StringInputBuffer or Get(i) to access the characters.
3013 str->TryFlatten();
3014 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003015 int end = length;
3016 if ( (length == -1) || (length > str->length() - start) )
3017 end = str->length() - start;
3018 if (end < 0) return 0;
3019 i::String::WriteToFlat(*str, buffer, start, end);
3020 if (length == -1 || end < length)
3021 buffer[end] = '\0';
3022 return end;
3023}
3024
3025
3026bool v8::String::IsExternal() const {
3027 EnsureInitialized("v8::String::IsExternal()");
3028 i::Handle<i::String> str = Utils::OpenHandle(this);
3029 return i::StringShape(*str).IsExternalTwoByte();
3030}
3031
3032
3033bool v8::String::IsExternalAscii() const {
3034 EnsureInitialized("v8::String::IsExternalAscii()");
3035 i::Handle<i::String> str = Utils::OpenHandle(this);
3036 return i::StringShape(*str).IsExternalAscii();
3037}
3038
3039
3040void v8::String::VerifyExternalStringResource(
3041 v8::String::ExternalStringResource* value) const {
3042 i::Handle<i::String> str = Utils::OpenHandle(this);
3043 v8::String::ExternalStringResource* expected;
3044 if (i::StringShape(*str).IsExternalTwoByte()) {
3045 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
3046 expected = reinterpret_cast<ExternalStringResource*>(resource);
3047 } else {
3048 expected = NULL;
3049 }
3050 CHECK_EQ(expected, value);
3051}
3052
3053
3054v8::String::ExternalAsciiStringResource*
3055 v8::String::GetExternalAsciiStringResource() const {
3056 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
3057 i::Handle<i::String> str = Utils::OpenHandle(this);
3058 if (i::StringShape(*str).IsExternalAscii()) {
3059 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
3060 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
3061 } else {
3062 return NULL;
3063 }
3064}
3065
3066
3067double Number::Value() const {
3068 if (IsDeadCheck("v8::Number::Value()")) return 0;
3069 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3070 return obj->Number();
3071}
3072
3073
3074bool Boolean::Value() const {
3075 if (IsDeadCheck("v8::Boolean::Value()")) return false;
3076 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3077 return obj->IsTrue();
3078}
3079
3080
3081int64_t Integer::Value() const {
3082 if (IsDeadCheck("v8::Integer::Value()")) return 0;
3083 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3084 if (obj->IsSmi()) {
3085 return i::Smi::cast(*obj)->value();
3086 } else {
3087 return static_cast<int64_t>(obj->Number());
3088 }
3089}
3090
3091
3092int32_t Int32::Value() const {
3093 if (IsDeadCheck("v8::Int32::Value()")) return 0;
3094 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3095 if (obj->IsSmi()) {
3096 return i::Smi::cast(*obj)->value();
3097 } else {
3098 return static_cast<int32_t>(obj->Number());
3099 }
3100}
3101
3102
Steve Block6ded16b2010-05-10 14:33:55 +01003103uint32_t Uint32::Value() const {
3104 if (IsDeadCheck("v8::Uint32::Value()")) return 0;
3105 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3106 if (obj->IsSmi()) {
3107 return i::Smi::cast(*obj)->value();
3108 } else {
3109 return static_cast<uint32_t>(obj->Number());
3110 }
3111}
3112
3113
Steve Blocka7e24c12009-10-30 11:49:00 +00003114int v8::Object::InternalFieldCount() {
3115 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
3116 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3117 return obj->GetInternalFieldCount();
3118}
3119
3120
3121Local<Value> v8::Object::CheckedGetInternalField(int index) {
3122 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
3123 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3124 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3125 "v8::Object::GetInternalField()",
3126 "Reading internal field out of bounds")) {
3127 return Local<Value>();
3128 }
3129 i::Handle<i::Object> value(obj->GetInternalField(index));
3130 Local<Value> result = Utils::ToLocal(value);
3131#ifdef DEBUG
3132 Local<Value> unchecked = UncheckedGetInternalField(index);
3133 ASSERT(unchecked.IsEmpty() || (unchecked == result));
3134#endif
3135 return result;
3136}
3137
3138
3139void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
3140 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
3141 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3142 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3143 "v8::Object::SetInternalField()",
3144 "Writing internal field out of bounds")) {
3145 return;
3146 }
3147 ENTER_V8;
3148 i::Handle<i::Object> val = Utils::OpenHandle(*value);
3149 obj->SetInternalField(index, *val);
3150}
3151
3152
3153void v8::Object::SetPointerInInternalField(int index, void* value) {
Steve Block6ded16b2010-05-10 14:33:55 +01003154 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003155 i::Object* as_object = reinterpret_cast<i::Object*>(value);
3156 if (as_object->IsSmi()) {
3157 Utils::OpenHandle(this)->SetInternalField(index, as_object);
3158 return;
3159 }
3160 HandleScope scope;
3161 i::Handle<i::Proxy> proxy =
3162 i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
3163 if (!proxy.is_null())
3164 Utils::OpenHandle(this)->SetInternalField(index, *proxy);
Steve Blocka7e24c12009-10-30 11:49:00 +00003165}
3166
3167
3168// --- E n v i r o n m e n t ---
3169
3170bool v8::V8::Initialize() {
3171 if (i::V8::IsRunning()) return true;
3172 ENTER_V8;
3173 HandleScope scope;
Steve Blockd0582a62009-12-15 09:54:21 +00003174 if (i::Snapshot::Initialize()) return true;
3175 return i::V8::Initialize(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00003176}
3177
3178
3179bool v8::V8::Dispose() {
3180 i::V8::TearDown();
3181 return true;
3182}
3183
3184
Steve Block3ce2e202009-11-05 08:53:23 +00003185HeapStatistics::HeapStatistics(): total_heap_size_(0), used_heap_size_(0) { }
3186
3187
3188void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
3189 heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
3190 heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
3191}
3192
3193
3194bool v8::V8::IdleNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003195 // Returning true tells the caller that it need not
3196 // continue to call IdleNotification.
3197 if (!i::V8::IsRunning()) return true;
Steve Block3ce2e202009-11-05 08:53:23 +00003198 return i::V8::IdleNotification();
Steve Blocka7e24c12009-10-30 11:49:00 +00003199}
3200
3201
3202void v8::V8::LowMemoryNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003203 if (!i::V8::IsRunning()) return;
3204 i::Heap::CollectAllGarbage(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00003205}
3206
3207
Steve Block6ded16b2010-05-10 14:33:55 +01003208int v8::V8::ContextDisposedNotification() {
3209 if (!i::V8::IsRunning()) return 0;
3210 return i::Heap::NotifyContextDisposed();
3211}
3212
3213
Steve Blocka7e24c12009-10-30 11:49:00 +00003214const char* v8::V8::GetVersion() {
3215 static v8::internal::EmbeddedVector<char, 128> buffer;
3216 v8::internal::Version::GetString(buffer);
3217 return buffer.start();
3218}
3219
3220
3221static i::Handle<i::FunctionTemplateInfo>
3222 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
3223 if (templ->constructor()->IsUndefined()) {
3224 Local<FunctionTemplate> constructor = FunctionTemplate::New();
3225 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
3226 templ->set_constructor(*Utils::OpenHandle(*constructor));
3227 }
3228 return i::Handle<i::FunctionTemplateInfo>(
3229 i::FunctionTemplateInfo::cast(templ->constructor()));
3230}
3231
3232
3233Persistent<Context> v8::Context::New(
3234 v8::ExtensionConfiguration* extensions,
3235 v8::Handle<ObjectTemplate> global_template,
3236 v8::Handle<Value> global_object) {
3237 EnsureInitialized("v8::Context::New()");
3238 LOG_API("Context::New");
3239 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
3240
3241 // Enter V8 via an ENTER_V8 scope.
3242 i::Handle<i::Context> env;
3243 {
3244 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003245 v8::Handle<ObjectTemplate> proxy_template = global_template;
3246 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
3247 i::Handle<i::FunctionTemplateInfo> global_constructor;
3248
3249 if (!global_template.IsEmpty()) {
3250 // Make sure that the global_template has a constructor.
3251 global_constructor =
3252 EnsureConstructor(Utils::OpenHandle(*global_template));
3253
3254 // Create a fresh template for the global proxy object.
3255 proxy_template = ObjectTemplate::New();
3256 proxy_constructor =
3257 EnsureConstructor(Utils::OpenHandle(*proxy_template));
3258
3259 // Set the global template to be the prototype template of
3260 // global proxy template.
3261 proxy_constructor->set_prototype_template(
3262 *Utils::OpenHandle(*global_template));
3263
3264 // Migrate security handlers from global_template to
3265 // proxy_template. Temporarily removing access check
3266 // information from the global template.
3267 if (!global_constructor->access_check_info()->IsUndefined()) {
3268 proxy_constructor->set_access_check_info(
3269 global_constructor->access_check_info());
3270 proxy_constructor->set_needs_access_check(
3271 global_constructor->needs_access_check());
3272 global_constructor->set_needs_access_check(false);
3273 global_constructor->set_access_check_info(i::Heap::undefined_value());
3274 }
3275 }
3276
3277 // Create the environment.
3278 env = i::Bootstrapper::CreateEnvironment(
3279 Utils::OpenHandle(*global_object),
3280 proxy_template,
3281 extensions);
3282
3283 // Restore the access check info on the global template.
3284 if (!global_template.IsEmpty()) {
3285 ASSERT(!global_constructor.is_null());
3286 ASSERT(!proxy_constructor.is_null());
3287 global_constructor->set_access_check_info(
3288 proxy_constructor->access_check_info());
3289 global_constructor->set_needs_access_check(
3290 proxy_constructor->needs_access_check());
3291 }
3292 }
3293 // Leave V8.
3294
3295 if (env.is_null())
3296 return Persistent<Context>();
3297 return Persistent<Context>(Utils::ToLocal(env));
3298}
3299
3300
3301void v8::Context::SetSecurityToken(Handle<Value> token) {
3302 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
3303 ENTER_V8;
3304 i::Handle<i::Context> env = Utils::OpenHandle(this);
3305 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
3306 env->set_security_token(*token_handle);
3307}
3308
3309
3310void v8::Context::UseDefaultSecurityToken() {
3311 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
3312 ENTER_V8;
3313 i::Handle<i::Context> env = Utils::OpenHandle(this);
3314 env->set_security_token(env->global());
3315}
3316
3317
3318Handle<Value> v8::Context::GetSecurityToken() {
3319 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
3320 i::Handle<i::Context> env = Utils::OpenHandle(this);
3321 i::Object* security_token = env->security_token();
3322 i::Handle<i::Object> token_handle(security_token);
3323 return Utils::ToLocal(token_handle);
3324}
3325
3326
3327bool Context::HasOutOfMemoryException() {
3328 i::Handle<i::Context> env = Utils::OpenHandle(this);
3329 return env->has_out_of_memory();
3330}
3331
3332
3333bool Context::InContext() {
3334 return i::Top::context() != NULL;
3335}
3336
3337
3338v8::Local<v8::Context> Context::GetEntered() {
3339 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
3340 i::Handle<i::Object> last = thread_local.LastEnteredContext();
3341 if (last.is_null()) return Local<Context>();
3342 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
3343 return Utils::ToLocal(context);
3344}
3345
3346
3347v8::Local<v8::Context> Context::GetCurrent() {
3348 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
Steve Block3ce2e202009-11-05 08:53:23 +00003349 i::Handle<i::Object> current = i::Top::global_context();
3350 if (current.is_null()) return Local<Context>();
3351 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
Steve Blocka7e24c12009-10-30 11:49:00 +00003352 return Utils::ToLocal(context);
3353}
3354
3355
3356v8::Local<v8::Context> Context::GetCalling() {
3357 if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
3358 i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
3359 if (calling.is_null()) return Local<Context>();
3360 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
3361 return Utils::ToLocal(context);
3362}
3363
3364
3365v8::Local<v8::Object> Context::Global() {
3366 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
3367 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3368 i::Handle<i::Context> context =
3369 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3370 i::Handle<i::Object> global(context->global_proxy());
3371 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
3372}
3373
3374
3375void Context::DetachGlobal() {
3376 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
3377 ENTER_V8;
3378 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3379 i::Handle<i::Context> context =
3380 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3381 i::Bootstrapper::DetachGlobal(context);
3382}
3383
3384
Andrei Popescu74b3c142010-03-29 12:03:09 +01003385void Context::ReattachGlobal(Handle<Object> global_object) {
3386 if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
3387 ENTER_V8;
3388 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3389 i::Handle<i::Context> context =
3390 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3391 i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
3392}
3393
3394
Steve Blocka7e24c12009-10-30 11:49:00 +00003395Local<v8::Object> ObjectTemplate::NewInstance() {
3396 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
3397 LOG_API("ObjectTemplate::NewInstance");
3398 ENTER_V8;
3399 EXCEPTION_PREAMBLE();
3400 i::Handle<i::Object> obj =
3401 i::Execution::InstantiateObject(Utils::OpenHandle(this),
3402 &has_pending_exception);
3403 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
3404 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3405}
3406
3407
3408Local<v8::Function> FunctionTemplate::GetFunction() {
3409 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
3410 return Local<v8::Function>());
3411 LOG_API("FunctionTemplate::GetFunction");
3412 ENTER_V8;
3413 EXCEPTION_PREAMBLE();
3414 i::Handle<i::Object> obj =
3415 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3416 &has_pending_exception);
3417 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
3418 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3419}
3420
3421
3422bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3423 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
3424 i::Object* obj = *Utils::OpenHandle(*value);
3425 return obj->IsInstanceOf(*Utils::OpenHandle(this));
3426}
3427
3428
3429static Local<External> ExternalNewImpl(void* data) {
3430 return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
3431}
3432
3433static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3434 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3435}
3436
3437
Steve Blocka7e24c12009-10-30 11:49:00 +00003438Local<Value> v8::External::Wrap(void* data) {
3439 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3440 LOG_API("External::Wrap");
3441 EnsureInitialized("v8::External::Wrap()");
3442 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003443 i::Object* as_object = reinterpret_cast<i::Object*>(data);
3444 if (as_object->IsSmi()) {
3445 return Utils::ToLocal(i::Handle<i::Object>(as_object));
Steve Blocka7e24c12009-10-30 11:49:00 +00003446 }
3447 return ExternalNewImpl(data);
3448}
3449
3450
Steve Block3ce2e202009-11-05 08:53:23 +00003451void* v8::Object::SlowGetPointerFromInternalField(int index) {
3452 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3453 i::Object* value = obj->GetInternalField(index);
3454 if (value->IsSmi()) {
3455 return value;
3456 } else if (value->IsProxy()) {
3457 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3458 } else {
3459 return NULL;
3460 }
3461}
3462
3463
Steve Blocka7e24c12009-10-30 11:49:00 +00003464void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3465 if (IsDeadCheck("v8::External::Unwrap()")) return 0;
3466 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3467 void* result;
3468 if (obj->IsSmi()) {
3469 // The external value was an aligned pointer.
Steve Block3ce2e202009-11-05 08:53:23 +00003470 result = *obj;
Steve Blocka7e24c12009-10-30 11:49:00 +00003471 } else if (obj->IsProxy()) {
3472 result = ExternalValueImpl(obj);
3473 } else {
3474 result = NULL;
3475 }
3476 ASSERT_EQ(result, QuickUnwrap(wrapper));
3477 return result;
3478}
3479
3480
3481Local<External> v8::External::New(void* data) {
3482 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3483 LOG_API("External::New");
3484 EnsureInitialized("v8::External::New()");
3485 ENTER_V8;
3486 return ExternalNewImpl(data);
3487}
3488
3489
3490void* External::Value() const {
3491 if (IsDeadCheck("v8::External::Value()")) return 0;
3492 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3493 return ExternalValueImpl(obj);
3494}
3495
3496
3497Local<String> v8::String::Empty() {
3498 EnsureInitialized("v8::String::Empty()");
3499 LOG_API("String::Empty()");
3500 return Utils::ToLocal(i::Factory::empty_symbol());
3501}
3502
3503
3504Local<String> v8::String::New(const char* data, int length) {
3505 EnsureInitialized("v8::String::New()");
3506 LOG_API("String::New(char)");
3507 if (length == 0) return Empty();
3508 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003509 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003510 i::Handle<i::String> result =
3511 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3512 return Utils::ToLocal(result);
3513}
3514
3515
Steve Block3ce2e202009-11-05 08:53:23 +00003516Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3517 EnsureInitialized("v8::String::New()");
3518 LOG_API("String::New(char)");
3519 ENTER_V8;
3520 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3521 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3522 i::Handle<i::String> result = i::Factory::NewConsString(left_string,
3523 right_string);
3524 return Utils::ToLocal(result);
3525}
3526
3527
Steve Blocka7e24c12009-10-30 11:49:00 +00003528Local<String> v8::String::NewUndetectable(const char* data, int length) {
3529 EnsureInitialized("v8::String::NewUndetectable()");
3530 LOG_API("String::NewUndetectable(char)");
3531 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003532 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003533 i::Handle<i::String> result =
3534 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3535 result->MarkAsUndetectable();
3536 return Utils::ToLocal(result);
3537}
3538
3539
3540static int TwoByteStringLength(const uint16_t* data) {
3541 int length = 0;
3542 while (data[length] != '\0') length++;
3543 return length;
3544}
3545
3546
3547Local<String> v8::String::New(const uint16_t* data, int length) {
3548 EnsureInitialized("v8::String::New()");
3549 LOG_API("String::New(uint16_)");
3550 if (length == 0) return Empty();
3551 ENTER_V8;
3552 if (length == -1) length = TwoByteStringLength(data);
3553 i::Handle<i::String> result =
3554 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3555 return Utils::ToLocal(result);
3556}
3557
3558
3559Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
3560 EnsureInitialized("v8::String::NewUndetectable()");
3561 LOG_API("String::NewUndetectable(uint16_)");
3562 ENTER_V8;
3563 if (length == -1) length = TwoByteStringLength(data);
3564 i::Handle<i::String> result =
3565 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3566 result->MarkAsUndetectable();
3567 return Utils::ToLocal(result);
3568}
3569
3570
3571i::Handle<i::String> NewExternalStringHandle(
3572 v8::String::ExternalStringResource* resource) {
3573 i::Handle<i::String> result =
3574 i::Factory::NewExternalStringFromTwoByte(resource);
3575 return result;
3576}
3577
3578
3579i::Handle<i::String> NewExternalAsciiStringHandle(
3580 v8::String::ExternalAsciiStringResource* resource) {
3581 i::Handle<i::String> result =
3582 i::Factory::NewExternalStringFromAscii(resource);
3583 return result;
3584}
3585
3586
Steve Blocka7e24c12009-10-30 11:49:00 +00003587Local<String> v8::String::NewExternal(
3588 v8::String::ExternalStringResource* resource) {
3589 EnsureInitialized("v8::String::NewExternal()");
3590 LOG_API("String::NewExternal");
3591 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003592 i::Handle<i::String> result = NewExternalStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003593 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003594 return Utils::ToLocal(result);
3595}
3596
3597
3598bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3599 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3600 if (this->IsExternal()) return false; // Already an external string.
3601 ENTER_V8;
3602 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003603 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003604 bool result = obj->MakeExternal(resource);
3605 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003606 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003607 }
3608 return result;
3609}
3610
3611
3612Local<String> v8::String::NewExternal(
3613 v8::String::ExternalAsciiStringResource* resource) {
3614 EnsureInitialized("v8::String::NewExternal()");
3615 LOG_API("String::NewExternal");
3616 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003617 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003618 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003619 return Utils::ToLocal(result);
3620}
3621
3622
3623bool v8::String::MakeExternal(
3624 v8::String::ExternalAsciiStringResource* resource) {
3625 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3626 if (this->IsExternal()) return false; // Already an external string.
3627 ENTER_V8;
3628 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003629 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003630 bool result = obj->MakeExternal(resource);
3631 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003632 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003633 }
3634 return result;
3635}
3636
3637
3638bool v8::String::CanMakeExternal() {
3639 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3640 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003641 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003642 int size = obj->Size(); // Byte size of the original string.
3643 if (size < i::ExternalString::kSize)
3644 return false;
3645 i::StringShape shape(*obj);
3646 return !shape.IsExternal();
3647}
3648
3649
3650Local<v8::Object> v8::Object::New() {
3651 EnsureInitialized("v8::Object::New()");
3652 LOG_API("Object::New");
3653 ENTER_V8;
3654 i::Handle<i::JSObject> obj =
3655 i::Factory::NewJSObject(i::Top::object_function());
3656 return Utils::ToLocal(obj);
3657}
3658
3659
3660Local<v8::Value> v8::Date::New(double time) {
3661 EnsureInitialized("v8::Date::New()");
3662 LOG_API("Date::New");
Steve Blockd0582a62009-12-15 09:54:21 +00003663 if (isnan(time)) {
3664 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3665 time = i::OS::nan_value();
3666 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003667 ENTER_V8;
3668 EXCEPTION_PREAMBLE();
3669 i::Handle<i::Object> obj =
3670 i::Execution::NewDate(time, &has_pending_exception);
3671 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3672 return Utils::ToLocal(obj);
3673}
3674
3675
3676double v8::Date::NumberValue() const {
3677 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3678 LOG_API("Date::NumberValue");
3679 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3680 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3681 return jsvalue->value()->Number();
3682}
3683
3684
3685Local<v8::Array> v8::Array::New(int length) {
3686 EnsureInitialized("v8::Array::New()");
3687 LOG_API("Array::New");
3688 ENTER_V8;
3689 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3690 return Utils::ToLocal(obj);
3691}
3692
3693
3694uint32_t v8::Array::Length() const {
3695 if (IsDeadCheck("v8::Array::Length()")) return 0;
3696 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3697 i::Object* length = obj->length();
3698 if (length->IsSmi()) {
3699 return i::Smi::cast(length)->value();
3700 } else {
3701 return static_cast<uint32_t>(length->Number());
3702 }
3703}
3704
3705
3706Local<Object> Array::CloneElementAt(uint32_t index) {
3707 ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3708 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3709 if (!self->HasFastElements()) {
3710 return Local<Object>();
3711 }
3712 i::FixedArray* elms = i::FixedArray::cast(self->elements());
3713 i::Object* paragon = elms->get(index);
3714 if (!paragon->IsJSObject()) {
3715 return Local<Object>();
3716 }
3717 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3718 EXCEPTION_PREAMBLE();
Steve Block6ded16b2010-05-10 14:33:55 +01003719 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003720 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3721 has_pending_exception = result.is_null();
3722 EXCEPTION_BAILOUT_CHECK(Local<Object>());
3723 return Utils::ToLocal(result);
3724}
3725
3726
3727Local<String> v8::String::NewSymbol(const char* data, int length) {
3728 EnsureInitialized("v8::String::NewSymbol()");
3729 LOG_API("String::NewSymbol(char)");
3730 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003731 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003732 i::Handle<i::String> result =
3733 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3734 return Utils::ToLocal(result);
3735}
3736
3737
3738Local<Number> v8::Number::New(double value) {
3739 EnsureInitialized("v8::Number::New()");
Steve Blockd0582a62009-12-15 09:54:21 +00003740 if (isnan(value)) {
3741 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3742 value = i::OS::nan_value();
3743 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003744 ENTER_V8;
3745 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3746 return Utils::NumberToLocal(result);
3747}
3748
3749
3750Local<Integer> v8::Integer::New(int32_t value) {
3751 EnsureInitialized("v8::Integer::New()");
3752 if (i::Smi::IsValid(value)) {
3753 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3754 }
3755 ENTER_V8;
3756 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3757 return Utils::IntegerToLocal(result);
3758}
3759
3760
Steve Block3ce2e202009-11-05 08:53:23 +00003761Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
3762 bool fits_into_int32_t = (value & (1 << 31)) == 0;
3763 if (fits_into_int32_t) {
3764 return Integer::New(static_cast<int32_t>(value));
3765 }
3766 ENTER_V8;
3767 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3768 return Utils::IntegerToLocal(result);
3769}
3770
3771
Steve Blocka7e24c12009-10-30 11:49:00 +00003772void V8::IgnoreOutOfMemoryException() {
3773 thread_local.set_ignore_out_of_memory(true);
3774}
3775
3776
3777bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
3778 EnsureInitialized("v8::V8::AddMessageListener()");
3779 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
3780 ENTER_V8;
3781 HandleScope scope;
3782 NeanderArray listeners(i::Factory::message_listeners());
3783 NeanderObject obj(2);
3784 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
3785 obj.set(1, data.IsEmpty() ?
3786 i::Heap::undefined_value() :
3787 *Utils::OpenHandle(*data));
3788 listeners.add(obj.value());
3789 return true;
3790}
3791
3792
3793void V8::RemoveMessageListeners(MessageCallback that) {
3794 EnsureInitialized("v8::V8::RemoveMessageListener()");
3795 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
3796 ENTER_V8;
3797 HandleScope scope;
3798 NeanderArray listeners(i::Factory::message_listeners());
3799 for (int i = 0; i < listeners.length(); i++) {
3800 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
3801
3802 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
3803 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
3804 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
3805 listeners.set(i, i::Heap::undefined_value());
3806 }
3807 }
3808}
3809
3810
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003811void V8::SetCaptureStackTraceForUncaughtExceptions(
3812 bool capture,
3813 int frame_limit,
3814 StackTrace::StackTraceOptions options) {
3815 i::Top::SetCaptureStackTraceForUncaughtExceptions(
3816 capture,
3817 frame_limit,
3818 options);
3819}
3820
3821
Steve Blocka7e24c12009-10-30 11:49:00 +00003822void V8::SetCounterFunction(CounterLookupCallback callback) {
3823 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
3824 i::StatsTable::SetCounterFunction(callback);
3825}
3826
3827void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
3828 if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
3829 i::StatsTable::SetCreateHistogramFunction(callback);
3830}
3831
3832void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
3833 if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
3834 i::StatsTable::SetAddHistogramSampleFunction(callback);
3835}
3836
3837void V8::EnableSlidingStateWindow() {
3838 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
3839 i::Logger::EnableSlidingStateWindow();
3840}
3841
3842
3843void V8::SetFailedAccessCheckCallbackFunction(
3844 FailedAccessCheckCallback callback) {
3845 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
3846 i::Top::SetFailedAccessCheckCallback(callback);
3847}
3848
3849
3850void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
3851 if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
3852 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
3853 i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
3854}
3855
3856
3857int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
3858 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
3859 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
3860}
3861
3862
3863void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
3864 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
3865 i::Heap::SetGlobalGCPrologueCallback(callback);
3866}
3867
3868
3869void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
3870 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
3871 i::Heap::SetGlobalGCEpilogueCallback(callback);
3872}
3873
3874
Steve Block6ded16b2010-05-10 14:33:55 +01003875void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
3876 if (IsDeadCheck("v8::V8::AddGCPrologueCallback()")) return;
3877 i::Heap::AddGCPrologueCallback(callback, gc_type);
3878}
3879
3880
3881void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
3882 if (IsDeadCheck("v8::V8::RemoveGCPrologueCallback()")) return;
3883 i::Heap::RemoveGCPrologueCallback(callback);
3884}
3885
3886
3887void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
3888 if (IsDeadCheck("v8::V8::AddGCEpilogueCallback()")) return;
3889 i::Heap::AddGCEpilogueCallback(callback, gc_type);
3890}
3891
3892
3893void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
3894 if (IsDeadCheck("v8::V8::RemoveGCEpilogueCallback()")) return;
3895 i::Heap::RemoveGCEpilogueCallback(callback);
3896}
3897
3898
Steve Blocka7e24c12009-10-30 11:49:00 +00003899void V8::PauseProfiler() {
3900#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003901 PauseProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003902#endif
3903}
3904
3905
3906void V8::ResumeProfiler() {
3907#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003908 ResumeProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003909#endif
3910}
3911
3912
3913bool V8::IsProfilerPaused() {
3914#ifdef ENABLE_LOGGING_AND_PROFILING
3915 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
3916#else
3917 return true;
3918#endif
3919}
3920
3921
Andrei Popescu402d9372010-02-26 13:31:12 +00003922void V8::ResumeProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003923#ifdef ENABLE_LOGGING_AND_PROFILING
3924 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
3925 // Snapshot mode: resume modules, perform GC, then pause only
3926 // those modules which haven't been started prior to making a
3927 // snapshot.
3928
Steve Block6ded16b2010-05-10 14:33:55 +01003929 // Make a GC prior to taking a snapshot.
3930 i::Heap::CollectAllGarbage(false);
Steve Blocka7e24c12009-10-30 11:49:00 +00003931 // Reset snapshot flag and CPU module flags.
3932 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
3933 const int current_flags = i::Logger::GetActiveProfilerModules();
Andrei Popescu402d9372010-02-26 13:31:12 +00003934 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003935 i::Heap::CollectAllGarbage(false);
Andrei Popescu402d9372010-02-26 13:31:12 +00003936 i::Logger::PauseProfiler(~current_flags & flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003937 } else {
Andrei Popescu402d9372010-02-26 13:31:12 +00003938 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003939 }
3940#endif
3941}
3942
3943
Andrei Popescu402d9372010-02-26 13:31:12 +00003944void V8::PauseProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003945#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003946 i::Logger::PauseProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003947#endif
3948}
3949
3950
3951int V8::GetActiveProfilerModules() {
3952#ifdef ENABLE_LOGGING_AND_PROFILING
3953 return i::Logger::GetActiveProfilerModules();
3954#else
3955 return PROFILER_MODULE_NONE;
3956#endif
3957}
3958
3959
3960int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
3961#ifdef ENABLE_LOGGING_AND_PROFILING
Steve Block6ded16b2010-05-10 14:33:55 +01003962 ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
Steve Blocka7e24c12009-10-30 11:49:00 +00003963 return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
3964#endif
3965 return 0;
3966}
3967
3968
3969int V8::GetCurrentThreadId() {
3970 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3971 EnsureInitialized("V8::GetCurrentThreadId()");
3972 return i::Top::thread_id();
3973}
3974
3975
3976void V8::TerminateExecution(int thread_id) {
3977 if (!i::V8::IsRunning()) return;
3978 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3979 // If the thread_id identifies the current thread just terminate
3980 // execution right away. Otherwise, ask the thread manager to
3981 // terminate the thread with the given id if any.
3982 if (thread_id == i::Top::thread_id()) {
3983 i::StackGuard::TerminateExecution();
3984 } else {
3985 i::ThreadManager::TerminateExecution(thread_id);
3986 }
3987}
3988
3989
3990void V8::TerminateExecution() {
3991 if (!i::V8::IsRunning()) return;
3992 i::StackGuard::TerminateExecution();
3993}
3994
3995
Steve Block6ded16b2010-05-10 14:33:55 +01003996bool V8::IsExecutionTerminating() {
3997 if (!i::V8::IsRunning()) return false;
3998 if (i::Top::has_scheduled_exception()) {
3999 return i::Top::scheduled_exception() == i::Heap::termination_exception();
4000 }
4001 return false;
4002}
4003
4004
Steve Blocka7e24c12009-10-30 11:49:00 +00004005String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
4006 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
4007 if (obj.IsEmpty()) {
4008 str_ = NULL;
4009 length_ = 0;
4010 return;
4011 }
4012 ENTER_V8;
4013 HandleScope scope;
4014 TryCatch try_catch;
4015 Handle<String> str = obj->ToString();
4016 if (str.IsEmpty()) {
4017 str_ = NULL;
4018 length_ = 0;
4019 } else {
4020 length_ = str->Utf8Length();
4021 str_ = i::NewArray<char>(length_ + 1);
4022 str->WriteUtf8(str_);
4023 }
4024}
4025
4026
4027String::Utf8Value::~Utf8Value() {
4028 i::DeleteArray(str_);
4029}
4030
4031
4032String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
4033 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
4034 if (obj.IsEmpty()) {
4035 str_ = NULL;
4036 length_ = 0;
4037 return;
4038 }
4039 ENTER_V8;
4040 HandleScope scope;
4041 TryCatch try_catch;
4042 Handle<String> str = obj->ToString();
4043 if (str.IsEmpty()) {
4044 str_ = NULL;
4045 length_ = 0;
4046 } else {
4047 length_ = str->Length();
4048 str_ = i::NewArray<char>(length_ + 1);
4049 str->WriteAscii(str_);
4050 }
4051}
4052
4053
4054String::AsciiValue::~AsciiValue() {
4055 i::DeleteArray(str_);
4056}
4057
4058
4059String::Value::Value(v8::Handle<v8::Value> obj) {
4060 EnsureInitialized("v8::String::Value::Value()");
4061 if (obj.IsEmpty()) {
4062 str_ = NULL;
4063 length_ = 0;
4064 return;
4065 }
4066 ENTER_V8;
4067 HandleScope scope;
4068 TryCatch try_catch;
4069 Handle<String> str = obj->ToString();
4070 if (str.IsEmpty()) {
4071 str_ = NULL;
4072 length_ = 0;
4073 } else {
4074 length_ = str->Length();
4075 str_ = i::NewArray<uint16_t>(length_ + 1);
4076 str->Write(str_);
4077 }
4078}
4079
4080
4081String::Value::~Value() {
4082 i::DeleteArray(str_);
4083}
4084
4085Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
4086 LOG_API("RangeError");
4087 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
4088 ENTER_V8;
4089 i::Object* error;
4090 {
4091 HandleScope scope;
4092 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4093 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
4094 error = *result;
4095 }
4096 i::Handle<i::Object> result(error);
4097 return Utils::ToLocal(result);
4098}
4099
4100Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
4101 LOG_API("ReferenceError");
4102 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
4103 ENTER_V8;
4104 i::Object* error;
4105 {
4106 HandleScope scope;
4107 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4108 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
4109 error = *result;
4110 }
4111 i::Handle<i::Object> result(error);
4112 return Utils::ToLocal(result);
4113}
4114
4115Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
4116 LOG_API("SyntaxError");
4117 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
4118 ENTER_V8;
4119 i::Object* error;
4120 {
4121 HandleScope scope;
4122 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4123 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
4124 error = *result;
4125 }
4126 i::Handle<i::Object> result(error);
4127 return Utils::ToLocal(result);
4128}
4129
4130Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
4131 LOG_API("TypeError");
4132 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
4133 ENTER_V8;
4134 i::Object* error;
4135 {
4136 HandleScope scope;
4137 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4138 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
4139 error = *result;
4140 }
4141 i::Handle<i::Object> result(error);
4142 return Utils::ToLocal(result);
4143}
4144
4145Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
4146 LOG_API("Error");
4147 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
4148 ENTER_V8;
4149 i::Object* error;
4150 {
4151 HandleScope scope;
4152 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4153 i::Handle<i::Object> result = i::Factory::NewError(message);
4154 error = *result;
4155 }
4156 i::Handle<i::Object> result(error);
4157 return Utils::ToLocal(result);
4158}
4159
4160
4161// --- D e b u g S u p p o r t ---
4162
4163#ifdef ENABLE_DEBUGGER_SUPPORT
Leon Clarkef7060e22010-06-03 12:02:55 +01004164
4165static v8::Debug::EventCallback event_callback = NULL;
4166
4167static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) {
4168 if (event_callback) {
4169 event_callback(event_details.GetEvent(),
4170 event_details.GetExecutionState(),
4171 event_details.GetEventData(),
4172 event_details.GetCallbackData());
4173 }
4174}
4175
4176
Steve Blocka7e24c12009-10-30 11:49:00 +00004177bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
4178 EnsureInitialized("v8::Debug::SetDebugEventListener()");
4179 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4180 ENTER_V8;
Leon Clarkef7060e22010-06-03 12:02:55 +01004181
4182 event_callback = that;
4183
4184 HandleScope scope;
4185 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4186 if (that != NULL) {
4187 proxy = i::Factory::NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
4188 }
4189 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4190 return true;
4191}
4192
4193
4194bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
4195 EnsureInitialized("v8::Debug::SetDebugEventListener2()");
4196 ON_BAILOUT("v8::Debug::SetDebugEventListener2()", return false);
4197 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004198 HandleScope scope;
4199 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4200 if (that != NULL) {
4201 proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
4202 }
4203 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4204 return true;
4205}
4206
4207
4208bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
4209 Handle<Value> data) {
4210 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4211 ENTER_V8;
4212 i::Debugger::SetEventListener(Utils::OpenHandle(*that),
4213 Utils::OpenHandle(*data));
4214 return true;
4215}
4216
4217
4218void Debug::DebugBreak() {
4219 if (!i::V8::IsRunning()) return;
4220 i::StackGuard::DebugBreak();
4221}
4222
4223
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004224void Debug::DebugBreakForCommand(ClientData* data) {
4225 if (!i::V8::IsRunning()) return;
4226 i::Debugger::EnqueueDebugCommand(data);
4227}
4228
4229
Steve Blocka7e24c12009-10-30 11:49:00 +00004230static v8::Debug::MessageHandler message_handler = NULL;
4231
4232static void MessageHandlerWrapper(const v8::Debug::Message& message) {
4233 if (message_handler) {
4234 v8::String::Value json(message.GetJSON());
4235 message_handler(*json, json.length(), message.GetClientData());
4236 }
4237}
4238
4239
4240void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
4241 bool message_handler_thread) {
4242 EnsureInitialized("v8::Debug::SetMessageHandler");
4243 ENTER_V8;
4244 // Message handler thread not supported any more. Parameter temporally left in
4245 // the API for client compatability reasons.
4246 CHECK(!message_handler_thread);
4247
4248 // TODO(sgjesse) support the old message handler API through a simple wrapper.
4249 message_handler = handler;
4250 if (message_handler != NULL) {
4251 i::Debugger::SetMessageHandler(MessageHandlerWrapper);
4252 } else {
4253 i::Debugger::SetMessageHandler(NULL);
4254 }
4255}
4256
4257
4258void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
4259 EnsureInitialized("v8::Debug::SetMessageHandler");
4260 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004261 i::Debugger::SetMessageHandler(handler);
4262}
4263
4264
4265void Debug::SendCommand(const uint16_t* command, int length,
4266 ClientData* client_data) {
4267 if (!i::V8::IsRunning()) return;
4268 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
4269 client_data);
4270}
4271
4272
4273void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
4274 int period) {
4275 EnsureInitialized("v8::Debug::SetHostDispatchHandler");
4276 ENTER_V8;
4277 i::Debugger::SetHostDispatchHandler(handler, period);
4278}
4279
4280
Steve Blockd0582a62009-12-15 09:54:21 +00004281void Debug::SetDebugMessageDispatchHandler(
Leon Clarkee46be812010-01-19 14:06:41 +00004282 DebugMessageDispatchHandler handler, bool provide_locker) {
Steve Blockd0582a62009-12-15 09:54:21 +00004283 EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
4284 ENTER_V8;
Leon Clarkee46be812010-01-19 14:06:41 +00004285 i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
Steve Blockd0582a62009-12-15 09:54:21 +00004286}
4287
4288
Steve Blocka7e24c12009-10-30 11:49:00 +00004289Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
4290 v8::Handle<v8::Value> data) {
4291 if (!i::V8::IsRunning()) return Local<Value>();
4292 ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
4293 ENTER_V8;
4294 i::Handle<i::Object> result;
4295 EXCEPTION_PREAMBLE();
4296 if (data.IsEmpty()) {
4297 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4298 i::Factory::undefined_value(),
4299 &has_pending_exception);
4300 } else {
4301 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4302 Utils::OpenHandle(*data),
4303 &has_pending_exception);
4304 }
4305 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4306 return Utils::ToLocal(result);
4307}
4308
4309
4310Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
4311 if (!i::V8::IsRunning()) return Local<Value>();
4312 ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
4313 ENTER_V8;
4314 v8::HandleScope scope;
4315 i::Debug::Load();
4316 i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
4317 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
4318 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
4319 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
4320 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
4321 const int kArgc = 1;
4322 v8::Handle<v8::Value> argv[kArgc] = { obj };
4323 EXCEPTION_PREAMBLE();
4324 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
4325 kArgc,
4326 argv);
4327 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4328 return scope.Close(result);
4329}
4330
4331
Leon Clarkee46be812010-01-19 14:06:41 +00004332bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
4333 return i::Debugger::StartAgent(name, port, wait_for_connection);
Steve Blocka7e24c12009-10-30 11:49:00 +00004334}
Leon Clarkee46be812010-01-19 14:06:41 +00004335
4336void Debug::ProcessDebugMessages() {
4337 i::Execution::ProcessDebugMesssages(true);
4338}
4339
Steve Block6ded16b2010-05-10 14:33:55 +01004340Local<Context> Debug::GetDebugContext() {
4341 EnsureInitialized("v8::Debug::GetDebugContext()");
4342 ENTER_V8;
4343 return Utils::ToLocal(i::Debugger::GetDebugContext());
4344}
4345
Steve Blocka7e24c12009-10-30 11:49:00 +00004346#endif // ENABLE_DEBUGGER_SUPPORT
4347
Steve Block6ded16b2010-05-10 14:33:55 +01004348
4349#ifdef ENABLE_LOGGING_AND_PROFILING
4350
4351Handle<String> CpuProfileNode::GetFunctionName() const {
4352 IsDeadCheck("v8::CpuProfileNode::GetFunctionName");
4353 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4354 const i::CodeEntry* entry = node->entry();
4355 if (!entry->has_name_prefix()) {
4356 return Handle<String>(ToApi<String>(
4357 i::Factory::LookupAsciiSymbol(entry->name())));
4358 } else {
4359 return Handle<String>(ToApi<String>(i::Factory::NewConsString(
4360 i::Factory::LookupAsciiSymbol(entry->name_prefix()),
4361 i::Factory::LookupAsciiSymbol(entry->name()))));
4362 }
4363}
4364
4365
4366Handle<String> CpuProfileNode::GetScriptResourceName() const {
4367 IsDeadCheck("v8::CpuProfileNode::GetScriptResourceName");
4368 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4369 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4370 node->entry()->resource_name())));
4371}
4372
4373
4374int CpuProfileNode::GetLineNumber() const {
4375 IsDeadCheck("v8::CpuProfileNode::GetLineNumber");
4376 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
4377}
4378
4379
4380double CpuProfileNode::GetTotalTime() const {
4381 IsDeadCheck("v8::CpuProfileNode::GetTotalTime");
4382 return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis();
4383}
4384
4385
4386double CpuProfileNode::GetSelfTime() const {
4387 IsDeadCheck("v8::CpuProfileNode::GetSelfTime");
4388 return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis();
4389}
4390
4391
4392double CpuProfileNode::GetTotalSamplesCount() const {
4393 IsDeadCheck("v8::CpuProfileNode::GetTotalSamplesCount");
4394 return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
4395}
4396
4397
4398double CpuProfileNode::GetSelfSamplesCount() const {
4399 IsDeadCheck("v8::CpuProfileNode::GetSelfSamplesCount");
4400 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
4401}
4402
4403
4404unsigned CpuProfileNode::GetCallUid() const {
4405 IsDeadCheck("v8::CpuProfileNode::GetCallUid");
4406 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->call_uid();
4407}
4408
4409
4410int CpuProfileNode::GetChildrenCount() const {
4411 IsDeadCheck("v8::CpuProfileNode::GetChildrenCount");
4412 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
4413}
4414
4415
4416const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
4417 IsDeadCheck("v8::CpuProfileNode::GetChild");
4418 const i::ProfileNode* child =
4419 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
4420 return reinterpret_cast<const CpuProfileNode*>(child);
4421}
4422
4423
4424unsigned CpuProfile::GetUid() const {
4425 IsDeadCheck("v8::CpuProfile::GetUid");
4426 return reinterpret_cast<const i::CpuProfile*>(this)->uid();
4427}
4428
4429
4430Handle<String> CpuProfile::GetTitle() const {
4431 IsDeadCheck("v8::CpuProfile::GetTitle");
4432 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4433 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4434 profile->title())));
4435}
4436
4437
4438const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
4439 IsDeadCheck("v8::CpuProfile::GetBottomUpRoot");
4440 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4441 return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
4442}
4443
4444
4445const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
4446 IsDeadCheck("v8::CpuProfile::GetTopDownRoot");
4447 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4448 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
4449}
4450
4451
4452int CpuProfiler::GetProfilesCount() {
4453 IsDeadCheck("v8::CpuProfiler::GetProfilesCount");
4454 return i::CpuProfiler::GetProfilesCount();
4455}
4456
4457
Leon Clarkef7060e22010-06-03 12:02:55 +01004458const CpuProfile* CpuProfiler::GetProfile(int index,
4459 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004460 IsDeadCheck("v8::CpuProfiler::GetProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004461 return reinterpret_cast<const CpuProfile*>(
4462 i::CpuProfiler::GetProfile(
4463 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4464 index));
Steve Block6ded16b2010-05-10 14:33:55 +01004465}
4466
4467
Leon Clarkef7060e22010-06-03 12:02:55 +01004468const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
4469 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004470 IsDeadCheck("v8::CpuProfiler::FindProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004471 return reinterpret_cast<const CpuProfile*>(
4472 i::CpuProfiler::FindProfile(
4473 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4474 uid));
Steve Block6ded16b2010-05-10 14:33:55 +01004475}
4476
4477
4478void CpuProfiler::StartProfiling(Handle<String> title) {
4479 IsDeadCheck("v8::CpuProfiler::StartProfiling");
4480 i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
4481}
4482
4483
Leon Clarkef7060e22010-06-03 12:02:55 +01004484const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
4485 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004486 IsDeadCheck("v8::CpuProfiler::StopProfiling");
4487 return reinterpret_cast<const CpuProfile*>(
Leon Clarkef7060e22010-06-03 12:02:55 +01004488 i::CpuProfiler::StopProfiling(
4489 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4490 *Utils::OpenHandle(*title)));
Steve Block6ded16b2010-05-10 14:33:55 +01004491}
4492
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004493
4494HeapGraphEdge::Type HeapGraphEdge::GetType() const {
4495 IsDeadCheck("v8::HeapGraphEdge::GetType");
4496 return static_cast<HeapGraphEdge::Type>(
4497 reinterpret_cast<const i::HeapGraphEdge*>(this)->type());
4498}
4499
4500
4501Handle<Value> HeapGraphEdge::GetName() const {
4502 IsDeadCheck("v8::HeapGraphEdge::GetName");
4503 const i::HeapGraphEdge* edge =
4504 reinterpret_cast<const i::HeapGraphEdge*>(this);
4505 switch (edge->type()) {
4506 case i::HeapGraphEdge::CONTEXT_VARIABLE:
4507 case i::HeapGraphEdge::INTERNAL:
4508 case i::HeapGraphEdge::PROPERTY:
4509 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4510 edge->name())));
4511 case i::HeapGraphEdge::ELEMENT:
4512 return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt(
4513 edge->index())));
4514 default: UNREACHABLE();
4515 }
4516 return ImplementationUtilities::Undefined();
4517}
4518
4519
4520const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
4521 IsDeadCheck("v8::HeapGraphEdge::GetFromNode");
4522 const i::HeapEntry* from =
4523 reinterpret_cast<const i::HeapGraphEdge*>(this)->from();
4524 return reinterpret_cast<const HeapGraphNode*>(from);
4525}
4526
4527
4528const HeapGraphNode* HeapGraphEdge::GetToNode() const {
4529 IsDeadCheck("v8::HeapGraphEdge::GetToNode");
4530 const i::HeapEntry* to =
4531 reinterpret_cast<const i::HeapGraphEdge*>(this)->to();
4532 return reinterpret_cast<const HeapGraphNode*>(to);
4533}
4534
4535
4536int HeapGraphPath::GetEdgesCount() const {
4537 return reinterpret_cast<const i::HeapGraphPath*>(this)->path()->length();
4538}
4539
4540
4541const HeapGraphEdge* HeapGraphPath::GetEdge(int index) const {
4542 return reinterpret_cast<const HeapGraphEdge*>(
4543 reinterpret_cast<const i::HeapGraphPath*>(this)->path()->at(index));
4544}
4545
4546
4547const HeapGraphNode* HeapGraphPath::GetFromNode() const {
4548 return GetEdgesCount() > 0 ? GetEdge(0)->GetFromNode() : NULL;
4549}
4550
4551
4552const HeapGraphNode* HeapGraphPath::GetToNode() const {
4553 const int count = GetEdgesCount();
4554 return count > 0 ? GetEdge(count - 1)->GetToNode() : NULL;
4555}
4556
4557
4558HeapGraphNode::Type HeapGraphNode::GetType() const {
4559 IsDeadCheck("v8::HeapGraphNode::GetType");
4560 return static_cast<HeapGraphNode::Type>(
4561 reinterpret_cast<const i::HeapEntry*>(this)->type());
4562}
4563
4564
4565Handle<String> HeapGraphNode::GetName() const {
4566 IsDeadCheck("v8::HeapGraphNode::GetName");
4567 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4568 reinterpret_cast<const i::HeapEntry*>(this)->name())));
4569}
4570
4571
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004572uint64_t HeapGraphNode::GetId() const {
4573 IsDeadCheck("v8::HeapGraphNode::GetId");
4574 return reinterpret_cast<const i::HeapEntry*>(this)->id();
4575}
4576
4577
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004578int HeapGraphNode::GetSelfSize() const {
4579 IsDeadCheck("v8::HeapGraphNode::GetSelfSize");
4580 return reinterpret_cast<const i::HeapEntry*>(this)->self_size();
4581}
4582
4583
4584int HeapGraphNode::GetTotalSize() const {
4585 IsDeadCheck("v8::HeapSnapshot::GetHead");
4586 return const_cast<i::HeapEntry*>(
4587 reinterpret_cast<const i::HeapEntry*>(this))->TotalSize();
4588}
4589
4590
4591int HeapGraphNode::GetPrivateSize() const {
4592 IsDeadCheck("v8::HeapSnapshot::GetPrivateSize");
4593 return const_cast<i::HeapEntry*>(
4594 reinterpret_cast<const i::HeapEntry*>(this))->NonSharedTotalSize();
4595}
4596
4597
4598int HeapGraphNode::GetChildrenCount() const {
4599 IsDeadCheck("v8::HeapSnapshot::GetChildrenCount");
4600 return reinterpret_cast<const i::HeapEntry*>(this)->children()->length();
4601}
4602
4603
4604const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
4605 IsDeadCheck("v8::HeapSnapshot::GetChild");
4606 return reinterpret_cast<const HeapGraphEdge*>(
4607 reinterpret_cast<const i::HeapEntry*>(this)->children()->at(index));
4608}
4609
4610
4611int HeapGraphNode::GetRetainersCount() const {
4612 IsDeadCheck("v8::HeapSnapshot::GetRetainersCount");
4613 return reinterpret_cast<const i::HeapEntry*>(this)->retainers()->length();
4614}
4615
4616
4617const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const {
4618 IsDeadCheck("v8::HeapSnapshot::GetRetainer");
4619 return reinterpret_cast<const HeapGraphEdge*>(
4620 reinterpret_cast<const i::HeapEntry*>(this)->retainers()->at(index));
4621}
4622
4623
4624int HeapGraphNode::GetRetainingPathsCount() const {
4625 IsDeadCheck("v8::HeapSnapshot::GetRetainingPathsCount");
4626 return const_cast<i::HeapEntry*>(
4627 reinterpret_cast<const i::HeapEntry*>(
4628 this))->GetRetainingPaths()->length();
4629}
4630
4631
4632const HeapGraphPath* HeapGraphNode::GetRetainingPath(int index) const {
4633 IsDeadCheck("v8::HeapSnapshot::GetRetainingPath");
4634 return reinterpret_cast<const HeapGraphPath*>(
4635 const_cast<i::HeapEntry*>(
4636 reinterpret_cast<const i::HeapEntry*>(
4637 this))->GetRetainingPaths()->at(index));
4638}
4639
4640
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004641const HeapGraphNode* HeapSnapshotsDiff::GetAdditionsRoot() const {
4642 IsDeadCheck("v8::HeapSnapshotsDiff::GetAdditionsRoot");
4643 const i::HeapSnapshotsDiff* diff =
4644 reinterpret_cast<const i::HeapSnapshotsDiff*>(this);
4645 return reinterpret_cast<const HeapGraphNode*>(diff->additions_root());
4646}
4647
4648
4649const HeapGraphNode* HeapSnapshotsDiff::GetDeletionsRoot() const {
4650 IsDeadCheck("v8::HeapSnapshotsDiff::GetDeletionsRoot");
4651 const i::HeapSnapshotsDiff* diff =
4652 reinterpret_cast<const i::HeapSnapshotsDiff*>(this);
4653 return reinterpret_cast<const HeapGraphNode*>(diff->deletions_root());
4654}
4655
4656
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004657unsigned HeapSnapshot::GetUid() const {
4658 IsDeadCheck("v8::HeapSnapshot::GetUid");
4659 return reinterpret_cast<const i::HeapSnapshot*>(this)->uid();
4660}
4661
4662
4663Handle<String> HeapSnapshot::GetTitle() const {
4664 IsDeadCheck("v8::HeapSnapshot::GetTitle");
4665 const i::HeapSnapshot* snapshot =
4666 reinterpret_cast<const i::HeapSnapshot*>(this);
4667 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4668 snapshot->title())));
4669}
4670
4671
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004672const HeapGraphNode* HeapSnapshot::GetRoot() const {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004673 IsDeadCheck("v8::HeapSnapshot::GetHead");
4674 const i::HeapSnapshot* snapshot =
4675 reinterpret_cast<const i::HeapSnapshot*>(this);
4676 return reinterpret_cast<const HeapGraphNode*>(snapshot->const_root());
4677}
4678
4679
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004680const HeapSnapshotsDiff* HeapSnapshot::CompareWith(
4681 const HeapSnapshot* snapshot) const {
4682 IsDeadCheck("v8::HeapSnapshot::CompareWith");
4683 i::HeapSnapshot* snapshot1 = const_cast<i::HeapSnapshot*>(
4684 reinterpret_cast<const i::HeapSnapshot*>(this));
4685 i::HeapSnapshot* snapshot2 = const_cast<i::HeapSnapshot*>(
4686 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
4687 return reinterpret_cast<const HeapSnapshotsDiff*>(
4688 snapshot1->CompareWith(snapshot2));
4689}
4690
4691
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004692int HeapProfiler::GetSnapshotsCount() {
4693 IsDeadCheck("v8::HeapProfiler::GetSnapshotsCount");
4694 return i::HeapProfiler::GetSnapshotsCount();
4695}
4696
4697
4698const HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
4699 IsDeadCheck("v8::HeapProfiler::GetSnapshot");
4700 return reinterpret_cast<const HeapSnapshot*>(
4701 i::HeapProfiler::GetSnapshot(index));
4702}
4703
4704
4705const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
4706 IsDeadCheck("v8::HeapProfiler::FindSnapshot");
4707 return reinterpret_cast<const HeapSnapshot*>(
4708 i::HeapProfiler::FindSnapshot(uid));
4709}
4710
4711
4712const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title) {
4713 IsDeadCheck("v8::HeapProfiler::TakeSnapshot");
4714 return reinterpret_cast<const HeapSnapshot*>(
4715 i::HeapProfiler::TakeSnapshot(*Utils::OpenHandle(*title)));
4716}
4717
Steve Block6ded16b2010-05-10 14:33:55 +01004718#endif // ENABLE_LOGGING_AND_PROFILING
4719
4720
Steve Blocka7e24c12009-10-30 11:49:00 +00004721namespace internal {
4722
4723
4724HandleScopeImplementer* HandleScopeImplementer::instance() {
4725 return &thread_local;
4726}
4727
4728
4729void HandleScopeImplementer::FreeThreadResources() {
4730 thread_local.Free();
4731}
4732
4733
4734char* HandleScopeImplementer::ArchiveThread(char* storage) {
4735 return thread_local.ArchiveThreadHelper(storage);
4736}
4737
4738
4739char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
4740 v8::ImplementationUtilities::HandleScopeData* current =
4741 v8::ImplementationUtilities::CurrentHandleScope();
4742 handle_scope_data_ = *current;
4743 memcpy(storage, this, sizeof(*this));
4744
4745 ResetAfterArchive();
4746 current->Initialize();
4747
4748 return storage + ArchiveSpacePerThread();
4749}
4750
4751
4752int HandleScopeImplementer::ArchiveSpacePerThread() {
4753 return sizeof(thread_local);
4754}
4755
4756
4757char* HandleScopeImplementer::RestoreThread(char* storage) {
4758 return thread_local.RestoreThreadHelper(storage);
4759}
4760
4761
4762char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
4763 memcpy(this, storage, sizeof(*this));
4764 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
4765 return storage + ArchiveSpacePerThread();
4766}
4767
4768
4769void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
4770 // Iterate over all handles in the blocks except for the last.
4771 for (int i = blocks()->length() - 2; i >= 0; --i) {
4772 Object** block = blocks()->at(i);
4773 v->VisitPointers(block, &block[kHandleBlockSize]);
4774 }
4775
4776 // Iterate over live handles in the last block (if any).
4777 if (!blocks()->is_empty()) {
4778 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
4779 }
4780
4781 if (!saved_contexts_.is_empty()) {
4782 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
4783 v->VisitPointers(start, start + saved_contexts_.length());
4784 }
4785}
4786
4787
4788void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
4789 v8::ImplementationUtilities::HandleScopeData* current =
4790 v8::ImplementationUtilities::CurrentHandleScope();
4791 thread_local.handle_scope_data_ = *current;
4792 thread_local.IterateThis(v);
4793}
4794
4795
4796char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
4797 HandleScopeImplementer* thread_local =
4798 reinterpret_cast<HandleScopeImplementer*>(storage);
4799 thread_local->IterateThis(v);
4800 return storage + ArchiveSpacePerThread();
4801}
4802
4803} } // namespace v8::internal