blob: 5f480c9073fac29c43ed90b0e7f84f01ea155ad8 [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;
Iain Merrick75681382010-08-19 15:07:18 +0100177 int os_error;
178 heap_stats.os_error = &os_error;
Steve Blockd0582a62009-12-15 09:54:21 +0000179 int end_marker;
180 heap_stats.end_marker = &end_marker;
Ben Murdochbb769b22010-08-11 14:56:33 +0100181 i::Heap::RecordStats(&heap_stats, take_snapshot);
Steve Blocka7e24c12009-10-30 11:49:00 +0000182 i::V8::SetFatalError();
183 FatalErrorCallback callback = GetFatalErrorHandler();
184 {
185 LEAVE_V8;
186 callback(location, "Allocation failed - process out of memory");
187 }
188 // If the callback returns, we stop execution.
189 UNREACHABLE();
190}
191
192
193void V8::SetFatalErrorHandler(FatalErrorCallback that) {
194 exception_behavior = that;
195}
196
197
198bool Utils::ReportApiFailure(const char* location, const char* message) {
199 FatalErrorCallback callback = GetFatalErrorHandler();
200 callback(location, message);
201 i::V8::SetFatalError();
202 return false;
203}
204
205
206bool V8::IsDead() {
207 return i::V8::IsDead();
208}
209
210
211static inline bool ApiCheck(bool condition,
212 const char* location,
213 const char* message) {
214 return condition ? true : Utils::ReportApiFailure(location, message);
215}
216
217
218static bool ReportV8Dead(const char* location) {
219 FatalErrorCallback callback = GetFatalErrorHandler();
220 callback(location, "V8 is no longer usable");
221 return true;
222}
223
224
225static bool ReportEmptyHandle(const char* location) {
226 FatalErrorCallback callback = GetFatalErrorHandler();
227 callback(location, "Reading from empty handle");
228 return true;
229}
230
231
232/**
233 * IsDeadCheck checks that the vm is usable. If, for instance, the vm has been
234 * out of memory at some point this check will fail. It should be called on
235 * entry to all methods that touch anything in the heap, except destructors
236 * which you sometimes can't avoid calling after the vm has crashed. Functions
237 * that call EnsureInitialized or ON_BAILOUT don't have to also call
238 * IsDeadCheck. ON_BAILOUT has the advantage over EnsureInitialized that you
239 * can arrange to return if the VM is dead. This is needed to ensure that no VM
240 * heap allocations are attempted on a dead VM. EnsureInitialized has the
241 * advantage over ON_BAILOUT that it actually initializes the VM if this has not
242 * yet been done.
243 */
244static inline bool IsDeadCheck(const char* location) {
245 return !i::V8::IsRunning()
246 && i::V8::IsDead() ? ReportV8Dead(location) : false;
247}
248
249
250static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
251 return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
252}
253
254
255static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
256 return (obj == 0) ? ReportEmptyHandle(location) : false;
257}
258
259// --- S t a t i c s ---
260
261
262static i::StringInputBuffer write_input_buffer;
263
264
265static inline bool EnsureInitialized(const char* location) {
266 if (i::V8::IsRunning()) {
267 return true;
268 }
269 if (IsDeadCheck(location)) {
270 return false;
271 }
272 return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
273}
274
275
276ImplementationUtilities::HandleScopeData*
277 ImplementationUtilities::CurrentHandleScope() {
278 return &i::HandleScope::current_;
279}
280
281
282#ifdef DEBUG
283void ImplementationUtilities::ZapHandleRange(i::Object** begin,
284 i::Object** end) {
285 i::HandleScope::ZapRange(begin, end);
286}
287#endif
288
289
290v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
291 if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
292 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
293}
294
295
296v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
297 if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
298 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
299}
300
301
302v8::Handle<v8::Boolean> ImplementationUtilities::True() {
303 if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
304 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
305}
306
307
308v8::Handle<v8::Boolean> ImplementationUtilities::False() {
309 if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
310 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
311}
312
313
314void V8::SetFlagsFromString(const char* str, int length) {
315 i::FlagList::SetFlagsFromString(str, length);
316}
317
318
319void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
320 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
321}
322
323
324v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
325 if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
326 ENTER_V8;
327 // If we're passed an empty handle, we throw an undefined exception
328 // to deal more gracefully with out of memory situations.
329 if (value.IsEmpty()) {
330 i::Top::ScheduleThrow(i::Heap::undefined_value());
331 } else {
332 i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
333 }
334 return v8::Undefined();
335}
336
337
338RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
339
340
341RegisteredExtension::RegisteredExtension(Extension* extension)
342 : extension_(extension), state_(UNVISITED) { }
343
344
345void RegisteredExtension::Register(RegisteredExtension* that) {
346 that->next_ = RegisteredExtension::first_extension_;
347 RegisteredExtension::first_extension_ = that;
348}
349
350
351void RegisterExtension(Extension* that) {
352 RegisteredExtension* extension = new RegisteredExtension(that);
353 RegisteredExtension::Register(extension);
354}
355
356
357Extension::Extension(const char* name,
358 const char* source,
359 int dep_count,
360 const char** deps)
361 : name_(name),
362 source_(source),
363 dep_count_(dep_count),
364 deps_(deps),
365 auto_enable_(false) { }
366
367
368v8::Handle<Primitive> Undefined() {
369 LOG_API("Undefined");
370 return ImplementationUtilities::Undefined();
371}
372
373
374v8::Handle<Primitive> Null() {
375 LOG_API("Null");
376 return ImplementationUtilities::Null();
377}
378
379
380v8::Handle<Boolean> True() {
381 LOG_API("True");
382 return ImplementationUtilities::True();
383}
384
385
386v8::Handle<Boolean> False() {
387 LOG_API("False");
388 return ImplementationUtilities::False();
389}
390
391
392ResourceConstraints::ResourceConstraints()
393 : max_young_space_size_(0),
394 max_old_space_size_(0),
395 stack_limit_(NULL) { }
396
397
398bool SetResourceConstraints(ResourceConstraints* constraints) {
Steve Block3ce2e202009-11-05 08:53:23 +0000399 int young_space_size = constraints->max_young_space_size();
Steve Blocka7e24c12009-10-30 11:49:00 +0000400 int old_gen_size = constraints->max_old_space_size();
Steve Block3ce2e202009-11-05 08:53:23 +0000401 if (young_space_size != 0 || old_gen_size != 0) {
402 bool result = i::Heap::ConfigureHeap(young_space_size / 2, old_gen_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000403 if (!result) return false;
404 }
405 if (constraints->stack_limit() != NULL) {
406 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
407 i::StackGuard::SetStackLimit(limit);
408 }
409 return true;
410}
411
412
413i::Object** V8::GlobalizeReference(i::Object** obj) {
414 if (IsDeadCheck("V8::Persistent::New")) return NULL;
415 LOG_API("Persistent::New");
416 i::Handle<i::Object> result =
417 i::GlobalHandles::Create(*obj);
418 return result.location();
419}
420
421
422void V8::MakeWeak(i::Object** object, void* parameters,
423 WeakReferenceCallback callback) {
424 LOG_API("MakeWeak");
425 i::GlobalHandles::MakeWeak(object, parameters, callback);
426}
427
428
429void V8::ClearWeak(i::Object** obj) {
430 LOG_API("ClearWeak");
431 i::GlobalHandles::ClearWeakness(obj);
432}
433
434
435bool V8::IsGlobalNearDeath(i::Object** obj) {
436 LOG_API("IsGlobalNearDeath");
437 if (!i::V8::IsRunning()) return false;
438 return i::GlobalHandles::IsNearDeath(obj);
439}
440
441
442bool V8::IsGlobalWeak(i::Object** obj) {
443 LOG_API("IsGlobalWeak");
444 if (!i::V8::IsRunning()) return false;
445 return i::GlobalHandles::IsWeak(obj);
446}
447
448
449void V8::DisposeGlobal(i::Object** obj) {
450 LOG_API("DisposeGlobal");
451 if (!i::V8::IsRunning()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 i::GlobalHandles::Destroy(obj);
453}
454
455// --- H a n d l e s ---
456
457
458HandleScope::HandleScope() : is_closed_(false) {
459 API_ENTRY_CHECK("HandleScope::HandleScope");
460 i::HandleScope::Enter(&previous_);
461}
462
463
464HandleScope::~HandleScope() {
465 if (!is_closed_) {
466 i::HandleScope::Leave(&previous_);
467 }
468}
469
470
471int HandleScope::NumberOfHandles() {
472 return i::HandleScope::NumberOfHandles();
473}
474
475
476i::Object** v8::HandleScope::CreateHandle(i::Object* value) {
477 return i::HandleScope::CreateHandle(value);
478}
479
480
481void Context::Enter() {
482 if (IsDeadCheck("v8::Context::Enter()")) return;
483 ENTER_V8;
484 i::Handle<i::Context> env = Utils::OpenHandle(this);
485 thread_local.EnterContext(env);
486
487 thread_local.SaveContext(i::Top::context());
488 i::Top::set_context(*env);
489}
490
491
492void Context::Exit() {
493 if (!i::V8::IsRunning()) return;
494 if (!ApiCheck(thread_local.LeaveLastContext(),
495 "v8::Context::Exit()",
496 "Cannot exit non-entered context")) {
497 return;
498 }
499
500 // Content of 'last_context' could be NULL.
501 i::Context* last_context = thread_local.RestoreContext();
502 i::Top::set_context(last_context);
503}
504
505
Steve Blockd0582a62009-12-15 09:54:21 +0000506void Context::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000507 if (IsDeadCheck("v8::Context::SetData()")) return;
508 ENTER_V8;
509 {
510 HandleScope scope;
511 i::Handle<i::Context> env = Utils::OpenHandle(this);
512 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
513 ASSERT(env->IsGlobalContext());
514 if (env->IsGlobalContext()) {
515 env->set_data(*raw_data);
516 }
517 }
518}
519
520
521v8::Local<v8::Value> Context::GetData() {
522 if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
523 ENTER_V8;
524 i::Object* raw_result = NULL;
525 {
526 HandleScope scope;
527 i::Handle<i::Context> env = Utils::OpenHandle(this);
528 ASSERT(env->IsGlobalContext());
529 if (env->IsGlobalContext()) {
530 raw_result = env->data();
531 } else {
532 return Local<Value>();
533 }
534 }
535 i::Handle<i::Object> result(raw_result);
536 return Utils::ToLocal(result);
537}
538
539
540i::Object** v8::HandleScope::RawClose(i::Object** value) {
541 if (!ApiCheck(!is_closed_,
542 "v8::HandleScope::Close()",
543 "Local scope has already been closed")) {
544 return 0;
545 }
546 LOG_API("CloseHandleScope");
547
548 // Read the result before popping the handle block.
Steve Block6ded16b2010-05-10 14:33:55 +0100549 i::Object* result = NULL;
550 if (value != NULL) {
551 result = *value;
552 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000553 is_closed_ = true;
554 i::HandleScope::Leave(&previous_);
555
Steve Block6ded16b2010-05-10 14:33:55 +0100556 if (value == NULL) {
557 return NULL;
558 }
559
Steve Blocka7e24c12009-10-30 11:49:00 +0000560 // Allocate a new handle on the previous handle block.
561 i::Handle<i::Object> handle(result);
562 return handle.location();
563}
564
565
566// --- N e a n d e r ---
567
568
569// A constructor cannot easily return an error value, therefore it is necessary
570// to check for a dead VM with ON_BAILOUT before constructing any Neander
571// objects. To remind you about this there is no HandleScope in the
572// NeanderObject constructor. When you add one to the site calling the
573// constructor you should check that you ensured the VM was not dead first.
574NeanderObject::NeanderObject(int size) {
575 EnsureInitialized("v8::Nowhere");
576 ENTER_V8;
577 value_ = i::Factory::NewNeanderObject();
578 i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
579 value_->set_elements(*elements);
580}
581
582
583int NeanderObject::size() {
584 return i::FixedArray::cast(value_->elements())->length();
585}
586
587
588NeanderArray::NeanderArray() : obj_(2) {
589 obj_.set(0, i::Smi::FromInt(0));
590}
591
592
593int NeanderArray::length() {
594 return i::Smi::cast(obj_.get(0))->value();
595}
596
597
598i::Object* NeanderArray::get(int offset) {
599 ASSERT(0 <= offset);
600 ASSERT(offset < length());
601 return obj_.get(offset + 1);
602}
603
604
605// This method cannot easily return an error value, therefore it is necessary
606// to check for a dead VM with ON_BAILOUT before calling it. To remind you
607// about this there is no HandleScope in this method. When you add one to the
608// site calling this method you should check that you ensured the VM was not
609// dead first.
610void NeanderArray::add(i::Handle<i::Object> value) {
611 int length = this->length();
612 int size = obj_.size();
613 if (length == size - 1) {
614 i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
615 for (int i = 0; i < length; i++)
616 new_elms->set(i + 1, get(i));
617 obj_.value()->set_elements(*new_elms);
618 }
619 obj_.set(length + 1, *value);
620 obj_.set(0, i::Smi::FromInt(length + 1));
621}
622
623
624void NeanderArray::set(int index, i::Object* value) {
625 if (index < 0 || index >= this->length()) return;
626 obj_.set(index + 1, value);
627}
628
629
630// --- T e m p l a t e ---
631
632
633static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
634 that->set_tag(i::Smi::FromInt(type));
635}
636
637
638void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
639 v8::PropertyAttribute attribute) {
640 if (IsDeadCheck("v8::Template::SetProperty()")) return;
641 ENTER_V8;
642 HandleScope scope;
643 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
644 if (list->IsUndefined()) {
645 list = NeanderArray().value();
646 Utils::OpenHandle(this)->set_property_list(*list);
647 }
648 NeanderArray array(list);
649 array.add(Utils::OpenHandle(*name));
650 array.add(Utils::OpenHandle(*value));
651 array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
652}
653
654
655// --- F u n c t i o n T e m p l a t e ---
656static void InitializeFunctionTemplate(
657 i::Handle<i::FunctionTemplateInfo> info) {
658 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
659 info->set_flag(0);
660}
661
662
663Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
664 if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
665 return Local<ObjectTemplate>();
666 }
667 ENTER_V8;
668 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
669 if (result->IsUndefined()) {
670 result = Utils::OpenHandle(*ObjectTemplate::New());
671 Utils::OpenHandle(this)->set_prototype_template(*result);
672 }
673 return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
674}
675
676
677void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
678 if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
679 ENTER_V8;
680 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
681}
682
683
684// To distinguish the function templates, so that we can find them in the
685// function cache of the global context.
686static int next_serial_number = 0;
687
688
689Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
690 v8::Handle<Value> data, v8::Handle<Signature> signature) {
691 EnsureInitialized("v8::FunctionTemplate::New()");
692 LOG_API("FunctionTemplate::New");
693 ENTER_V8;
694 i::Handle<i::Struct> struct_obj =
695 i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
696 i::Handle<i::FunctionTemplateInfo> obj =
697 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
698 InitializeFunctionTemplate(obj);
699 obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
700 if (callback != 0) {
701 if (data.IsEmpty()) data = v8::Undefined();
702 Utils::ToLocal(obj)->SetCallHandler(callback, data);
703 }
704 obj->set_undetectable(false);
705 obj->set_needs_access_check(false);
706
707 if (!signature.IsEmpty())
708 obj->set_signature(*Utils::OpenHandle(*signature));
709 return Utils::ToLocal(obj);
710}
711
712
713Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
714 int argc, Handle<FunctionTemplate> argv[]) {
715 EnsureInitialized("v8::Signature::New()");
716 LOG_API("Signature::New");
717 ENTER_V8;
718 i::Handle<i::Struct> struct_obj =
719 i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
720 i::Handle<i::SignatureInfo> obj =
721 i::Handle<i::SignatureInfo>::cast(struct_obj);
722 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
723 if (argc > 0) {
724 i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
725 for (int i = 0; i < argc; i++) {
726 if (!argv[i].IsEmpty())
727 args->set(i, *Utils::OpenHandle(*argv[i]));
728 }
729 obj->set_args(*args);
730 }
731 return Utils::ToLocal(obj);
732}
733
734
735Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
736 Handle<FunctionTemplate> types[1] = { type };
737 return TypeSwitch::New(1, types);
738}
739
740
741Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
742 EnsureInitialized("v8::TypeSwitch::New()");
743 LOG_API("TypeSwitch::New");
744 ENTER_V8;
745 i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
746 for (int i = 0; i < argc; i++)
747 vector->set(i, *Utils::OpenHandle(*types[i]));
748 i::Handle<i::Struct> struct_obj =
749 i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
750 i::Handle<i::TypeSwitchInfo> obj =
751 i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
752 obj->set_types(*vector);
753 return Utils::ToLocal(obj);
754}
755
756
757int TypeSwitch::match(v8::Handle<Value> value) {
758 LOG_API("TypeSwitch::match");
759 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
760 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
761 i::FixedArray* types = i::FixedArray::cast(info->types());
762 for (int i = 0; i < types->length(); i++) {
763 if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
764 return i + 1;
765 }
766 return 0;
767}
768
769
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100770#define SET_FIELD_WRAPPED(obj, setter, cdata) do { \
771 i::Handle<i::Object> proxy = FromCData(cdata); \
772 (obj)->setter(*proxy); \
773 } while (false)
774
775
Steve Blocka7e24c12009-10-30 11:49:00 +0000776void FunctionTemplate::SetCallHandler(InvocationCallback callback,
777 v8::Handle<Value> data) {
778 if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
779 ENTER_V8;
780 HandleScope scope;
781 i::Handle<i::Struct> struct_obj =
782 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
783 i::Handle<i::CallHandlerInfo> obj =
784 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100785 SET_FIELD_WRAPPED(obj, set_callback, callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000786 if (data.IsEmpty()) data = v8::Undefined();
787 obj->set_data(*Utils::OpenHandle(*data));
788 Utils::OpenHandle(this)->set_call_code(*obj);
789}
790
791
Leon Clarkef7060e22010-06-03 12:02:55 +0100792static i::Handle<i::AccessorInfo> MakeAccessorInfo(
793 v8::Handle<String> name,
794 AccessorGetter getter,
795 AccessorSetter setter,
796 v8::Handle<Value> data,
797 v8::AccessControl settings,
798 v8::PropertyAttribute attributes) {
799 i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
800 ASSERT(getter != NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100801 SET_FIELD_WRAPPED(obj, set_getter, getter);
802 SET_FIELD_WRAPPED(obj, set_setter, setter);
Leon Clarkef7060e22010-06-03 12:02:55 +0100803 if (data.IsEmpty()) data = v8::Undefined();
804 obj->set_data(*Utils::OpenHandle(*data));
805 obj->set_name(*Utils::OpenHandle(*name));
806 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
807 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
808 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
809 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
810 return obj;
811}
812
813
Steve Blocka7e24c12009-10-30 11:49:00 +0000814void FunctionTemplate::AddInstancePropertyAccessor(
815 v8::Handle<String> name,
816 AccessorGetter getter,
817 AccessorSetter setter,
818 v8::Handle<Value> data,
819 v8::AccessControl settings,
820 v8::PropertyAttribute attributes) {
821 if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
822 return;
823 }
824 ENTER_V8;
825 HandleScope scope;
Steve Blocka7e24c12009-10-30 11:49:00 +0000826
Leon Clarkef7060e22010-06-03 12:02:55 +0100827 i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name,
828 getter, setter, data,
829 settings, attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000830 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
831 if (list->IsUndefined()) {
832 list = NeanderArray().value();
833 Utils::OpenHandle(this)->set_property_accessors(*list);
834 }
835 NeanderArray array(list);
836 array.add(obj);
837}
838
839
840Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
841 if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
842 || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
843 return Local<ObjectTemplate>();
844 ENTER_V8;
845 if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
846 Local<ObjectTemplate> templ =
847 ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
848 Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
849 }
850 i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
851 Utils::OpenHandle(this)->instance_template()));
852 return Utils::ToLocal(result);
853}
854
855
856void FunctionTemplate::SetClassName(Handle<String> name) {
857 if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
858 ENTER_V8;
859 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
860}
861
862
863void FunctionTemplate::SetHiddenPrototype(bool value) {
864 if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
865 ENTER_V8;
866 Utils::OpenHandle(this)->set_hidden_prototype(value);
867}
868
869
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100870void FunctionTemplate::SetNamedInstancePropertyHandler(
Steve Blocka7e24c12009-10-30 11:49:00 +0000871 NamedPropertyGetter getter,
872 NamedPropertySetter setter,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100873 NamedPropertyQuery query,
Steve Blocka7e24c12009-10-30 11:49:00 +0000874 NamedPropertyDeleter remover,
875 NamedPropertyEnumerator enumerator,
876 Handle<Value> data) {
877 if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
878 return;
879 }
880 ENTER_V8;
881 HandleScope scope;
882 i::Handle<i::Struct> struct_obj =
883 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
884 i::Handle<i::InterceptorInfo> obj =
885 i::Handle<i::InterceptorInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100886
887 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
888 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
889 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
890 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
891 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
892
Steve Blocka7e24c12009-10-30 11:49:00 +0000893 if (data.IsEmpty()) data = v8::Undefined();
894 obj->set_data(*Utils::OpenHandle(*data));
895 Utils::OpenHandle(this)->set_named_property_handler(*obj);
896}
897
898
899void FunctionTemplate::SetIndexedInstancePropertyHandler(
900 IndexedPropertyGetter getter,
901 IndexedPropertySetter setter,
902 IndexedPropertyQuery query,
903 IndexedPropertyDeleter remover,
904 IndexedPropertyEnumerator enumerator,
905 Handle<Value> data) {
906 if (IsDeadCheck(
907 "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
908 return;
909 }
910 ENTER_V8;
911 HandleScope scope;
912 i::Handle<i::Struct> struct_obj =
913 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
914 i::Handle<i::InterceptorInfo> obj =
915 i::Handle<i::InterceptorInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100916
917 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
918 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
919 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
920 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
921 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
922
Steve Blocka7e24c12009-10-30 11:49:00 +0000923 if (data.IsEmpty()) data = v8::Undefined();
924 obj->set_data(*Utils::OpenHandle(*data));
925 Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
926}
927
928
929void FunctionTemplate::SetInstanceCallAsFunctionHandler(
930 InvocationCallback callback,
931 Handle<Value> data) {
932 if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
933 return;
934 }
935 ENTER_V8;
936 HandleScope scope;
937 i::Handle<i::Struct> struct_obj =
938 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
939 i::Handle<i::CallHandlerInfo> obj =
940 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100941 SET_FIELD_WRAPPED(obj, set_callback, callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000942 if (data.IsEmpty()) data = v8::Undefined();
943 obj->set_data(*Utils::OpenHandle(*data));
944 Utils::OpenHandle(this)->set_instance_call_handler(*obj);
945}
946
947
948// --- O b j e c t T e m p l a t e ---
949
950
951Local<ObjectTemplate> ObjectTemplate::New() {
952 return New(Local<FunctionTemplate>());
953}
954
955
956Local<ObjectTemplate> ObjectTemplate::New(
957 v8::Handle<FunctionTemplate> constructor) {
958 if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
959 EnsureInitialized("v8::ObjectTemplate::New()");
960 LOG_API("ObjectTemplate::New");
961 ENTER_V8;
962 i::Handle<i::Struct> struct_obj =
963 i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
964 i::Handle<i::ObjectTemplateInfo> obj =
965 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
966 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
967 if (!constructor.IsEmpty())
968 obj->set_constructor(*Utils::OpenHandle(*constructor));
969 obj->set_internal_field_count(i::Smi::FromInt(0));
970 return Utils::ToLocal(obj);
971}
972
973
974// Ensure that the object template has a constructor. If no
975// constructor is available we create one.
976static void EnsureConstructor(ObjectTemplate* object_template) {
977 if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
978 Local<FunctionTemplate> templ = FunctionTemplate::New();
979 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
980 constructor->set_instance_template(*Utils::OpenHandle(object_template));
981 Utils::OpenHandle(object_template)->set_constructor(*constructor);
982 }
983}
984
985
986void ObjectTemplate::SetAccessor(v8::Handle<String> name,
987 AccessorGetter getter,
988 AccessorSetter setter,
989 v8::Handle<Value> data,
990 AccessControl settings,
991 PropertyAttribute attribute) {
992 if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
993 ENTER_V8;
994 HandleScope scope;
995 EnsureConstructor(this);
996 i::FunctionTemplateInfo* constructor =
997 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
998 i::Handle<i::FunctionTemplateInfo> cons(constructor);
999 Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
1000 getter,
1001 setter,
1002 data,
1003 settings,
1004 attribute);
1005}
1006
1007
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001008void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
1009 NamedPropertySetter setter,
1010 NamedPropertyQuery query,
1011 NamedPropertyDeleter remover,
1012 NamedPropertyEnumerator enumerator,
1013 Handle<Value> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001014 if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
1015 ENTER_V8;
1016 HandleScope scope;
1017 EnsureConstructor(this);
1018 i::FunctionTemplateInfo* constructor =
1019 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1020 i::Handle<i::FunctionTemplateInfo> cons(constructor);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001021 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
1022 setter,
1023 query,
1024 remover,
1025 enumerator,
1026 data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001027}
1028
1029
1030void ObjectTemplate::MarkAsUndetectable() {
1031 if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
1032 ENTER_V8;
1033 HandleScope scope;
1034 EnsureConstructor(this);
1035 i::FunctionTemplateInfo* constructor =
1036 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1037 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1038 cons->set_undetectable(true);
1039}
1040
1041
1042void ObjectTemplate::SetAccessCheckCallbacks(
1043 NamedSecurityCallback named_callback,
1044 IndexedSecurityCallback indexed_callback,
1045 Handle<Value> data,
1046 bool turned_on_by_default) {
1047 if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
1048 ENTER_V8;
1049 HandleScope scope;
1050 EnsureConstructor(this);
1051
1052 i::Handle<i::Struct> struct_info =
1053 i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1054 i::Handle<i::AccessCheckInfo> info =
1055 i::Handle<i::AccessCheckInfo>::cast(struct_info);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001056
1057 SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
1058 SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
1059
Steve Blocka7e24c12009-10-30 11:49:00 +00001060 if (data.IsEmpty()) data = v8::Undefined();
1061 info->set_data(*Utils::OpenHandle(*data));
1062
1063 i::FunctionTemplateInfo* constructor =
1064 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1065 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1066 cons->set_access_check_info(*info);
1067 cons->set_needs_access_check(turned_on_by_default);
1068}
1069
1070
1071void ObjectTemplate::SetIndexedPropertyHandler(
1072 IndexedPropertyGetter getter,
1073 IndexedPropertySetter setter,
1074 IndexedPropertyQuery query,
1075 IndexedPropertyDeleter remover,
1076 IndexedPropertyEnumerator enumerator,
1077 Handle<Value> data) {
1078 if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
1079 ENTER_V8;
1080 HandleScope scope;
1081 EnsureConstructor(this);
1082 i::FunctionTemplateInfo* constructor =
1083 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1084 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1085 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
1086 setter,
1087 query,
1088 remover,
1089 enumerator,
1090 data);
1091}
1092
1093
1094void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1095 Handle<Value> data) {
1096 if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
1097 ENTER_V8;
1098 HandleScope scope;
1099 EnsureConstructor(this);
1100 i::FunctionTemplateInfo* constructor =
1101 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1102 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1103 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1104}
1105
1106
1107int ObjectTemplate::InternalFieldCount() {
1108 if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
1109 return 0;
1110 }
1111 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1112}
1113
1114
1115void ObjectTemplate::SetInternalFieldCount(int value) {
1116 if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
1117 if (!ApiCheck(i::Smi::IsValid(value),
1118 "v8::ObjectTemplate::SetInternalFieldCount()",
1119 "Invalid internal field count")) {
1120 return;
1121 }
1122 ENTER_V8;
1123 if (value > 0) {
1124 // The internal field count is set by the constructor function's
1125 // construct code, so we ensure that there is a constructor
1126 // function to do the setting.
1127 EnsureConstructor(this);
1128 }
1129 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1130}
1131
1132
1133// --- S c r i p t D a t a ---
1134
1135
1136ScriptData* ScriptData::PreCompile(const char* input, int length) {
1137 unibrow::Utf8InputBuffer<> buf(input, length);
1138 return i::PreParse(i::Handle<i::String>(), &buf, NULL);
1139}
1140
1141
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001142ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
1143 i::Handle<i::String> str = Utils::OpenHandle(*source);
1144 return i::PreParse(str, NULL, NULL);
1145}
1146
1147
Leon Clarkef7060e22010-06-03 12:02:55 +01001148ScriptData* ScriptData::New(const char* data, int length) {
1149 // Return an empty ScriptData if the length is obviously invalid.
1150 if (length % sizeof(unsigned) != 0) {
Iain Merrick9ac36c92010-09-13 15:29:50 +01001151 return new i::ScriptDataImpl();
Leon Clarkef7060e22010-06-03 12:02:55 +01001152 }
1153
1154 // Copy the data to ensure it is properly aligned.
1155 int deserialized_data_length = length / sizeof(unsigned);
Iain Merrick9ac36c92010-09-13 15:29:50 +01001156 // If aligned, don't create a copy of the data.
1157 if (reinterpret_cast<intptr_t>(data) % sizeof(unsigned) == 0) {
1158 return new i::ScriptDataImpl(data, length);
1159 }
1160 // Copy the data to align it.
Leon Clarkef7060e22010-06-03 12:02:55 +01001161 unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
Iain Merrick9ac36c92010-09-13 15:29:50 +01001162 i::MemCopy(deserialized_data, data, length);
Leon Clarkef7060e22010-06-03 12:02:55 +01001163
1164 return new i::ScriptDataImpl(
1165 i::Vector<unsigned>(deserialized_data, deserialized_data_length));
Steve Blocka7e24c12009-10-30 11:49:00 +00001166}
1167
1168
1169// --- S c r i p t ---
1170
1171
1172Local<Script> Script::New(v8::Handle<String> source,
1173 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001174 v8::ScriptData* pre_data,
1175 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001176 ON_BAILOUT("v8::Script::New()", return Local<Script>());
1177 LOG_API("Script::New");
1178 ENTER_V8;
1179 i::Handle<i::String> str = Utils::OpenHandle(*source);
1180 i::Handle<i::Object> name_obj;
1181 int line_offset = 0;
1182 int column_offset = 0;
1183 if (origin != NULL) {
1184 if (!origin->ResourceName().IsEmpty()) {
1185 name_obj = Utils::OpenHandle(*origin->ResourceName());
1186 }
1187 if (!origin->ResourceLineOffset().IsEmpty()) {
1188 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1189 }
1190 if (!origin->ResourceColumnOffset().IsEmpty()) {
1191 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1192 }
1193 }
1194 EXCEPTION_PREAMBLE();
Andrei Popescu402d9372010-02-26 13:31:12 +00001195 i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001196 // We assert that the pre-data is sane, even though we can actually
1197 // handle it if it turns out not to be in release mode.
Andrei Popescu402d9372010-02-26 13:31:12 +00001198 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
Steve Blocka7e24c12009-10-30 11:49:00 +00001199 // If the pre-data isn't sane we simply ignore it
Andrei Popescu402d9372010-02-26 13:31:12 +00001200 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
1201 pre_data_impl = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001202 }
Steve Block6ded16b2010-05-10 14:33:55 +01001203 i::Handle<i::SharedFunctionInfo> result =
Andrei Popescu31002712010-02-23 13:46:05 +00001204 i::Compiler::Compile(str,
1205 name_obj,
1206 line_offset,
1207 column_offset,
1208 NULL,
Andrei Popescu402d9372010-02-26 13:31:12 +00001209 pre_data_impl,
1210 Utils::OpenHandle(*script_data),
Andrei Popescu31002712010-02-23 13:46:05 +00001211 i::NOT_NATIVES_CODE);
Steve Block6ded16b2010-05-10 14:33:55 +01001212 has_pending_exception = result.is_null();
Steve Blocka7e24c12009-10-30 11:49:00 +00001213 EXCEPTION_BAILOUT_CHECK(Local<Script>());
Steve Block6ded16b2010-05-10 14:33:55 +01001214 return Local<Script>(ToApi<Script>(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00001215}
1216
1217
1218Local<Script> Script::New(v8::Handle<String> source,
1219 v8::Handle<Value> file_name) {
1220 ScriptOrigin origin(file_name);
1221 return New(source, &origin);
1222}
1223
1224
1225Local<Script> Script::Compile(v8::Handle<String> source,
1226 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001227 v8::ScriptData* pre_data,
1228 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001229 ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1230 LOG_API("Script::Compile");
1231 ENTER_V8;
Andrei Popescu402d9372010-02-26 13:31:12 +00001232 Local<Script> generic = New(source, origin, pre_data, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001233 if (generic.IsEmpty())
1234 return generic;
Steve Block6ded16b2010-05-10 14:33:55 +01001235 i::Handle<i::Object> obj = Utils::OpenHandle(*generic);
1236 i::Handle<i::SharedFunctionInfo> function =
1237 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001238 i::Handle<i::JSFunction> result =
Steve Block6ded16b2010-05-10 14:33:55 +01001239 i::Factory::NewFunctionFromSharedFunctionInfo(function,
1240 i::Top::global_context());
Steve Blocka7e24c12009-10-30 11:49:00 +00001241 return Local<Script>(ToApi<Script>(result));
1242}
1243
1244
1245Local<Script> Script::Compile(v8::Handle<String> source,
Andrei Popescu402d9372010-02-26 13:31:12 +00001246 v8::Handle<Value> file_name,
1247 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001248 ScriptOrigin origin(file_name);
Andrei Popescu402d9372010-02-26 13:31:12 +00001249 return Compile(source, &origin, 0, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001250}
1251
1252
1253Local<Value> Script::Run() {
1254 ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1255 LOG_API("Script::Run");
1256 ENTER_V8;
1257 i::Object* raw_result = NULL;
1258 {
1259 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001260 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1261 i::Handle<i::JSFunction> fun;
1262 if (obj->IsSharedFunctionInfo()) {
1263 i::Handle<i::SharedFunctionInfo>
1264 function_info(i::SharedFunctionInfo::cast(*obj));
1265 fun = i::Factory::NewFunctionFromSharedFunctionInfo(
1266 function_info, i::Top::global_context());
1267 } else {
1268 fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001269 }
1270 EXCEPTION_PREAMBLE();
1271 i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
1272 i::Handle<i::Object> result =
1273 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
1274 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1275 raw_result = *result;
1276 }
1277 i::Handle<i::Object> result(raw_result);
1278 return Utils::ToLocal(result);
1279}
1280
1281
Steve Block6ded16b2010-05-10 14:33:55 +01001282static i::Handle<i::SharedFunctionInfo> OpenScript(Script* script) {
1283 i::Handle<i::Object> obj = Utils::OpenHandle(script);
1284 i::Handle<i::SharedFunctionInfo> result;
1285 if (obj->IsSharedFunctionInfo()) {
1286 result =
1287 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
1288 } else {
1289 result =
1290 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared());
1291 }
1292 return result;
1293}
1294
1295
Steve Blocka7e24c12009-10-30 11:49:00 +00001296Local<Value> Script::Id() {
1297 ON_BAILOUT("v8::Script::Id()", return Local<Value>());
1298 LOG_API("Script::Id");
1299 i::Object* raw_id = NULL;
1300 {
1301 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001302 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1303 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001304 i::Handle<i::Object> id(script->id());
1305 raw_id = *id;
1306 }
1307 i::Handle<i::Object> id(raw_id);
1308 return Utils::ToLocal(id);
1309}
1310
1311
Steve Blockd0582a62009-12-15 09:54:21 +00001312void Script::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001313 ON_BAILOUT("v8::Script::SetData()", return);
1314 LOG_API("Script::SetData");
1315 {
1316 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001317 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001318 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
Steve Block6ded16b2010-05-10 14:33:55 +01001319 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001320 script->set_data(*raw_data);
1321 }
1322}
1323
1324
1325// --- E x c e p t i o n s ---
1326
1327
1328v8::TryCatch::TryCatch()
Steve Blockd0582a62009-12-15 09:54:21 +00001329 : next_(i::Top::try_catch_handler_address()),
Steve Blocka7e24c12009-10-30 11:49:00 +00001330 exception_(i::Heap::the_hole_value()),
1331 message_(i::Smi::FromInt(0)),
1332 is_verbose_(false),
1333 can_continue_(true),
1334 capture_message_(true),
Steve Blockd0582a62009-12-15 09:54:21 +00001335 rethrow_(false) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001336 i::Top::RegisterTryCatchHandler(this);
1337}
1338
1339
1340v8::TryCatch::~TryCatch() {
Steve Blockd0582a62009-12-15 09:54:21 +00001341 if (rethrow_) {
1342 v8::HandleScope scope;
1343 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
1344 i::Top::UnregisterTryCatchHandler(this);
1345 v8::ThrowException(exc);
1346 } else {
1347 i::Top::UnregisterTryCatchHandler(this);
1348 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001349}
1350
1351
1352bool v8::TryCatch::HasCaught() const {
1353 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1354}
1355
1356
1357bool v8::TryCatch::CanContinue() const {
1358 return can_continue_;
1359}
1360
1361
Steve Blockd0582a62009-12-15 09:54:21 +00001362v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1363 if (!HasCaught()) return v8::Local<v8::Value>();
1364 rethrow_ = true;
1365 return v8::Undefined();
1366}
1367
1368
Steve Blocka7e24c12009-10-30 11:49:00 +00001369v8::Local<Value> v8::TryCatch::Exception() const {
1370 if (HasCaught()) {
1371 // Check for out of memory exception.
1372 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1373 return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1374 } else {
1375 return v8::Local<Value>();
1376 }
1377}
1378
1379
1380v8::Local<Value> v8::TryCatch::StackTrace() const {
1381 if (HasCaught()) {
1382 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1383 if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1384 v8::HandleScope scope;
1385 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
1386 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
1387 if (!obj->HasProperty(*name))
1388 return v8::Local<Value>();
1389 return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
1390 } else {
1391 return v8::Local<Value>();
1392 }
1393}
1394
1395
1396v8::Local<v8::Message> v8::TryCatch::Message() const {
1397 if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1398 i::Object* message = reinterpret_cast<i::Object*>(message_);
1399 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1400 } else {
1401 return v8::Local<v8::Message>();
1402 }
1403}
1404
1405
1406void v8::TryCatch::Reset() {
1407 exception_ = i::Heap::the_hole_value();
1408 message_ = i::Smi::FromInt(0);
1409}
1410
1411
1412void v8::TryCatch::SetVerbose(bool value) {
1413 is_verbose_ = value;
1414}
1415
1416
1417void v8::TryCatch::SetCaptureMessage(bool value) {
1418 capture_message_ = value;
1419}
1420
1421
1422// --- M e s s a g e ---
1423
1424
1425Local<String> Message::Get() const {
1426 ON_BAILOUT("v8::Message::Get()", return Local<String>());
1427 ENTER_V8;
1428 HandleScope scope;
1429 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1430 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1431 Local<String> result = Utils::ToLocal(raw_result);
1432 return scope.Close(result);
1433}
1434
1435
1436v8::Handle<Value> Message::GetScriptResourceName() const {
1437 if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1438 return Local<String>();
1439 }
1440 ENTER_V8;
1441 HandleScope scope;
1442 i::Handle<i::JSObject> obj =
1443 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1444 // Return this.script.name.
1445 i::Handle<i::JSValue> script =
1446 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1447 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
1448 return scope.Close(Utils::ToLocal(resource_name));
1449}
1450
1451
1452v8::Handle<Value> Message::GetScriptData() const {
1453 if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
1454 return Local<Value>();
1455 }
1456 ENTER_V8;
1457 HandleScope scope;
1458 i::Handle<i::JSObject> obj =
1459 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1460 // Return this.script.data.
1461 i::Handle<i::JSValue> script =
1462 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1463 i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1464 return scope.Close(Utils::ToLocal(data));
1465}
1466
1467
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001468v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
1469 if (IsDeadCheck("v8::Message::GetStackTrace()")) {
1470 return Local<v8::StackTrace>();
1471 }
1472 ENTER_V8;
1473 HandleScope scope;
1474 i::Handle<i::JSObject> obj =
1475 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1476 i::Handle<i::Object> stackFramesObj = GetProperty(obj, "stackFrames");
1477 if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
1478 i::Handle<i::JSArray> stackTrace =
1479 i::Handle<i::JSArray>::cast(stackFramesObj);
1480 return scope.Close(Utils::StackTraceToLocal(stackTrace));
1481}
1482
1483
Steve Blocka7e24c12009-10-30 11:49:00 +00001484static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1485 i::Handle<i::Object> recv,
1486 int argc,
1487 i::Object** argv[],
1488 bool* has_pending_exception) {
1489 i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
1490 i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
1491 i::Handle<i::JSFunction> fun =
1492 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1493 i::Handle<i::Object> value =
1494 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1495 return value;
1496}
1497
1498
1499static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1500 i::Handle<i::Object> data,
1501 bool* has_pending_exception) {
1502 i::Object** argv[1] = { data.location() };
1503 return CallV8HeapFunction(name,
1504 i::Top::builtins(),
1505 1,
1506 argv,
1507 has_pending_exception);
1508}
1509
1510
1511int Message::GetLineNumber() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001512 ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001513 ENTER_V8;
1514 HandleScope scope;
1515 EXCEPTION_PREAMBLE();
1516 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1517 Utils::OpenHandle(this),
1518 &has_pending_exception);
1519 EXCEPTION_BAILOUT_CHECK(0);
1520 return static_cast<int>(result->Number());
1521}
1522
1523
1524int Message::GetStartPosition() const {
1525 if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1526 ENTER_V8;
1527 HandleScope scope;
1528
1529 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1530 return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1531}
1532
1533
1534int Message::GetEndPosition() const {
1535 if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1536 ENTER_V8;
1537 HandleScope scope;
1538 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1539 return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1540}
1541
1542
1543int Message::GetStartColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001544 if (IsDeadCheck("v8::Message::GetStartColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001545 ENTER_V8;
1546 HandleScope scope;
1547 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1548 EXCEPTION_PREAMBLE();
1549 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1550 "GetPositionInLine",
1551 data_obj,
1552 &has_pending_exception);
1553 EXCEPTION_BAILOUT_CHECK(0);
1554 return static_cast<int>(start_col_obj->Number());
1555}
1556
1557
1558int Message::GetEndColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001559 if (IsDeadCheck("v8::Message::GetEndColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001560 ENTER_V8;
1561 HandleScope scope;
1562 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1563 EXCEPTION_PREAMBLE();
1564 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1565 "GetPositionInLine",
1566 data_obj,
1567 &has_pending_exception);
1568 EXCEPTION_BAILOUT_CHECK(0);
1569 int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1570 int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1571 return static_cast<int>(start_col_obj->Number()) + (end - start);
1572}
1573
1574
1575Local<String> Message::GetSourceLine() const {
1576 ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
1577 ENTER_V8;
1578 HandleScope scope;
1579 EXCEPTION_PREAMBLE();
1580 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1581 Utils::OpenHandle(this),
1582 &has_pending_exception);
1583 EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1584 if (result->IsString()) {
1585 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1586 } else {
1587 return Local<String>();
1588 }
1589}
1590
1591
1592void Message::PrintCurrentStackTrace(FILE* out) {
1593 if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1594 ENTER_V8;
1595 i::Top::PrintCurrentStackTrace(out);
1596}
1597
1598
Kristian Monsen25f61362010-05-21 11:50:48 +01001599// --- S t a c k T r a c e ---
1600
1601Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
1602 if (IsDeadCheck("v8::StackTrace::GetFrame()")) return Local<StackFrame>();
1603 ENTER_V8;
1604 HandleScope scope;
1605 i::Handle<i::JSArray> self = Utils::OpenHandle(this);
1606 i::Handle<i::JSObject> obj(i::JSObject::cast(self->GetElement(index)));
1607 return scope.Close(Utils::StackFrameToLocal(obj));
1608}
1609
1610
1611int StackTrace::GetFrameCount() const {
1612 if (IsDeadCheck("v8::StackTrace::GetFrameCount()")) return -1;
1613 ENTER_V8;
1614 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
1615}
1616
1617
1618Local<Array> StackTrace::AsArray() {
1619 if (IsDeadCheck("v8::StackTrace::AsArray()")) Local<Array>();
1620 ENTER_V8;
1621 return Utils::ToLocal(Utils::OpenHandle(this));
1622}
1623
1624
1625Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
1626 StackTraceOptions options) {
1627 if (IsDeadCheck("v8::StackTrace::CurrentStackTrace()")) Local<StackTrace>();
1628 ENTER_V8;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001629 i::Handle<i::JSArray> stackTrace =
1630 i::Top::CaptureCurrentStackTrace(frame_limit, options);
1631 return Utils::StackTraceToLocal(stackTrace);
Kristian Monsen25f61362010-05-21 11:50:48 +01001632}
1633
1634
1635// --- S t a c k F r a m e ---
1636
1637int StackFrame::GetLineNumber() const {
1638 if (IsDeadCheck("v8::StackFrame::GetLineNumber()")) {
1639 return Message::kNoLineNumberInfo;
1640 }
1641 ENTER_V8;
1642 i::HandleScope scope;
1643 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1644 i::Handle<i::Object> line = GetProperty(self, "lineNumber");
1645 if (!line->IsSmi()) {
1646 return Message::kNoLineNumberInfo;
1647 }
1648 return i::Smi::cast(*line)->value();
1649}
1650
1651
1652int StackFrame::GetColumn() const {
1653 if (IsDeadCheck("v8::StackFrame::GetColumn()")) {
1654 return Message::kNoColumnInfo;
1655 }
1656 ENTER_V8;
1657 i::HandleScope scope;
1658 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1659 i::Handle<i::Object> column = GetProperty(self, "column");
1660 if (!column->IsSmi()) {
1661 return Message::kNoColumnInfo;
1662 }
1663 return i::Smi::cast(*column)->value();
1664}
1665
1666
1667Local<String> StackFrame::GetScriptName() const {
1668 if (IsDeadCheck("v8::StackFrame::GetScriptName()")) return Local<String>();
1669 ENTER_V8;
1670 HandleScope scope;
1671 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1672 i::Handle<i::Object> name = GetProperty(self, "scriptName");
1673 if (!name->IsString()) {
1674 return Local<String>();
1675 }
1676 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1677}
1678
1679
1680Local<String> StackFrame::GetFunctionName() const {
1681 if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
1682 ENTER_V8;
1683 HandleScope scope;
1684 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1685 i::Handle<i::Object> name = GetProperty(self, "functionName");
1686 if (!name->IsString()) {
1687 return Local<String>();
1688 }
1689 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1690}
1691
1692
1693bool StackFrame::IsEval() const {
1694 if (IsDeadCheck("v8::StackFrame::IsEval()")) return false;
1695 ENTER_V8;
1696 i::HandleScope scope;
1697 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1698 i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
1699 return is_eval->IsTrue();
1700}
1701
1702
1703bool StackFrame::IsConstructor() const {
1704 if (IsDeadCheck("v8::StackFrame::IsConstructor()")) return false;
1705 ENTER_V8;
1706 i::HandleScope scope;
1707 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1708 i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
1709 return is_constructor->IsTrue();
1710}
1711
1712
Steve Blocka7e24c12009-10-30 11:49:00 +00001713// --- D a t a ---
1714
1715bool Value::IsUndefined() const {
1716 if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1717 return Utils::OpenHandle(this)->IsUndefined();
1718}
1719
1720
1721bool Value::IsNull() const {
1722 if (IsDeadCheck("v8::Value::IsNull()")) return false;
1723 return Utils::OpenHandle(this)->IsNull();
1724}
1725
1726
1727bool Value::IsTrue() const {
1728 if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1729 return Utils::OpenHandle(this)->IsTrue();
1730}
1731
1732
1733bool Value::IsFalse() const {
1734 if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1735 return Utils::OpenHandle(this)->IsFalse();
1736}
1737
1738
1739bool Value::IsFunction() const {
1740 if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1741 return Utils::OpenHandle(this)->IsJSFunction();
1742}
1743
1744
1745bool Value::FullIsString() const {
1746 if (IsDeadCheck("v8::Value::IsString()")) return false;
1747 bool result = Utils::OpenHandle(this)->IsString();
1748 ASSERT_EQ(result, QuickIsString());
1749 return result;
1750}
1751
1752
1753bool Value::IsArray() const {
1754 if (IsDeadCheck("v8::Value::IsArray()")) return false;
1755 return Utils::OpenHandle(this)->IsJSArray();
1756}
1757
1758
1759bool Value::IsObject() const {
1760 if (IsDeadCheck("v8::Value::IsObject()")) return false;
1761 return Utils::OpenHandle(this)->IsJSObject();
1762}
1763
1764
1765bool Value::IsNumber() const {
1766 if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1767 return Utils::OpenHandle(this)->IsNumber();
1768}
1769
1770
1771bool Value::IsBoolean() const {
1772 if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1773 return Utils::OpenHandle(this)->IsBoolean();
1774}
1775
1776
1777bool Value::IsExternal() const {
1778 if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1779 return Utils::OpenHandle(this)->IsProxy();
1780}
1781
1782
1783bool Value::IsInt32() const {
1784 if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1785 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1786 if (obj->IsSmi()) return true;
1787 if (obj->IsNumber()) {
1788 double value = obj->Number();
1789 return i::FastI2D(i::FastD2I(value)) == value;
1790 }
1791 return false;
1792}
1793
1794
Steve Block6ded16b2010-05-10 14:33:55 +01001795bool Value::IsUint32() const {
1796 if (IsDeadCheck("v8::Value::IsUint32()")) return false;
1797 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1798 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
1799 if (obj->IsNumber()) {
1800 double value = obj->Number();
1801 return i::FastUI2D(i::FastD2UI(value)) == value;
1802 }
1803 return false;
1804}
1805
1806
Steve Blocka7e24c12009-10-30 11:49:00 +00001807bool Value::IsDate() const {
1808 if (IsDeadCheck("v8::Value::IsDate()")) return false;
1809 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1810 return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1811}
1812
1813
Iain Merrick75681382010-08-19 15:07:18 +01001814bool Value::IsRegExp() const {
1815 if (IsDeadCheck("v8::Value::IsRegExp()")) return false;
1816 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1817 return obj->IsJSRegExp();
1818}
1819
1820
Steve Blocka7e24c12009-10-30 11:49:00 +00001821Local<String> Value::ToString() const {
1822 if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1823 LOG_API("ToString");
1824 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1825 i::Handle<i::Object> str;
1826 if (obj->IsString()) {
1827 str = obj;
1828 } else {
1829 ENTER_V8;
1830 EXCEPTION_PREAMBLE();
1831 str = i::Execution::ToString(obj, &has_pending_exception);
1832 EXCEPTION_BAILOUT_CHECK(Local<String>());
1833 }
1834 return Local<String>(ToApi<String>(str));
1835}
1836
1837
1838Local<String> Value::ToDetailString() const {
1839 if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1840 LOG_API("ToDetailString");
1841 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1842 i::Handle<i::Object> str;
1843 if (obj->IsString()) {
1844 str = obj;
1845 } else {
1846 ENTER_V8;
1847 EXCEPTION_PREAMBLE();
1848 str = i::Execution::ToDetailString(obj, &has_pending_exception);
1849 EXCEPTION_BAILOUT_CHECK(Local<String>());
1850 }
1851 return Local<String>(ToApi<String>(str));
1852}
1853
1854
1855Local<v8::Object> Value::ToObject() const {
1856 if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1857 LOG_API("ToObject");
1858 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1859 i::Handle<i::Object> val;
1860 if (obj->IsJSObject()) {
1861 val = obj;
1862 } else {
1863 ENTER_V8;
1864 EXCEPTION_PREAMBLE();
1865 val = i::Execution::ToObject(obj, &has_pending_exception);
1866 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1867 }
1868 return Local<v8::Object>(ToApi<Object>(val));
1869}
1870
1871
1872Local<Boolean> Value::ToBoolean() const {
1873 if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1874 LOG_API("ToBoolean");
1875 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1876 if (obj->IsBoolean()) {
1877 return Local<Boolean>(ToApi<Boolean>(obj));
1878 } else {
1879 ENTER_V8;
1880 i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1881 return Local<Boolean>(ToApi<Boolean>(val));
1882 }
1883}
1884
1885
1886Local<Number> Value::ToNumber() const {
1887 if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1888 LOG_API("ToNumber");
1889 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1890 i::Handle<i::Object> num;
1891 if (obj->IsNumber()) {
1892 num = obj;
1893 } else {
1894 ENTER_V8;
1895 EXCEPTION_PREAMBLE();
1896 num = i::Execution::ToNumber(obj, &has_pending_exception);
1897 EXCEPTION_BAILOUT_CHECK(Local<Number>());
1898 }
1899 return Local<Number>(ToApi<Number>(num));
1900}
1901
1902
1903Local<Integer> Value::ToInteger() const {
1904 if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1905 LOG_API("ToInteger");
1906 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1907 i::Handle<i::Object> num;
1908 if (obj->IsSmi()) {
1909 num = obj;
1910 } else {
1911 ENTER_V8;
1912 EXCEPTION_PREAMBLE();
1913 num = i::Execution::ToInteger(obj, &has_pending_exception);
1914 EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1915 }
1916 return Local<Integer>(ToApi<Integer>(num));
1917}
1918
1919
1920void External::CheckCast(v8::Value* that) {
1921 if (IsDeadCheck("v8::External::Cast()")) return;
1922 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1923 ApiCheck(obj->IsProxy(),
1924 "v8::External::Cast()",
1925 "Could not convert to external");
1926}
1927
1928
1929void v8::Object::CheckCast(Value* that) {
1930 if (IsDeadCheck("v8::Object::Cast()")) return;
1931 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1932 ApiCheck(obj->IsJSObject(),
1933 "v8::Object::Cast()",
1934 "Could not convert to object");
1935}
1936
1937
1938void v8::Function::CheckCast(Value* that) {
1939 if (IsDeadCheck("v8::Function::Cast()")) return;
1940 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1941 ApiCheck(obj->IsJSFunction(),
1942 "v8::Function::Cast()",
1943 "Could not convert to function");
1944}
1945
1946
1947void v8::String::CheckCast(v8::Value* that) {
1948 if (IsDeadCheck("v8::String::Cast()")) return;
1949 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1950 ApiCheck(obj->IsString(),
1951 "v8::String::Cast()",
1952 "Could not convert to string");
1953}
1954
1955
1956void v8::Number::CheckCast(v8::Value* that) {
1957 if (IsDeadCheck("v8::Number::Cast()")) return;
1958 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1959 ApiCheck(obj->IsNumber(),
1960 "v8::Number::Cast()",
1961 "Could not convert to number");
1962}
1963
1964
1965void v8::Integer::CheckCast(v8::Value* that) {
1966 if (IsDeadCheck("v8::Integer::Cast()")) return;
1967 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1968 ApiCheck(obj->IsNumber(),
1969 "v8::Integer::Cast()",
1970 "Could not convert to number");
1971}
1972
1973
1974void v8::Array::CheckCast(Value* that) {
1975 if (IsDeadCheck("v8::Array::Cast()")) return;
1976 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1977 ApiCheck(obj->IsJSArray(),
1978 "v8::Array::Cast()",
1979 "Could not convert to array");
1980}
1981
1982
1983void v8::Date::CheckCast(v8::Value* that) {
1984 if (IsDeadCheck("v8::Date::Cast()")) return;
1985 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1986 ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
1987 "v8::Date::Cast()",
1988 "Could not convert to date");
1989}
1990
1991
1992bool Value::BooleanValue() const {
1993 if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
1994 LOG_API("BooleanValue");
1995 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1996 if (obj->IsBoolean()) {
1997 return obj->IsTrue();
1998 } else {
1999 ENTER_V8;
2000 i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
2001 return value->IsTrue();
2002 }
2003}
2004
2005
2006double Value::NumberValue() const {
2007 if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
2008 LOG_API("NumberValue");
2009 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2010 i::Handle<i::Object> num;
2011 if (obj->IsNumber()) {
2012 num = obj;
2013 } else {
2014 ENTER_V8;
2015 EXCEPTION_PREAMBLE();
2016 num = i::Execution::ToNumber(obj, &has_pending_exception);
2017 EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
2018 }
2019 return num->Number();
2020}
2021
2022
2023int64_t Value::IntegerValue() const {
2024 if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
2025 LOG_API("IntegerValue");
2026 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2027 i::Handle<i::Object> num;
2028 if (obj->IsNumber()) {
2029 num = obj;
2030 } else {
2031 ENTER_V8;
2032 EXCEPTION_PREAMBLE();
2033 num = i::Execution::ToInteger(obj, &has_pending_exception);
2034 EXCEPTION_BAILOUT_CHECK(0);
2035 }
2036 if (num->IsSmi()) {
2037 return i::Smi::cast(*num)->value();
2038 } else {
2039 return static_cast<int64_t>(num->Number());
2040 }
2041}
2042
2043
2044Local<Int32> Value::ToInt32() const {
2045 if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
2046 LOG_API("ToInt32");
2047 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2048 i::Handle<i::Object> num;
2049 if (obj->IsSmi()) {
2050 num = obj;
2051 } else {
2052 ENTER_V8;
2053 EXCEPTION_PREAMBLE();
2054 num = i::Execution::ToInt32(obj, &has_pending_exception);
2055 EXCEPTION_BAILOUT_CHECK(Local<Int32>());
2056 }
2057 return Local<Int32>(ToApi<Int32>(num));
2058}
2059
2060
2061Local<Uint32> Value::ToUint32() const {
2062 if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
2063 LOG_API("ToUInt32");
2064 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2065 i::Handle<i::Object> num;
2066 if (obj->IsSmi()) {
2067 num = obj;
2068 } else {
2069 ENTER_V8;
2070 EXCEPTION_PREAMBLE();
2071 num = i::Execution::ToUint32(obj, &has_pending_exception);
2072 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2073 }
2074 return Local<Uint32>(ToApi<Uint32>(num));
2075}
2076
2077
2078Local<Uint32> Value::ToArrayIndex() const {
2079 if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
2080 LOG_API("ToArrayIndex");
2081 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2082 if (obj->IsSmi()) {
2083 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2084 return Local<Uint32>();
2085 }
2086 ENTER_V8;
2087 EXCEPTION_PREAMBLE();
2088 i::Handle<i::Object> string_obj =
2089 i::Execution::ToString(obj, &has_pending_exception);
2090 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2091 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2092 uint32_t index;
2093 if (str->AsArrayIndex(&index)) {
2094 i::Handle<i::Object> value;
2095 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2096 value = i::Handle<i::Object>(i::Smi::FromInt(index));
2097 } else {
2098 value = i::Factory::NewNumber(index);
2099 }
2100 return Utils::Uint32ToLocal(value);
2101 }
2102 return Local<Uint32>();
2103}
2104
2105
2106int32_t Value::Int32Value() const {
2107 if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
2108 LOG_API("Int32Value");
2109 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2110 if (obj->IsSmi()) {
2111 return i::Smi::cast(*obj)->value();
2112 } else {
2113 LOG_API("Int32Value (slow)");
2114 ENTER_V8;
2115 EXCEPTION_PREAMBLE();
2116 i::Handle<i::Object> num =
2117 i::Execution::ToInt32(obj, &has_pending_exception);
2118 EXCEPTION_BAILOUT_CHECK(0);
2119 if (num->IsSmi()) {
2120 return i::Smi::cast(*num)->value();
2121 } else {
2122 return static_cast<int32_t>(num->Number());
2123 }
2124 }
2125}
2126
2127
2128bool Value::Equals(Handle<Value> that) const {
2129 if (IsDeadCheck("v8::Value::Equals()")
2130 || EmptyCheck("v8::Value::Equals()", this)
2131 || EmptyCheck("v8::Value::Equals()", that)) {
2132 return false;
2133 }
2134 LOG_API("Equals");
2135 ENTER_V8;
2136 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2137 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2138 i::Object** args[1] = { other.location() };
2139 EXCEPTION_PREAMBLE();
2140 i::Handle<i::Object> result =
2141 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
2142 EXCEPTION_BAILOUT_CHECK(false);
2143 return *result == i::Smi::FromInt(i::EQUAL);
2144}
2145
2146
2147bool Value::StrictEquals(Handle<Value> that) const {
2148 if (IsDeadCheck("v8::Value::StrictEquals()")
2149 || EmptyCheck("v8::Value::StrictEquals()", this)
2150 || EmptyCheck("v8::Value::StrictEquals()", that)) {
2151 return false;
2152 }
2153 LOG_API("StrictEquals");
2154 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2155 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2156 // Must check HeapNumber first, since NaN !== NaN.
2157 if (obj->IsHeapNumber()) {
2158 if (!other->IsNumber()) return false;
2159 double x = obj->Number();
2160 double y = other->Number();
2161 // Must check explicitly for NaN:s on Windows, but -0 works fine.
2162 return x == y && !isnan(x) && !isnan(y);
2163 } else if (*obj == *other) { // Also covers Booleans.
2164 return true;
2165 } else if (obj->IsSmi()) {
2166 return other->IsNumber() && obj->Number() == other->Number();
2167 } else if (obj->IsString()) {
2168 return other->IsString() &&
2169 i::String::cast(*obj)->Equals(i::String::cast(*other));
2170 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2171 return other->IsUndefined() || other->IsUndetectableObject();
2172 } else {
2173 return false;
2174 }
2175}
2176
2177
2178uint32_t Value::Uint32Value() const {
2179 if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
2180 LOG_API("Uint32Value");
2181 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2182 if (obj->IsSmi()) {
2183 return i::Smi::cast(*obj)->value();
2184 } else {
2185 ENTER_V8;
2186 EXCEPTION_PREAMBLE();
2187 i::Handle<i::Object> num =
2188 i::Execution::ToUint32(obj, &has_pending_exception);
2189 EXCEPTION_BAILOUT_CHECK(0);
2190 if (num->IsSmi()) {
2191 return i::Smi::cast(*num)->value();
2192 } else {
2193 return static_cast<uint32_t>(num->Number());
2194 }
2195 }
2196}
2197
2198
2199bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
2200 v8::PropertyAttribute attribs) {
2201 ON_BAILOUT("v8::Object::Set()", return false);
2202 ENTER_V8;
2203 HandleScope scope;
2204 i::Handle<i::Object> self = Utils::OpenHandle(this);
2205 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2206 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2207 EXCEPTION_PREAMBLE();
2208 i::Handle<i::Object> obj = i::SetProperty(
2209 self,
2210 key_obj,
2211 value_obj,
2212 static_cast<PropertyAttributes>(attribs));
2213 has_pending_exception = obj.is_null();
2214 EXCEPTION_BAILOUT_CHECK(false);
2215 return true;
2216}
2217
2218
Steve Block6ded16b2010-05-10 14:33:55 +01002219bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
2220 ON_BAILOUT("v8::Object::Set()", return false);
2221 ENTER_V8;
2222 HandleScope scope;
2223 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2224 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2225 EXCEPTION_PREAMBLE();
2226 i::Handle<i::Object> obj = i::SetElement(
2227 self,
2228 index,
2229 value_obj);
2230 has_pending_exception = obj.is_null();
2231 EXCEPTION_BAILOUT_CHECK(false);
2232 return true;
2233}
2234
2235
Steve Blocka7e24c12009-10-30 11:49:00 +00002236bool v8::Object::ForceSet(v8::Handle<Value> key,
2237 v8::Handle<Value> value,
2238 v8::PropertyAttribute attribs) {
2239 ON_BAILOUT("v8::Object::ForceSet()", return false);
2240 ENTER_V8;
2241 HandleScope scope;
2242 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2243 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2244 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2245 EXCEPTION_PREAMBLE();
2246 i::Handle<i::Object> obj = i::ForceSetProperty(
2247 self,
2248 key_obj,
2249 value_obj,
2250 static_cast<PropertyAttributes>(attribs));
2251 has_pending_exception = obj.is_null();
2252 EXCEPTION_BAILOUT_CHECK(false);
2253 return true;
2254}
2255
2256
2257bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2258 ON_BAILOUT("v8::Object::ForceDelete()", return false);
2259 ENTER_V8;
2260 HandleScope scope;
2261 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2262 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2263 EXCEPTION_PREAMBLE();
2264 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2265 has_pending_exception = obj.is_null();
2266 EXCEPTION_BAILOUT_CHECK(false);
2267 return obj->IsTrue();
2268}
2269
2270
2271Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2272 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2273 ENTER_V8;
2274 i::Handle<i::Object> self = Utils::OpenHandle(this);
2275 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2276 EXCEPTION_PREAMBLE();
2277 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2278 has_pending_exception = result.is_null();
2279 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2280 return Utils::ToLocal(result);
2281}
2282
2283
Steve Block6ded16b2010-05-10 14:33:55 +01002284Local<Value> v8::Object::Get(uint32_t index) {
2285 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2286 ENTER_V8;
2287 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2288 EXCEPTION_PREAMBLE();
2289 i::Handle<i::Object> result = i::GetElement(self, index);
2290 has_pending_exception = result.is_null();
2291 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2292 return Utils::ToLocal(result);
2293}
2294
2295
Steve Blocka7e24c12009-10-30 11:49:00 +00002296Local<Value> v8::Object::GetPrototype() {
2297 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
2298 ENTER_V8;
2299 i::Handle<i::Object> self = Utils::OpenHandle(this);
2300 i::Handle<i::Object> result = i::GetPrototype(self);
2301 return Utils::ToLocal(result);
2302}
2303
2304
Andrei Popescu402d9372010-02-26 13:31:12 +00002305bool v8::Object::SetPrototype(Handle<Value> value) {
2306 ON_BAILOUT("v8::Object::SetPrototype()", return false);
2307 ENTER_V8;
2308 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2309 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2310 EXCEPTION_PREAMBLE();
2311 i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2312 has_pending_exception = result.is_null();
2313 EXCEPTION_BAILOUT_CHECK(false);
2314 return true;
2315}
2316
2317
Steve Blocka7e24c12009-10-30 11:49:00 +00002318Local<Object> v8::Object::FindInstanceInPrototypeChain(
2319 v8::Handle<FunctionTemplate> tmpl) {
2320 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
2321 return Local<v8::Object>());
2322 ENTER_V8;
2323 i::JSObject* object = *Utils::OpenHandle(this);
2324 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2325 while (!object->IsInstanceOf(tmpl_info)) {
2326 i::Object* prototype = object->GetPrototype();
2327 if (!prototype->IsJSObject()) return Local<Object>();
2328 object = i::JSObject::cast(prototype);
2329 }
2330 return Utils::ToLocal(i::Handle<i::JSObject>(object));
2331}
2332
2333
2334Local<Array> v8::Object::GetPropertyNames() {
2335 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
2336 ENTER_V8;
2337 v8::HandleScope scope;
2338 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2339 i::Handle<i::FixedArray> value =
2340 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2341 // Because we use caching to speed up enumeration it is important
2342 // to never change the result of the basic enumeration function so
2343 // we clone the result.
2344 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
2345 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
2346 return scope.Close(Utils::ToLocal(result));
2347}
2348
2349
2350Local<String> v8::Object::ObjectProtoToString() {
2351 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2352 ENTER_V8;
2353 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2354
2355 i::Handle<i::Object> name(self->class_name());
2356
2357 // Native implementation of Object.prototype.toString (v8natives.js):
2358 // var c = %ClassOf(this);
2359 // if (c === 'Arguments') c = 'Object';
2360 // return "[object " + c + "]";
2361
2362 if (!name->IsString()) {
2363 return v8::String::New("[object ]");
2364
2365 } else {
2366 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2367 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2368 return v8::String::New("[object Object]");
2369
2370 } else {
2371 const char* prefix = "[object ";
2372 Local<String> str = Utils::ToLocal(class_name);
2373 const char* postfix = "]";
2374
Steve Blockd0582a62009-12-15 09:54:21 +00002375 int prefix_len = i::StrLength(prefix);
2376 int str_len = str->Length();
2377 int postfix_len = i::StrLength(postfix);
Steve Blocka7e24c12009-10-30 11:49:00 +00002378
Steve Blockd0582a62009-12-15 09:54:21 +00002379 int buf_len = prefix_len + str_len + postfix_len;
Kristian Monsen25f61362010-05-21 11:50:48 +01002380 i::ScopedVector<char> buf(buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002381
2382 // Write prefix.
Kristian Monsen25f61362010-05-21 11:50:48 +01002383 char* ptr = buf.start();
Steve Blocka7e24c12009-10-30 11:49:00 +00002384 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2385 ptr += prefix_len;
2386
2387 // Write real content.
2388 str->WriteAscii(ptr, 0, str_len);
2389 ptr += str_len;
2390
2391 // Write postfix.
2392 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2393
2394 // Copy the buffer into a heap-allocated string and return it.
Kristian Monsen25f61362010-05-21 11:50:48 +01002395 Local<String> result = v8::String::New(buf.start(), buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002396 return result;
2397 }
2398 }
2399}
2400
2401
2402bool v8::Object::Delete(v8::Handle<String> key) {
2403 ON_BAILOUT("v8::Object::Delete()", return false);
2404 ENTER_V8;
2405 HandleScope scope;
2406 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2407 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2408 return i::DeleteProperty(self, key_obj)->IsTrue();
2409}
2410
2411
2412bool v8::Object::Has(v8::Handle<String> key) {
2413 ON_BAILOUT("v8::Object::Has()", return false);
2414 ENTER_V8;
2415 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2416 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2417 return self->HasProperty(*key_obj);
2418}
2419
2420
2421bool v8::Object::Delete(uint32_t index) {
2422 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2423 ENTER_V8;
2424 HandleScope scope;
2425 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2426 return i::DeleteElement(self, index)->IsTrue();
2427}
2428
2429
2430bool v8::Object::Has(uint32_t index) {
2431 ON_BAILOUT("v8::Object::HasProperty()", return false);
2432 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2433 return self->HasElement(index);
2434}
2435
2436
Leon Clarkef7060e22010-06-03 12:02:55 +01002437bool Object::SetAccessor(Handle<String> name,
2438 AccessorGetter getter,
2439 AccessorSetter setter,
2440 v8::Handle<Value> data,
2441 AccessControl settings,
2442 PropertyAttribute attributes) {
2443 ON_BAILOUT("v8::Object::SetAccessor()", return false);
2444 ENTER_V8;
2445 HandleScope scope;
2446 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name,
2447 getter, setter, data,
2448 settings, attributes);
2449 i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info);
2450 return !result.is_null() && !result->IsUndefined();
2451}
2452
2453
Steve Blocka7e24c12009-10-30 11:49:00 +00002454bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2455 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2456 return Utils::OpenHandle(this)->HasRealNamedProperty(
2457 *Utils::OpenHandle(*key));
2458}
2459
2460
2461bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2462 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2463 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2464}
2465
2466
2467bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2468 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2469 ENTER_V8;
2470 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2471 *Utils::OpenHandle(*key));
2472}
2473
2474
2475bool v8::Object::HasNamedLookupInterceptor() {
2476 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2477 return Utils::OpenHandle(this)->HasNamedInterceptor();
2478}
2479
2480
2481bool v8::Object::HasIndexedLookupInterceptor() {
2482 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2483 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2484}
2485
2486
2487Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2488 Handle<String> key) {
2489 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2490 return Local<Value>());
2491 ENTER_V8;
2492 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2493 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2494 i::LookupResult lookup;
2495 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002496 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002497 PropertyAttributes attributes;
2498 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2499 &lookup,
2500 *key_obj,
2501 &attributes));
2502 return Utils::ToLocal(result);
2503 }
2504 return Local<Value>(); // No real property was found in prototype chain.
2505}
2506
2507
2508Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2509 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
2510 ENTER_V8;
2511 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2512 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2513 i::LookupResult lookup;
2514 self_obj->LookupRealNamedProperty(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002515 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002516 PropertyAttributes attributes;
2517 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2518 &lookup,
2519 *key_obj,
2520 &attributes));
2521 return Utils::ToLocal(result);
2522 }
2523 return Local<Value>(); // No real property was found in prototype chain.
2524}
2525
2526
2527// Turns on access checks by copying the map and setting the check flag.
2528// Because the object gets a new map, existing inline cache caching
2529// the old map of this object will fail.
2530void v8::Object::TurnOnAccessCheck() {
2531 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2532 ENTER_V8;
2533 HandleScope scope;
2534 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2535
2536 i::Handle<i::Map> new_map =
2537 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2538 new_map->set_is_access_check_needed(true);
2539 obj->set_map(*new_map);
2540}
2541
2542
2543bool v8::Object::IsDirty() {
2544 return Utils::OpenHandle(this)->IsDirty();
2545}
2546
2547
2548Local<v8::Object> v8::Object::Clone() {
2549 ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2550 ENTER_V8;
2551 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2552 EXCEPTION_PREAMBLE();
2553 i::Handle<i::JSObject> result = i::Copy(self);
2554 has_pending_exception = result.is_null();
2555 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2556 return Utils::ToLocal(result);
2557}
2558
2559
2560int v8::Object::GetIdentityHash() {
2561 ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2562 ENTER_V8;
2563 HandleScope scope;
2564 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2565 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2566 i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
2567 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2568 int hash_value;
2569 if (hash->IsSmi()) {
2570 hash_value = i::Smi::cast(*hash)->value();
2571 } else {
2572 int attempts = 0;
2573 do {
2574 // Generate a random 32-bit hash value but limit range to fit
2575 // within a smi.
2576 hash_value = i::V8::Random() & i::Smi::kMaxValue;
2577 attempts++;
2578 } while (hash_value == 0 && attempts < 30);
2579 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
2580 i::SetProperty(hidden_props,
2581 hash_symbol,
2582 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2583 static_cast<PropertyAttributes>(None));
2584 }
2585 return hash_value;
2586}
2587
2588
2589bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2590 v8::Handle<v8::Value> value) {
2591 ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
2592 ENTER_V8;
2593 HandleScope scope;
2594 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2595 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2596 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2597 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2598 EXCEPTION_PREAMBLE();
2599 i::Handle<i::Object> obj = i::SetProperty(
2600 hidden_props,
2601 key_obj,
2602 value_obj,
2603 static_cast<PropertyAttributes>(None));
2604 has_pending_exception = obj.is_null();
2605 EXCEPTION_BAILOUT_CHECK(false);
2606 return true;
2607}
2608
2609
2610v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2611 ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2612 ENTER_V8;
2613 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2614 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2615 if (hidden_props->IsUndefined()) {
2616 return v8::Local<v8::Value>();
2617 }
2618 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2619 EXCEPTION_PREAMBLE();
2620 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2621 has_pending_exception = result.is_null();
2622 EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2623 if (result->IsUndefined()) {
2624 return v8::Local<v8::Value>();
2625 }
2626 return Utils::ToLocal(result);
2627}
2628
2629
2630bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2631 ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2632 ENTER_V8;
2633 HandleScope scope;
2634 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2635 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2636 if (hidden_props->IsUndefined()) {
2637 return true;
2638 }
2639 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2640 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2641 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2642}
2643
2644
2645void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2646 ON_BAILOUT("v8::SetElementsToPixelData()", return);
2647 ENTER_V8;
2648 HandleScope scope;
Steve Block3ce2e202009-11-05 08:53:23 +00002649 if (!ApiCheck(length <= i::PixelArray::kMaxLength,
Steve Blocka7e24c12009-10-30 11:49:00 +00002650 "v8::Object::SetIndexedPropertiesToPixelData()",
2651 "length exceeds max acceptable value")) {
2652 return;
2653 }
2654 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2655 if (!ApiCheck(!self->IsJSArray(),
2656 "v8::Object::SetIndexedPropertiesToPixelData()",
2657 "JSArray is not supported")) {
2658 return;
2659 }
2660 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002661 i::Handle<i::Map> slow_map =
2662 i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map()));
2663 self->set_map(*slow_map);
Steve Blocka7e24c12009-10-30 11:49:00 +00002664 self->set_elements(*pixels);
2665}
2666
2667
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002668bool v8::Object::HasIndexedPropertiesInPixelData() {
2669 ON_BAILOUT("v8::HasIndexedPropertiesInPixelData()", return false);
2670 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2671 return self->HasPixelElements();
2672}
2673
2674
2675uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
2676 ON_BAILOUT("v8::GetIndexedPropertiesPixelData()", return NULL);
2677 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2678 if (self->HasPixelElements()) {
2679 return i::PixelArray::cast(self->elements())->external_pointer();
2680 } else {
2681 return NULL;
2682 }
2683}
2684
2685
2686int v8::Object::GetIndexedPropertiesPixelDataLength() {
2687 ON_BAILOUT("v8::GetIndexedPropertiesPixelDataLength()", return -1);
2688 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2689 if (self->HasPixelElements()) {
2690 return i::PixelArray::cast(self->elements())->length();
2691 } else {
2692 return -1;
2693 }
2694}
2695
2696
Steve Block3ce2e202009-11-05 08:53:23 +00002697void v8::Object::SetIndexedPropertiesToExternalArrayData(
2698 void* data,
2699 ExternalArrayType array_type,
2700 int length) {
2701 ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
2702 ENTER_V8;
2703 HandleScope scope;
2704 if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
2705 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2706 "length exceeds max acceptable value")) {
2707 return;
2708 }
2709 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2710 if (!ApiCheck(!self->IsJSArray(),
2711 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2712 "JSArray is not supported")) {
2713 return;
2714 }
2715 i::Handle<i::ExternalArray> array =
2716 i::Factory::NewExternalArray(length, array_type, data);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002717 i::Handle<i::Map> slow_map =
2718 i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map()));
2719 self->set_map(*slow_map);
Steve Block3ce2e202009-11-05 08:53:23 +00002720 self->set_elements(*array);
2721}
2722
2723
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002724bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
2725 ON_BAILOUT("v8::HasIndexedPropertiesInExternalArrayData()", return false);
2726 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2727 return self->HasExternalArrayElements();
2728}
2729
2730
2731void* v8::Object::GetIndexedPropertiesExternalArrayData() {
2732 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayData()", return NULL);
2733 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2734 if (self->HasExternalArrayElements()) {
2735 return i::ExternalArray::cast(self->elements())->external_pointer();
2736 } else {
2737 return NULL;
2738 }
2739}
2740
2741
2742ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
2743 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataType()",
2744 return static_cast<ExternalArrayType>(-1));
2745 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2746 switch (self->elements()->map()->instance_type()) {
2747 case i::EXTERNAL_BYTE_ARRAY_TYPE:
2748 return kExternalByteArray;
2749 case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2750 return kExternalUnsignedByteArray;
2751 case i::EXTERNAL_SHORT_ARRAY_TYPE:
2752 return kExternalShortArray;
2753 case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2754 return kExternalUnsignedShortArray;
2755 case i::EXTERNAL_INT_ARRAY_TYPE:
2756 return kExternalIntArray;
2757 case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2758 return kExternalUnsignedIntArray;
2759 case i::EXTERNAL_FLOAT_ARRAY_TYPE:
2760 return kExternalFloatArray;
2761 default:
2762 return static_cast<ExternalArrayType>(-1);
2763 }
2764}
2765
2766
2767int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
2768 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataLength()", return 0);
2769 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2770 if (self->HasExternalArrayElements()) {
2771 return i::ExternalArray::cast(self->elements())->length();
2772 } else {
2773 return -1;
2774 }
2775}
2776
2777
Steve Blocka7e24c12009-10-30 11:49:00 +00002778Local<v8::Object> Function::NewInstance() const {
2779 return NewInstance(0, NULL);
2780}
2781
2782
2783Local<v8::Object> Function::NewInstance(int argc,
2784 v8::Handle<v8::Value> argv[]) const {
2785 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2786 LOG_API("Function::NewInstance");
2787 ENTER_V8;
2788 HandleScope scope;
2789 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2790 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2791 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2792 EXCEPTION_PREAMBLE();
2793 i::Handle<i::Object> returned =
2794 i::Execution::New(function, argc, args, &has_pending_exception);
2795 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2796 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2797}
2798
2799
2800Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2801 v8::Handle<v8::Value> argv[]) {
2802 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2803 LOG_API("Function::Call");
2804 ENTER_V8;
2805 i::Object* raw_result = NULL;
2806 {
2807 HandleScope scope;
2808 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2809 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2810 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2811 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2812 EXCEPTION_PREAMBLE();
2813 i::Handle<i::Object> returned =
2814 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2815 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2816 raw_result = *returned;
2817 }
2818 i::Handle<i::Object> result(raw_result);
2819 return Utils::ToLocal(result);
2820}
2821
2822
2823void Function::SetName(v8::Handle<v8::String> name) {
2824 ENTER_V8;
2825 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2826 func->shared()->set_name(*Utils::OpenHandle(*name));
2827}
2828
2829
2830Handle<Value> Function::GetName() const {
2831 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2832 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2833}
2834
2835
Andrei Popescu402d9372010-02-26 13:31:12 +00002836ScriptOrigin Function::GetScriptOrigin() const {
2837 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2838 if (func->shared()->script()->IsScript()) {
2839 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2840 v8::ScriptOrigin origin(
2841 Utils::ToLocal(i::Handle<i::Object>(script->name())),
2842 v8::Integer::New(script->line_offset()->value()),
2843 v8::Integer::New(script->column_offset()->value()));
2844 return origin;
2845 }
2846 return v8::ScriptOrigin(Handle<Value>());
2847}
2848
2849
2850const int Function::kLineOffsetNotFound = -1;
2851
2852
2853int Function::GetScriptLineNumber() const {
2854 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2855 if (func->shared()->script()->IsScript()) {
2856 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2857 return i::GetScriptLineNumber(script, func->shared()->start_position());
2858 }
2859 return kLineOffsetNotFound;
2860}
2861
2862
2863namespace {
2864
2865// Tracks string usage to help make better decisions when
2866// externalizing strings.
2867//
2868// Implementation note: internally this class only tracks fresh
2869// strings and keeps a single use counter for them.
2870class StringTracker {
2871 public:
2872 // Records that the given string's characters were copied to some
2873 // external buffer. If this happens often we should honor
2874 // externalization requests for the string.
2875 static void RecordWrite(i::Handle<i::String> string) {
2876 i::Address address = reinterpret_cast<i::Address>(*string);
2877 i::Address top = i::Heap::NewSpaceTop();
2878 if (IsFreshString(address, top)) {
2879 IncrementUseCount(top);
2880 }
2881 }
2882
2883 // Estimates freshness and use frequency of the given string based
2884 // on how close it is to the new space top and the recorded usage
2885 // history.
2886 static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
2887 i::Address address = reinterpret_cast<i::Address>(*string);
2888 i::Address top = i::Heap::NewSpaceTop();
2889 return IsFreshString(address, top) && IsUseCountLow(top);
2890 }
2891
2892 private:
2893 static inline bool IsFreshString(i::Address string, i::Address top) {
2894 return top - kFreshnessLimit <= string && string <= top;
2895 }
2896
2897 static inline bool IsUseCountLow(i::Address top) {
2898 if (last_top_ != top) return true;
2899 return use_count_ < kUseLimit;
2900 }
2901
2902 static inline void IncrementUseCount(i::Address top) {
2903 if (last_top_ != top) {
2904 use_count_ = 0;
2905 last_top_ = top;
2906 }
2907 ++use_count_;
2908 }
2909
2910 // How close to the new space top a fresh string has to be.
2911 static const int kFreshnessLimit = 1024;
2912
2913 // The number of uses required to consider a string useful.
2914 static const int kUseLimit = 32;
2915
2916 // Single use counter shared by all fresh strings.
2917 static int use_count_;
2918
2919 // Last new space top when the use count above was valid.
2920 static i::Address last_top_;
2921};
2922
2923int StringTracker::use_count_ = 0;
2924i::Address StringTracker::last_top_ = NULL;
2925
2926} // namespace
2927
2928
Steve Blocka7e24c12009-10-30 11:49:00 +00002929int String::Length() const {
2930 if (IsDeadCheck("v8::String::Length()")) return 0;
2931 return Utils::OpenHandle(this)->length();
2932}
2933
2934
2935int String::Utf8Length() const {
2936 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
2937 return Utils::OpenHandle(this)->Utf8Length();
2938}
2939
2940
Steve Block6ded16b2010-05-10 14:33:55 +01002941int String::WriteUtf8(char* buffer,
2942 int capacity,
2943 int* nchars_ref,
2944 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002945 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
2946 LOG_API("String::WriteUtf8");
2947 ENTER_V8;
2948 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002949 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002950 if (hints & HINT_MANY_WRITES_EXPECTED) {
2951 // Flatten the string for efficiency. This applies whether we are
2952 // using StringInputBuffer or Get(i) to access the characters.
2953 str->TryFlatten();
2954 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002955 write_input_buffer.Reset(0, *str);
2956 int len = str->length();
2957 // Encode the first K - 3 bytes directly into the buffer since we
2958 // know there's room for them. If no capacity is given we copy all
2959 // of them here.
2960 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
2961 int i;
2962 int pos = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01002963 int nchars = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002964 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
2965 i::uc32 c = write_input_buffer.GetNext();
2966 int written = unibrow::Utf8::Encode(buffer + pos, c);
2967 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002968 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002969 }
2970 if (i < len) {
2971 // For the last characters we need to check the length for each one
2972 // because they may be longer than the remaining space in the
2973 // buffer.
2974 char intermediate[unibrow::Utf8::kMaxEncodedSize];
2975 for (; i < len && pos < capacity; i++) {
2976 i::uc32 c = write_input_buffer.GetNext();
2977 int written = unibrow::Utf8::Encode(intermediate, c);
2978 if (pos + written <= capacity) {
2979 for (int j = 0; j < written; j++)
2980 buffer[pos + j] = intermediate[j];
2981 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002982 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002983 } else {
2984 // We've reached the end of the buffer
2985 break;
2986 }
2987 }
2988 }
Steve Block6ded16b2010-05-10 14:33:55 +01002989 if (nchars_ref != NULL) *nchars_ref = nchars;
Steve Blocka7e24c12009-10-30 11:49:00 +00002990 if (i == len && (capacity == -1 || pos < capacity))
2991 buffer[pos++] = '\0';
2992 return pos;
2993}
2994
2995
Steve Block6ded16b2010-05-10 14:33:55 +01002996int String::WriteAscii(char* buffer,
2997 int start,
2998 int length,
2999 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003000 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
3001 LOG_API("String::WriteAscii");
3002 ENTER_V8;
3003 ASSERT(start >= 0 && length >= -1);
3004 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003005 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003006 if (hints & HINT_MANY_WRITES_EXPECTED) {
3007 // Flatten the string for efficiency. This applies whether we are
3008 // using StringInputBuffer or Get(i) to access the characters.
3009 str->TryFlatten();
3010 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003011 int end = length;
3012 if ( (length == -1) || (length > str->length() - start) )
3013 end = str->length() - start;
3014 if (end < 0) return 0;
3015 write_input_buffer.Reset(start, *str);
3016 int i;
3017 for (i = 0; i < end; i++) {
3018 char c = static_cast<char>(write_input_buffer.GetNext());
3019 if (c == '\0') c = ' ';
3020 buffer[i] = c;
3021 }
3022 if (length == -1 || i < length)
3023 buffer[i] = '\0';
3024 return i;
3025}
3026
3027
Steve Block6ded16b2010-05-10 14:33:55 +01003028int String::Write(uint16_t* buffer,
3029 int start,
3030 int length,
3031 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003032 if (IsDeadCheck("v8::String::Write()")) return 0;
3033 LOG_API("String::Write");
3034 ENTER_V8;
3035 ASSERT(start >= 0 && length >= -1);
3036 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003037 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003038 if (hints & HINT_MANY_WRITES_EXPECTED) {
3039 // Flatten the string for efficiency. This applies whether we are
3040 // using StringInputBuffer or Get(i) to access the characters.
3041 str->TryFlatten();
3042 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003043 int end = length;
3044 if ( (length == -1) || (length > str->length() - start) )
3045 end = str->length() - start;
3046 if (end < 0) return 0;
3047 i::String::WriteToFlat(*str, buffer, start, end);
3048 if (length == -1 || end < length)
3049 buffer[end] = '\0';
3050 return end;
3051}
3052
3053
3054bool v8::String::IsExternal() const {
3055 EnsureInitialized("v8::String::IsExternal()");
3056 i::Handle<i::String> str = Utils::OpenHandle(this);
3057 return i::StringShape(*str).IsExternalTwoByte();
3058}
3059
3060
3061bool v8::String::IsExternalAscii() const {
3062 EnsureInitialized("v8::String::IsExternalAscii()");
3063 i::Handle<i::String> str = Utils::OpenHandle(this);
3064 return i::StringShape(*str).IsExternalAscii();
3065}
3066
3067
3068void v8::String::VerifyExternalStringResource(
3069 v8::String::ExternalStringResource* value) const {
3070 i::Handle<i::String> str = Utils::OpenHandle(this);
3071 v8::String::ExternalStringResource* expected;
3072 if (i::StringShape(*str).IsExternalTwoByte()) {
3073 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
3074 expected = reinterpret_cast<ExternalStringResource*>(resource);
3075 } else {
3076 expected = NULL;
3077 }
3078 CHECK_EQ(expected, value);
3079}
3080
3081
3082v8::String::ExternalAsciiStringResource*
3083 v8::String::GetExternalAsciiStringResource() const {
3084 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
3085 i::Handle<i::String> str = Utils::OpenHandle(this);
3086 if (i::StringShape(*str).IsExternalAscii()) {
3087 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
3088 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
3089 } else {
3090 return NULL;
3091 }
3092}
3093
3094
3095double Number::Value() const {
3096 if (IsDeadCheck("v8::Number::Value()")) return 0;
3097 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3098 return obj->Number();
3099}
3100
3101
3102bool Boolean::Value() const {
3103 if (IsDeadCheck("v8::Boolean::Value()")) return false;
3104 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3105 return obj->IsTrue();
3106}
3107
3108
3109int64_t Integer::Value() const {
3110 if (IsDeadCheck("v8::Integer::Value()")) return 0;
3111 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3112 if (obj->IsSmi()) {
3113 return i::Smi::cast(*obj)->value();
3114 } else {
3115 return static_cast<int64_t>(obj->Number());
3116 }
3117}
3118
3119
3120int32_t Int32::Value() const {
3121 if (IsDeadCheck("v8::Int32::Value()")) return 0;
3122 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3123 if (obj->IsSmi()) {
3124 return i::Smi::cast(*obj)->value();
3125 } else {
3126 return static_cast<int32_t>(obj->Number());
3127 }
3128}
3129
3130
Steve Block6ded16b2010-05-10 14:33:55 +01003131uint32_t Uint32::Value() const {
3132 if (IsDeadCheck("v8::Uint32::Value()")) return 0;
3133 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3134 if (obj->IsSmi()) {
3135 return i::Smi::cast(*obj)->value();
3136 } else {
3137 return static_cast<uint32_t>(obj->Number());
3138 }
3139}
3140
3141
Steve Blocka7e24c12009-10-30 11:49:00 +00003142int v8::Object::InternalFieldCount() {
3143 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
3144 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3145 return obj->GetInternalFieldCount();
3146}
3147
3148
3149Local<Value> v8::Object::CheckedGetInternalField(int index) {
3150 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
3151 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3152 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3153 "v8::Object::GetInternalField()",
3154 "Reading internal field out of bounds")) {
3155 return Local<Value>();
3156 }
3157 i::Handle<i::Object> value(obj->GetInternalField(index));
3158 Local<Value> result = Utils::ToLocal(value);
3159#ifdef DEBUG
3160 Local<Value> unchecked = UncheckedGetInternalField(index);
3161 ASSERT(unchecked.IsEmpty() || (unchecked == result));
3162#endif
3163 return result;
3164}
3165
3166
3167void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
3168 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
3169 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3170 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3171 "v8::Object::SetInternalField()",
3172 "Writing internal field out of bounds")) {
3173 return;
3174 }
3175 ENTER_V8;
3176 i::Handle<i::Object> val = Utils::OpenHandle(*value);
3177 obj->SetInternalField(index, *val);
3178}
3179
3180
3181void v8::Object::SetPointerInInternalField(int index, void* value) {
Steve Block6ded16b2010-05-10 14:33:55 +01003182 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003183 i::Object* as_object = reinterpret_cast<i::Object*>(value);
3184 if (as_object->IsSmi()) {
3185 Utils::OpenHandle(this)->SetInternalField(index, as_object);
3186 return;
3187 }
3188 HandleScope scope;
3189 i::Handle<i::Proxy> proxy =
3190 i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
3191 if (!proxy.is_null())
3192 Utils::OpenHandle(this)->SetInternalField(index, *proxy);
Steve Blocka7e24c12009-10-30 11:49:00 +00003193}
3194
3195
3196// --- E n v i r o n m e n t ---
3197
3198bool v8::V8::Initialize() {
3199 if (i::V8::IsRunning()) return true;
3200 ENTER_V8;
3201 HandleScope scope;
Steve Blockd0582a62009-12-15 09:54:21 +00003202 if (i::Snapshot::Initialize()) return true;
3203 return i::V8::Initialize(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00003204}
3205
3206
3207bool v8::V8::Dispose() {
3208 i::V8::TearDown();
3209 return true;
3210}
3211
3212
Steve Block3ce2e202009-11-05 08:53:23 +00003213HeapStatistics::HeapStatistics(): total_heap_size_(0), used_heap_size_(0) { }
3214
3215
3216void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
3217 heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
3218 heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
3219}
3220
3221
3222bool v8::V8::IdleNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003223 // Returning true tells the caller that it need not
3224 // continue to call IdleNotification.
3225 if (!i::V8::IsRunning()) return true;
Steve Block3ce2e202009-11-05 08:53:23 +00003226 return i::V8::IdleNotification();
Steve Blocka7e24c12009-10-30 11:49:00 +00003227}
3228
3229
3230void v8::V8::LowMemoryNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003231 if (!i::V8::IsRunning()) return;
3232 i::Heap::CollectAllGarbage(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00003233}
3234
3235
Steve Block6ded16b2010-05-10 14:33:55 +01003236int v8::V8::ContextDisposedNotification() {
3237 if (!i::V8::IsRunning()) return 0;
3238 return i::Heap::NotifyContextDisposed();
3239}
3240
3241
Steve Blocka7e24c12009-10-30 11:49:00 +00003242const char* v8::V8::GetVersion() {
3243 static v8::internal::EmbeddedVector<char, 128> buffer;
3244 v8::internal::Version::GetString(buffer);
3245 return buffer.start();
3246}
3247
3248
3249static i::Handle<i::FunctionTemplateInfo>
3250 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
3251 if (templ->constructor()->IsUndefined()) {
3252 Local<FunctionTemplate> constructor = FunctionTemplate::New();
3253 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
3254 templ->set_constructor(*Utils::OpenHandle(*constructor));
3255 }
3256 return i::Handle<i::FunctionTemplateInfo>(
3257 i::FunctionTemplateInfo::cast(templ->constructor()));
3258}
3259
3260
3261Persistent<Context> v8::Context::New(
3262 v8::ExtensionConfiguration* extensions,
3263 v8::Handle<ObjectTemplate> global_template,
3264 v8::Handle<Value> global_object) {
3265 EnsureInitialized("v8::Context::New()");
3266 LOG_API("Context::New");
3267 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
3268
3269 // Enter V8 via an ENTER_V8 scope.
3270 i::Handle<i::Context> env;
3271 {
3272 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003273 v8::Handle<ObjectTemplate> proxy_template = global_template;
3274 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
3275 i::Handle<i::FunctionTemplateInfo> global_constructor;
3276
3277 if (!global_template.IsEmpty()) {
3278 // Make sure that the global_template has a constructor.
3279 global_constructor =
3280 EnsureConstructor(Utils::OpenHandle(*global_template));
3281
3282 // Create a fresh template for the global proxy object.
3283 proxy_template = ObjectTemplate::New();
3284 proxy_constructor =
3285 EnsureConstructor(Utils::OpenHandle(*proxy_template));
3286
3287 // Set the global template to be the prototype template of
3288 // global proxy template.
3289 proxy_constructor->set_prototype_template(
3290 *Utils::OpenHandle(*global_template));
3291
3292 // Migrate security handlers from global_template to
3293 // proxy_template. Temporarily removing access check
3294 // information from the global template.
3295 if (!global_constructor->access_check_info()->IsUndefined()) {
3296 proxy_constructor->set_access_check_info(
3297 global_constructor->access_check_info());
3298 proxy_constructor->set_needs_access_check(
3299 global_constructor->needs_access_check());
3300 global_constructor->set_needs_access_check(false);
3301 global_constructor->set_access_check_info(i::Heap::undefined_value());
3302 }
3303 }
3304
3305 // Create the environment.
3306 env = i::Bootstrapper::CreateEnvironment(
3307 Utils::OpenHandle(*global_object),
3308 proxy_template,
3309 extensions);
3310
3311 // Restore the access check info on the global template.
3312 if (!global_template.IsEmpty()) {
3313 ASSERT(!global_constructor.is_null());
3314 ASSERT(!proxy_constructor.is_null());
3315 global_constructor->set_access_check_info(
3316 proxy_constructor->access_check_info());
3317 global_constructor->set_needs_access_check(
3318 proxy_constructor->needs_access_check());
3319 }
3320 }
3321 // Leave V8.
3322
3323 if (env.is_null())
3324 return Persistent<Context>();
3325 return Persistent<Context>(Utils::ToLocal(env));
3326}
3327
3328
3329void v8::Context::SetSecurityToken(Handle<Value> token) {
3330 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
3331 ENTER_V8;
3332 i::Handle<i::Context> env = Utils::OpenHandle(this);
3333 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
3334 env->set_security_token(*token_handle);
3335}
3336
3337
3338void v8::Context::UseDefaultSecurityToken() {
3339 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
3340 ENTER_V8;
3341 i::Handle<i::Context> env = Utils::OpenHandle(this);
3342 env->set_security_token(env->global());
3343}
3344
3345
3346Handle<Value> v8::Context::GetSecurityToken() {
3347 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
3348 i::Handle<i::Context> env = Utils::OpenHandle(this);
3349 i::Object* security_token = env->security_token();
3350 i::Handle<i::Object> token_handle(security_token);
3351 return Utils::ToLocal(token_handle);
3352}
3353
3354
3355bool Context::HasOutOfMemoryException() {
3356 i::Handle<i::Context> env = Utils::OpenHandle(this);
3357 return env->has_out_of_memory();
3358}
3359
3360
3361bool Context::InContext() {
3362 return i::Top::context() != NULL;
3363}
3364
3365
3366v8::Local<v8::Context> Context::GetEntered() {
3367 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
3368 i::Handle<i::Object> last = thread_local.LastEnteredContext();
3369 if (last.is_null()) return Local<Context>();
3370 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
3371 return Utils::ToLocal(context);
3372}
3373
3374
3375v8::Local<v8::Context> Context::GetCurrent() {
3376 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
Steve Block3ce2e202009-11-05 08:53:23 +00003377 i::Handle<i::Object> current = i::Top::global_context();
3378 if (current.is_null()) return Local<Context>();
3379 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
Steve Blocka7e24c12009-10-30 11:49:00 +00003380 return Utils::ToLocal(context);
3381}
3382
3383
3384v8::Local<v8::Context> Context::GetCalling() {
3385 if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
3386 i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
3387 if (calling.is_null()) return Local<Context>();
3388 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
3389 return Utils::ToLocal(context);
3390}
3391
3392
3393v8::Local<v8::Object> Context::Global() {
3394 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
3395 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3396 i::Handle<i::Context> context =
3397 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3398 i::Handle<i::Object> global(context->global_proxy());
3399 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
3400}
3401
3402
3403void Context::DetachGlobal() {
3404 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
3405 ENTER_V8;
3406 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3407 i::Handle<i::Context> context =
3408 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3409 i::Bootstrapper::DetachGlobal(context);
3410}
3411
3412
Andrei Popescu74b3c142010-03-29 12:03:09 +01003413void Context::ReattachGlobal(Handle<Object> global_object) {
3414 if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
3415 ENTER_V8;
3416 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3417 i::Handle<i::Context> context =
3418 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3419 i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
3420}
3421
3422
Steve Blocka7e24c12009-10-30 11:49:00 +00003423Local<v8::Object> ObjectTemplate::NewInstance() {
3424 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
3425 LOG_API("ObjectTemplate::NewInstance");
3426 ENTER_V8;
3427 EXCEPTION_PREAMBLE();
3428 i::Handle<i::Object> obj =
3429 i::Execution::InstantiateObject(Utils::OpenHandle(this),
3430 &has_pending_exception);
3431 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
3432 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3433}
3434
3435
3436Local<v8::Function> FunctionTemplate::GetFunction() {
3437 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
3438 return Local<v8::Function>());
3439 LOG_API("FunctionTemplate::GetFunction");
3440 ENTER_V8;
3441 EXCEPTION_PREAMBLE();
3442 i::Handle<i::Object> obj =
3443 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3444 &has_pending_exception);
3445 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
3446 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3447}
3448
3449
3450bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3451 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
3452 i::Object* obj = *Utils::OpenHandle(*value);
3453 return obj->IsInstanceOf(*Utils::OpenHandle(this));
3454}
3455
3456
3457static Local<External> ExternalNewImpl(void* data) {
3458 return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
3459}
3460
3461static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3462 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3463}
3464
3465
Steve Blocka7e24c12009-10-30 11:49:00 +00003466Local<Value> v8::External::Wrap(void* data) {
3467 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3468 LOG_API("External::Wrap");
3469 EnsureInitialized("v8::External::Wrap()");
3470 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003471 i::Object* as_object = reinterpret_cast<i::Object*>(data);
3472 if (as_object->IsSmi()) {
3473 return Utils::ToLocal(i::Handle<i::Object>(as_object));
Steve Blocka7e24c12009-10-30 11:49:00 +00003474 }
3475 return ExternalNewImpl(data);
3476}
3477
3478
Steve Block3ce2e202009-11-05 08:53:23 +00003479void* v8::Object::SlowGetPointerFromInternalField(int index) {
3480 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3481 i::Object* value = obj->GetInternalField(index);
3482 if (value->IsSmi()) {
3483 return value;
3484 } else if (value->IsProxy()) {
3485 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3486 } else {
3487 return NULL;
3488 }
3489}
3490
3491
Steve Blocka7e24c12009-10-30 11:49:00 +00003492void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3493 if (IsDeadCheck("v8::External::Unwrap()")) return 0;
3494 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3495 void* result;
3496 if (obj->IsSmi()) {
3497 // The external value was an aligned pointer.
Steve Block3ce2e202009-11-05 08:53:23 +00003498 result = *obj;
Steve Blocka7e24c12009-10-30 11:49:00 +00003499 } else if (obj->IsProxy()) {
3500 result = ExternalValueImpl(obj);
3501 } else {
3502 result = NULL;
3503 }
3504 ASSERT_EQ(result, QuickUnwrap(wrapper));
3505 return result;
3506}
3507
3508
3509Local<External> v8::External::New(void* data) {
3510 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3511 LOG_API("External::New");
3512 EnsureInitialized("v8::External::New()");
3513 ENTER_V8;
3514 return ExternalNewImpl(data);
3515}
3516
3517
3518void* External::Value() const {
3519 if (IsDeadCheck("v8::External::Value()")) return 0;
3520 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3521 return ExternalValueImpl(obj);
3522}
3523
3524
3525Local<String> v8::String::Empty() {
3526 EnsureInitialized("v8::String::Empty()");
3527 LOG_API("String::Empty()");
3528 return Utils::ToLocal(i::Factory::empty_symbol());
3529}
3530
3531
3532Local<String> v8::String::New(const char* data, int length) {
3533 EnsureInitialized("v8::String::New()");
3534 LOG_API("String::New(char)");
3535 if (length == 0) return Empty();
3536 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003537 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003538 i::Handle<i::String> result =
3539 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3540 return Utils::ToLocal(result);
3541}
3542
3543
Steve Block3ce2e202009-11-05 08:53:23 +00003544Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3545 EnsureInitialized("v8::String::New()");
3546 LOG_API("String::New(char)");
3547 ENTER_V8;
3548 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3549 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3550 i::Handle<i::String> result = i::Factory::NewConsString(left_string,
3551 right_string);
3552 return Utils::ToLocal(result);
3553}
3554
3555
Steve Blocka7e24c12009-10-30 11:49:00 +00003556Local<String> v8::String::NewUndetectable(const char* data, int length) {
3557 EnsureInitialized("v8::String::NewUndetectable()");
3558 LOG_API("String::NewUndetectable(char)");
3559 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003560 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003561 i::Handle<i::String> result =
3562 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3563 result->MarkAsUndetectable();
3564 return Utils::ToLocal(result);
3565}
3566
3567
3568static int TwoByteStringLength(const uint16_t* data) {
3569 int length = 0;
3570 while (data[length] != '\0') length++;
3571 return length;
3572}
3573
3574
3575Local<String> v8::String::New(const uint16_t* data, int length) {
3576 EnsureInitialized("v8::String::New()");
3577 LOG_API("String::New(uint16_)");
3578 if (length == 0) return Empty();
3579 ENTER_V8;
3580 if (length == -1) length = TwoByteStringLength(data);
3581 i::Handle<i::String> result =
3582 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3583 return Utils::ToLocal(result);
3584}
3585
3586
3587Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
3588 EnsureInitialized("v8::String::NewUndetectable()");
3589 LOG_API("String::NewUndetectable(uint16_)");
3590 ENTER_V8;
3591 if (length == -1) length = TwoByteStringLength(data);
3592 i::Handle<i::String> result =
3593 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3594 result->MarkAsUndetectable();
3595 return Utils::ToLocal(result);
3596}
3597
3598
3599i::Handle<i::String> NewExternalStringHandle(
3600 v8::String::ExternalStringResource* resource) {
3601 i::Handle<i::String> result =
3602 i::Factory::NewExternalStringFromTwoByte(resource);
3603 return result;
3604}
3605
3606
3607i::Handle<i::String> NewExternalAsciiStringHandle(
3608 v8::String::ExternalAsciiStringResource* resource) {
3609 i::Handle<i::String> result =
3610 i::Factory::NewExternalStringFromAscii(resource);
3611 return result;
3612}
3613
3614
Steve Blocka7e24c12009-10-30 11:49:00 +00003615Local<String> v8::String::NewExternal(
3616 v8::String::ExternalStringResource* resource) {
3617 EnsureInitialized("v8::String::NewExternal()");
3618 LOG_API("String::NewExternal");
3619 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003620 i::Handle<i::String> result = NewExternalStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003621 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003622 return Utils::ToLocal(result);
3623}
3624
3625
3626bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3627 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3628 if (this->IsExternal()) return false; // Already an external string.
3629 ENTER_V8;
3630 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003631 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003632 bool result = obj->MakeExternal(resource);
3633 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003634 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003635 }
3636 return result;
3637}
3638
3639
3640Local<String> v8::String::NewExternal(
3641 v8::String::ExternalAsciiStringResource* resource) {
3642 EnsureInitialized("v8::String::NewExternal()");
3643 LOG_API("String::NewExternal");
3644 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003645 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003646 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003647 return Utils::ToLocal(result);
3648}
3649
3650
3651bool v8::String::MakeExternal(
3652 v8::String::ExternalAsciiStringResource* resource) {
3653 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3654 if (this->IsExternal()) return false; // Already an external string.
3655 ENTER_V8;
3656 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003657 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003658 bool result = obj->MakeExternal(resource);
3659 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003660 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003661 }
3662 return result;
3663}
3664
3665
3666bool v8::String::CanMakeExternal() {
3667 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3668 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003669 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003670 int size = obj->Size(); // Byte size of the original string.
3671 if (size < i::ExternalString::kSize)
3672 return false;
3673 i::StringShape shape(*obj);
3674 return !shape.IsExternal();
3675}
3676
3677
3678Local<v8::Object> v8::Object::New() {
3679 EnsureInitialized("v8::Object::New()");
3680 LOG_API("Object::New");
3681 ENTER_V8;
3682 i::Handle<i::JSObject> obj =
3683 i::Factory::NewJSObject(i::Top::object_function());
3684 return Utils::ToLocal(obj);
3685}
3686
3687
3688Local<v8::Value> v8::Date::New(double time) {
3689 EnsureInitialized("v8::Date::New()");
3690 LOG_API("Date::New");
Steve Blockd0582a62009-12-15 09:54:21 +00003691 if (isnan(time)) {
3692 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3693 time = i::OS::nan_value();
3694 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003695 ENTER_V8;
3696 EXCEPTION_PREAMBLE();
3697 i::Handle<i::Object> obj =
3698 i::Execution::NewDate(time, &has_pending_exception);
3699 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3700 return Utils::ToLocal(obj);
3701}
3702
3703
3704double v8::Date::NumberValue() const {
3705 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3706 LOG_API("Date::NumberValue");
3707 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3708 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3709 return jsvalue->value()->Number();
3710}
3711
3712
3713Local<v8::Array> v8::Array::New(int length) {
3714 EnsureInitialized("v8::Array::New()");
3715 LOG_API("Array::New");
3716 ENTER_V8;
3717 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3718 return Utils::ToLocal(obj);
3719}
3720
3721
3722uint32_t v8::Array::Length() const {
3723 if (IsDeadCheck("v8::Array::Length()")) return 0;
3724 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3725 i::Object* length = obj->length();
3726 if (length->IsSmi()) {
3727 return i::Smi::cast(length)->value();
3728 } else {
3729 return static_cast<uint32_t>(length->Number());
3730 }
3731}
3732
3733
3734Local<Object> Array::CloneElementAt(uint32_t index) {
3735 ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3736 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3737 if (!self->HasFastElements()) {
3738 return Local<Object>();
3739 }
3740 i::FixedArray* elms = i::FixedArray::cast(self->elements());
3741 i::Object* paragon = elms->get(index);
3742 if (!paragon->IsJSObject()) {
3743 return Local<Object>();
3744 }
3745 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3746 EXCEPTION_PREAMBLE();
Steve Block6ded16b2010-05-10 14:33:55 +01003747 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003748 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3749 has_pending_exception = result.is_null();
3750 EXCEPTION_BAILOUT_CHECK(Local<Object>());
3751 return Utils::ToLocal(result);
3752}
3753
3754
3755Local<String> v8::String::NewSymbol(const char* data, int length) {
3756 EnsureInitialized("v8::String::NewSymbol()");
3757 LOG_API("String::NewSymbol(char)");
3758 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003759 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003760 i::Handle<i::String> result =
3761 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3762 return Utils::ToLocal(result);
3763}
3764
3765
3766Local<Number> v8::Number::New(double value) {
3767 EnsureInitialized("v8::Number::New()");
Steve Blockd0582a62009-12-15 09:54:21 +00003768 if (isnan(value)) {
3769 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3770 value = i::OS::nan_value();
3771 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003772 ENTER_V8;
3773 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3774 return Utils::NumberToLocal(result);
3775}
3776
3777
3778Local<Integer> v8::Integer::New(int32_t value) {
3779 EnsureInitialized("v8::Integer::New()");
3780 if (i::Smi::IsValid(value)) {
3781 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3782 }
3783 ENTER_V8;
3784 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3785 return Utils::IntegerToLocal(result);
3786}
3787
3788
Steve Block3ce2e202009-11-05 08:53:23 +00003789Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
3790 bool fits_into_int32_t = (value & (1 << 31)) == 0;
3791 if (fits_into_int32_t) {
3792 return Integer::New(static_cast<int32_t>(value));
3793 }
3794 ENTER_V8;
3795 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3796 return Utils::IntegerToLocal(result);
3797}
3798
3799
Steve Blocka7e24c12009-10-30 11:49:00 +00003800void V8::IgnoreOutOfMemoryException() {
3801 thread_local.set_ignore_out_of_memory(true);
3802}
3803
3804
3805bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
3806 EnsureInitialized("v8::V8::AddMessageListener()");
3807 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
3808 ENTER_V8;
3809 HandleScope scope;
3810 NeanderArray listeners(i::Factory::message_listeners());
3811 NeanderObject obj(2);
3812 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
3813 obj.set(1, data.IsEmpty() ?
3814 i::Heap::undefined_value() :
3815 *Utils::OpenHandle(*data));
3816 listeners.add(obj.value());
3817 return true;
3818}
3819
3820
3821void V8::RemoveMessageListeners(MessageCallback that) {
3822 EnsureInitialized("v8::V8::RemoveMessageListener()");
3823 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
3824 ENTER_V8;
3825 HandleScope scope;
3826 NeanderArray listeners(i::Factory::message_listeners());
3827 for (int i = 0; i < listeners.length(); i++) {
3828 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
3829
3830 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
3831 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
3832 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
3833 listeners.set(i, i::Heap::undefined_value());
3834 }
3835 }
3836}
3837
3838
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003839void V8::SetCaptureStackTraceForUncaughtExceptions(
3840 bool capture,
3841 int frame_limit,
3842 StackTrace::StackTraceOptions options) {
3843 i::Top::SetCaptureStackTraceForUncaughtExceptions(
3844 capture,
3845 frame_limit,
3846 options);
3847}
3848
3849
Steve Blocka7e24c12009-10-30 11:49:00 +00003850void V8::SetCounterFunction(CounterLookupCallback callback) {
3851 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
3852 i::StatsTable::SetCounterFunction(callback);
3853}
3854
3855void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
3856 if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
3857 i::StatsTable::SetCreateHistogramFunction(callback);
3858}
3859
3860void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
3861 if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
3862 i::StatsTable::SetAddHistogramSampleFunction(callback);
3863}
3864
3865void V8::EnableSlidingStateWindow() {
3866 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
3867 i::Logger::EnableSlidingStateWindow();
3868}
3869
3870
3871void V8::SetFailedAccessCheckCallbackFunction(
3872 FailedAccessCheckCallback callback) {
3873 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
3874 i::Top::SetFailedAccessCheckCallback(callback);
3875}
3876
3877
3878void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
3879 if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
3880 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
3881 i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
3882}
3883
3884
3885int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
3886 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
3887 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
3888}
3889
3890
3891void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
3892 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
3893 i::Heap::SetGlobalGCPrologueCallback(callback);
3894}
3895
3896
3897void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
3898 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
3899 i::Heap::SetGlobalGCEpilogueCallback(callback);
3900}
3901
3902
Steve Block6ded16b2010-05-10 14:33:55 +01003903void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
3904 if (IsDeadCheck("v8::V8::AddGCPrologueCallback()")) return;
3905 i::Heap::AddGCPrologueCallback(callback, gc_type);
3906}
3907
3908
3909void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
3910 if (IsDeadCheck("v8::V8::RemoveGCPrologueCallback()")) return;
3911 i::Heap::RemoveGCPrologueCallback(callback);
3912}
3913
3914
3915void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
3916 if (IsDeadCheck("v8::V8::AddGCEpilogueCallback()")) return;
3917 i::Heap::AddGCEpilogueCallback(callback, gc_type);
3918}
3919
3920
3921void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
3922 if (IsDeadCheck("v8::V8::RemoveGCEpilogueCallback()")) return;
3923 i::Heap::RemoveGCEpilogueCallback(callback);
3924}
3925
3926
Iain Merrick9ac36c92010-09-13 15:29:50 +01003927void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
3928 ObjectSpace space,
3929 AllocationAction action) {
3930 if (IsDeadCheck("v8::V8::AddMemoryAllocationCallback()")) return;
3931 i::MemoryAllocator::AddMemoryAllocationCallback(callback,
3932 space,
3933 action);
3934}
3935
3936
3937void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
3938 if (IsDeadCheck("v8::V8::RemoveMemoryAllocationCallback()")) return;
3939 i::MemoryAllocator::RemoveMemoryAllocationCallback(callback);
3940}
3941
3942
Steve Blocka7e24c12009-10-30 11:49:00 +00003943void V8::PauseProfiler() {
3944#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003945 PauseProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003946#endif
3947}
3948
3949
3950void V8::ResumeProfiler() {
3951#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003952 ResumeProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003953#endif
3954}
3955
3956
3957bool V8::IsProfilerPaused() {
3958#ifdef ENABLE_LOGGING_AND_PROFILING
3959 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
3960#else
3961 return true;
3962#endif
3963}
3964
3965
Andrei Popescu402d9372010-02-26 13:31:12 +00003966void V8::ResumeProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003967#ifdef ENABLE_LOGGING_AND_PROFILING
3968 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
3969 // Snapshot mode: resume modules, perform GC, then pause only
3970 // those modules which haven't been started prior to making a
3971 // snapshot.
3972
Steve Block6ded16b2010-05-10 14:33:55 +01003973 // Make a GC prior to taking a snapshot.
3974 i::Heap::CollectAllGarbage(false);
Steve Blocka7e24c12009-10-30 11:49:00 +00003975 // Reset snapshot flag and CPU module flags.
3976 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
3977 const int current_flags = i::Logger::GetActiveProfilerModules();
Andrei Popescu402d9372010-02-26 13:31:12 +00003978 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003979 i::Heap::CollectAllGarbage(false);
Andrei Popescu402d9372010-02-26 13:31:12 +00003980 i::Logger::PauseProfiler(~current_flags & flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003981 } else {
Andrei Popescu402d9372010-02-26 13:31:12 +00003982 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003983 }
3984#endif
3985}
3986
3987
Andrei Popescu402d9372010-02-26 13:31:12 +00003988void V8::PauseProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003989#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003990 i::Logger::PauseProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003991#endif
3992}
3993
3994
3995int V8::GetActiveProfilerModules() {
3996#ifdef ENABLE_LOGGING_AND_PROFILING
3997 return i::Logger::GetActiveProfilerModules();
3998#else
3999 return PROFILER_MODULE_NONE;
4000#endif
4001}
4002
4003
4004int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
4005#ifdef ENABLE_LOGGING_AND_PROFILING
Steve Block6ded16b2010-05-10 14:33:55 +01004006 ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
Steve Blocka7e24c12009-10-30 11:49:00 +00004007 return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
4008#endif
4009 return 0;
4010}
4011
4012
4013int V8::GetCurrentThreadId() {
4014 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
4015 EnsureInitialized("V8::GetCurrentThreadId()");
4016 return i::Top::thread_id();
4017}
4018
4019
4020void V8::TerminateExecution(int thread_id) {
4021 if (!i::V8::IsRunning()) return;
4022 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
4023 // If the thread_id identifies the current thread just terminate
4024 // execution right away. Otherwise, ask the thread manager to
4025 // terminate the thread with the given id if any.
4026 if (thread_id == i::Top::thread_id()) {
4027 i::StackGuard::TerminateExecution();
4028 } else {
4029 i::ThreadManager::TerminateExecution(thread_id);
4030 }
4031}
4032
4033
4034void V8::TerminateExecution() {
4035 if (!i::V8::IsRunning()) return;
4036 i::StackGuard::TerminateExecution();
4037}
4038
4039
Steve Block6ded16b2010-05-10 14:33:55 +01004040bool V8::IsExecutionTerminating() {
4041 if (!i::V8::IsRunning()) return false;
4042 if (i::Top::has_scheduled_exception()) {
4043 return i::Top::scheduled_exception() == i::Heap::termination_exception();
4044 }
4045 return false;
4046}
4047
4048
Steve Blocka7e24c12009-10-30 11:49:00 +00004049String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
4050 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
4051 if (obj.IsEmpty()) {
4052 str_ = NULL;
4053 length_ = 0;
4054 return;
4055 }
4056 ENTER_V8;
4057 HandleScope scope;
4058 TryCatch try_catch;
4059 Handle<String> str = obj->ToString();
4060 if (str.IsEmpty()) {
4061 str_ = NULL;
4062 length_ = 0;
4063 } else {
4064 length_ = str->Utf8Length();
4065 str_ = i::NewArray<char>(length_ + 1);
4066 str->WriteUtf8(str_);
4067 }
4068}
4069
4070
4071String::Utf8Value::~Utf8Value() {
4072 i::DeleteArray(str_);
4073}
4074
4075
4076String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
4077 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
4078 if (obj.IsEmpty()) {
4079 str_ = NULL;
4080 length_ = 0;
4081 return;
4082 }
4083 ENTER_V8;
4084 HandleScope scope;
4085 TryCatch try_catch;
4086 Handle<String> str = obj->ToString();
4087 if (str.IsEmpty()) {
4088 str_ = NULL;
4089 length_ = 0;
4090 } else {
4091 length_ = str->Length();
4092 str_ = i::NewArray<char>(length_ + 1);
4093 str->WriteAscii(str_);
4094 }
4095}
4096
4097
4098String::AsciiValue::~AsciiValue() {
4099 i::DeleteArray(str_);
4100}
4101
4102
4103String::Value::Value(v8::Handle<v8::Value> obj) {
4104 EnsureInitialized("v8::String::Value::Value()");
4105 if (obj.IsEmpty()) {
4106 str_ = NULL;
4107 length_ = 0;
4108 return;
4109 }
4110 ENTER_V8;
4111 HandleScope scope;
4112 TryCatch try_catch;
4113 Handle<String> str = obj->ToString();
4114 if (str.IsEmpty()) {
4115 str_ = NULL;
4116 length_ = 0;
4117 } else {
4118 length_ = str->Length();
4119 str_ = i::NewArray<uint16_t>(length_ + 1);
4120 str->Write(str_);
4121 }
4122}
4123
4124
4125String::Value::~Value() {
4126 i::DeleteArray(str_);
4127}
4128
4129Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
4130 LOG_API("RangeError");
4131 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
4132 ENTER_V8;
4133 i::Object* error;
4134 {
4135 HandleScope scope;
4136 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4137 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
4138 error = *result;
4139 }
4140 i::Handle<i::Object> result(error);
4141 return Utils::ToLocal(result);
4142}
4143
4144Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
4145 LOG_API("ReferenceError");
4146 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
4147 ENTER_V8;
4148 i::Object* error;
4149 {
4150 HandleScope scope;
4151 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4152 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
4153 error = *result;
4154 }
4155 i::Handle<i::Object> result(error);
4156 return Utils::ToLocal(result);
4157}
4158
4159Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
4160 LOG_API("SyntaxError");
4161 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
4162 ENTER_V8;
4163 i::Object* error;
4164 {
4165 HandleScope scope;
4166 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4167 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
4168 error = *result;
4169 }
4170 i::Handle<i::Object> result(error);
4171 return Utils::ToLocal(result);
4172}
4173
4174Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
4175 LOG_API("TypeError");
4176 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
4177 ENTER_V8;
4178 i::Object* error;
4179 {
4180 HandleScope scope;
4181 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4182 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
4183 error = *result;
4184 }
4185 i::Handle<i::Object> result(error);
4186 return Utils::ToLocal(result);
4187}
4188
4189Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
4190 LOG_API("Error");
4191 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
4192 ENTER_V8;
4193 i::Object* error;
4194 {
4195 HandleScope scope;
4196 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4197 i::Handle<i::Object> result = i::Factory::NewError(message);
4198 error = *result;
4199 }
4200 i::Handle<i::Object> result(error);
4201 return Utils::ToLocal(result);
4202}
4203
4204
4205// --- D e b u g S u p p o r t ---
4206
4207#ifdef ENABLE_DEBUGGER_SUPPORT
Leon Clarkef7060e22010-06-03 12:02:55 +01004208
4209static v8::Debug::EventCallback event_callback = NULL;
4210
4211static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) {
4212 if (event_callback) {
4213 event_callback(event_details.GetEvent(),
4214 event_details.GetExecutionState(),
4215 event_details.GetEventData(),
4216 event_details.GetCallbackData());
4217 }
4218}
4219
4220
Steve Blocka7e24c12009-10-30 11:49:00 +00004221bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
4222 EnsureInitialized("v8::Debug::SetDebugEventListener()");
4223 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4224 ENTER_V8;
Leon Clarkef7060e22010-06-03 12:02:55 +01004225
4226 event_callback = that;
4227
4228 HandleScope scope;
4229 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4230 if (that != NULL) {
4231 proxy = i::Factory::NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
4232 }
4233 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4234 return true;
4235}
4236
4237
4238bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
4239 EnsureInitialized("v8::Debug::SetDebugEventListener2()");
4240 ON_BAILOUT("v8::Debug::SetDebugEventListener2()", return false);
4241 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004242 HandleScope scope;
4243 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4244 if (that != NULL) {
4245 proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
4246 }
4247 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4248 return true;
4249}
4250
4251
4252bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
4253 Handle<Value> data) {
4254 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4255 ENTER_V8;
4256 i::Debugger::SetEventListener(Utils::OpenHandle(*that),
4257 Utils::OpenHandle(*data));
4258 return true;
4259}
4260
4261
4262void Debug::DebugBreak() {
4263 if (!i::V8::IsRunning()) return;
4264 i::StackGuard::DebugBreak();
4265}
4266
4267
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004268void Debug::DebugBreakForCommand(ClientData* data) {
4269 if (!i::V8::IsRunning()) return;
4270 i::Debugger::EnqueueDebugCommand(data);
4271}
4272
4273
Steve Blocka7e24c12009-10-30 11:49:00 +00004274static v8::Debug::MessageHandler message_handler = NULL;
4275
4276static void MessageHandlerWrapper(const v8::Debug::Message& message) {
4277 if (message_handler) {
4278 v8::String::Value json(message.GetJSON());
4279 message_handler(*json, json.length(), message.GetClientData());
4280 }
4281}
4282
4283
4284void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
4285 bool message_handler_thread) {
4286 EnsureInitialized("v8::Debug::SetMessageHandler");
4287 ENTER_V8;
4288 // Message handler thread not supported any more. Parameter temporally left in
4289 // the API for client compatability reasons.
4290 CHECK(!message_handler_thread);
4291
4292 // TODO(sgjesse) support the old message handler API through a simple wrapper.
4293 message_handler = handler;
4294 if (message_handler != NULL) {
4295 i::Debugger::SetMessageHandler(MessageHandlerWrapper);
4296 } else {
4297 i::Debugger::SetMessageHandler(NULL);
4298 }
4299}
4300
4301
4302void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
4303 EnsureInitialized("v8::Debug::SetMessageHandler");
4304 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004305 i::Debugger::SetMessageHandler(handler);
4306}
4307
4308
4309void Debug::SendCommand(const uint16_t* command, int length,
4310 ClientData* client_data) {
4311 if (!i::V8::IsRunning()) return;
4312 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
4313 client_data);
4314}
4315
4316
4317void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
4318 int period) {
4319 EnsureInitialized("v8::Debug::SetHostDispatchHandler");
4320 ENTER_V8;
4321 i::Debugger::SetHostDispatchHandler(handler, period);
4322}
4323
4324
Steve Blockd0582a62009-12-15 09:54:21 +00004325void Debug::SetDebugMessageDispatchHandler(
Leon Clarkee46be812010-01-19 14:06:41 +00004326 DebugMessageDispatchHandler handler, bool provide_locker) {
Steve Blockd0582a62009-12-15 09:54:21 +00004327 EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
4328 ENTER_V8;
Leon Clarkee46be812010-01-19 14:06:41 +00004329 i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
Steve Blockd0582a62009-12-15 09:54:21 +00004330}
4331
4332
Steve Blocka7e24c12009-10-30 11:49:00 +00004333Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
4334 v8::Handle<v8::Value> data) {
4335 if (!i::V8::IsRunning()) return Local<Value>();
4336 ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
4337 ENTER_V8;
4338 i::Handle<i::Object> result;
4339 EXCEPTION_PREAMBLE();
4340 if (data.IsEmpty()) {
4341 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4342 i::Factory::undefined_value(),
4343 &has_pending_exception);
4344 } else {
4345 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4346 Utils::OpenHandle(*data),
4347 &has_pending_exception);
4348 }
4349 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4350 return Utils::ToLocal(result);
4351}
4352
4353
4354Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
4355 if (!i::V8::IsRunning()) return Local<Value>();
4356 ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
4357 ENTER_V8;
4358 v8::HandleScope scope;
4359 i::Debug::Load();
4360 i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
4361 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
4362 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
4363 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
4364 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
4365 const int kArgc = 1;
4366 v8::Handle<v8::Value> argv[kArgc] = { obj };
4367 EXCEPTION_PREAMBLE();
4368 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
4369 kArgc,
4370 argv);
4371 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4372 return scope.Close(result);
4373}
4374
4375
Leon Clarkee46be812010-01-19 14:06:41 +00004376bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
4377 return i::Debugger::StartAgent(name, port, wait_for_connection);
Steve Blocka7e24c12009-10-30 11:49:00 +00004378}
Leon Clarkee46be812010-01-19 14:06:41 +00004379
4380void Debug::ProcessDebugMessages() {
4381 i::Execution::ProcessDebugMesssages(true);
4382}
4383
Steve Block6ded16b2010-05-10 14:33:55 +01004384Local<Context> Debug::GetDebugContext() {
4385 EnsureInitialized("v8::Debug::GetDebugContext()");
4386 ENTER_V8;
4387 return Utils::ToLocal(i::Debugger::GetDebugContext());
4388}
4389
Steve Blocka7e24c12009-10-30 11:49:00 +00004390#endif // ENABLE_DEBUGGER_SUPPORT
4391
Steve Block6ded16b2010-05-10 14:33:55 +01004392
4393#ifdef ENABLE_LOGGING_AND_PROFILING
4394
4395Handle<String> CpuProfileNode::GetFunctionName() const {
4396 IsDeadCheck("v8::CpuProfileNode::GetFunctionName");
4397 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4398 const i::CodeEntry* entry = node->entry();
4399 if (!entry->has_name_prefix()) {
4400 return Handle<String>(ToApi<String>(
4401 i::Factory::LookupAsciiSymbol(entry->name())));
4402 } else {
4403 return Handle<String>(ToApi<String>(i::Factory::NewConsString(
4404 i::Factory::LookupAsciiSymbol(entry->name_prefix()),
4405 i::Factory::LookupAsciiSymbol(entry->name()))));
4406 }
4407}
4408
4409
4410Handle<String> CpuProfileNode::GetScriptResourceName() const {
4411 IsDeadCheck("v8::CpuProfileNode::GetScriptResourceName");
4412 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4413 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4414 node->entry()->resource_name())));
4415}
4416
4417
4418int CpuProfileNode::GetLineNumber() const {
4419 IsDeadCheck("v8::CpuProfileNode::GetLineNumber");
4420 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
4421}
4422
4423
4424double CpuProfileNode::GetTotalTime() const {
4425 IsDeadCheck("v8::CpuProfileNode::GetTotalTime");
4426 return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis();
4427}
4428
4429
4430double CpuProfileNode::GetSelfTime() const {
4431 IsDeadCheck("v8::CpuProfileNode::GetSelfTime");
4432 return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis();
4433}
4434
4435
4436double CpuProfileNode::GetTotalSamplesCount() const {
4437 IsDeadCheck("v8::CpuProfileNode::GetTotalSamplesCount");
4438 return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
4439}
4440
4441
4442double CpuProfileNode::GetSelfSamplesCount() const {
4443 IsDeadCheck("v8::CpuProfileNode::GetSelfSamplesCount");
4444 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
4445}
4446
4447
4448unsigned CpuProfileNode::GetCallUid() const {
4449 IsDeadCheck("v8::CpuProfileNode::GetCallUid");
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004450 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
Steve Block6ded16b2010-05-10 14:33:55 +01004451}
4452
4453
4454int CpuProfileNode::GetChildrenCount() const {
4455 IsDeadCheck("v8::CpuProfileNode::GetChildrenCount");
4456 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
4457}
4458
4459
4460const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
4461 IsDeadCheck("v8::CpuProfileNode::GetChild");
4462 const i::ProfileNode* child =
4463 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
4464 return reinterpret_cast<const CpuProfileNode*>(child);
4465}
4466
4467
4468unsigned CpuProfile::GetUid() const {
4469 IsDeadCheck("v8::CpuProfile::GetUid");
4470 return reinterpret_cast<const i::CpuProfile*>(this)->uid();
4471}
4472
4473
4474Handle<String> CpuProfile::GetTitle() const {
4475 IsDeadCheck("v8::CpuProfile::GetTitle");
4476 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4477 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4478 profile->title())));
4479}
4480
4481
4482const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
4483 IsDeadCheck("v8::CpuProfile::GetBottomUpRoot");
4484 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4485 return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
4486}
4487
4488
4489const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
4490 IsDeadCheck("v8::CpuProfile::GetTopDownRoot");
4491 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4492 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
4493}
4494
4495
4496int CpuProfiler::GetProfilesCount() {
4497 IsDeadCheck("v8::CpuProfiler::GetProfilesCount");
4498 return i::CpuProfiler::GetProfilesCount();
4499}
4500
4501
Leon Clarkef7060e22010-06-03 12:02:55 +01004502const CpuProfile* CpuProfiler::GetProfile(int index,
4503 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004504 IsDeadCheck("v8::CpuProfiler::GetProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004505 return reinterpret_cast<const CpuProfile*>(
4506 i::CpuProfiler::GetProfile(
4507 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4508 index));
Steve Block6ded16b2010-05-10 14:33:55 +01004509}
4510
4511
Leon Clarkef7060e22010-06-03 12:02:55 +01004512const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
4513 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004514 IsDeadCheck("v8::CpuProfiler::FindProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004515 return reinterpret_cast<const CpuProfile*>(
4516 i::CpuProfiler::FindProfile(
4517 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4518 uid));
Steve Block6ded16b2010-05-10 14:33:55 +01004519}
4520
4521
4522void CpuProfiler::StartProfiling(Handle<String> title) {
4523 IsDeadCheck("v8::CpuProfiler::StartProfiling");
4524 i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
4525}
4526
4527
Leon Clarkef7060e22010-06-03 12:02:55 +01004528const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
4529 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004530 IsDeadCheck("v8::CpuProfiler::StopProfiling");
4531 return reinterpret_cast<const CpuProfile*>(
Leon Clarkef7060e22010-06-03 12:02:55 +01004532 i::CpuProfiler::StopProfiling(
4533 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4534 *Utils::OpenHandle(*title)));
Steve Block6ded16b2010-05-10 14:33:55 +01004535}
4536
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004537
Iain Merrick75681382010-08-19 15:07:18 +01004538static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
4539 return const_cast<i::HeapGraphEdge*>(
4540 reinterpret_cast<const i::HeapGraphEdge*>(edge));
4541}
4542
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004543HeapGraphEdge::Type HeapGraphEdge::GetType() const {
4544 IsDeadCheck("v8::HeapGraphEdge::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004545 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004546}
4547
4548
4549Handle<Value> HeapGraphEdge::GetName() const {
4550 IsDeadCheck("v8::HeapGraphEdge::GetName");
Iain Merrick75681382010-08-19 15:07:18 +01004551 i::HeapGraphEdge* edge = ToInternal(this);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004552 switch (edge->type()) {
Iain Merrick75681382010-08-19 15:07:18 +01004553 case i::HeapGraphEdge::kContextVariable:
4554 case i::HeapGraphEdge::kInternal:
4555 case i::HeapGraphEdge::kProperty:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004556 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4557 edge->name())));
Iain Merrick75681382010-08-19 15:07:18 +01004558 case i::HeapGraphEdge::kElement:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004559 return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt(
4560 edge->index())));
4561 default: UNREACHABLE();
4562 }
4563 return ImplementationUtilities::Undefined();
4564}
4565
4566
4567const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
4568 IsDeadCheck("v8::HeapGraphEdge::GetFromNode");
Iain Merrick75681382010-08-19 15:07:18 +01004569 const i::HeapEntry* from = ToInternal(this)->From();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004570 return reinterpret_cast<const HeapGraphNode*>(from);
4571}
4572
4573
4574const HeapGraphNode* HeapGraphEdge::GetToNode() const {
4575 IsDeadCheck("v8::HeapGraphEdge::GetToNode");
Iain Merrick75681382010-08-19 15:07:18 +01004576 const i::HeapEntry* to = ToInternal(this)->to();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004577 return reinterpret_cast<const HeapGraphNode*>(to);
4578}
4579
4580
Iain Merrick75681382010-08-19 15:07:18 +01004581static i::HeapGraphPath* ToInternal(const HeapGraphPath* path) {
4582 return const_cast<i::HeapGraphPath*>(
4583 reinterpret_cast<const i::HeapGraphPath*>(path));
4584}
4585
4586
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004587int HeapGraphPath::GetEdgesCount() const {
Iain Merrick75681382010-08-19 15:07:18 +01004588 return ToInternal(this)->path()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004589}
4590
4591
4592const HeapGraphEdge* HeapGraphPath::GetEdge(int index) const {
4593 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004594 ToInternal(this)->path()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004595}
4596
4597
4598const HeapGraphNode* HeapGraphPath::GetFromNode() const {
4599 return GetEdgesCount() > 0 ? GetEdge(0)->GetFromNode() : NULL;
4600}
4601
4602
4603const HeapGraphNode* HeapGraphPath::GetToNode() const {
4604 const int count = GetEdgesCount();
4605 return count > 0 ? GetEdge(count - 1)->GetToNode() : NULL;
4606}
4607
4608
Iain Merrick75681382010-08-19 15:07:18 +01004609static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
4610 return const_cast<i::HeapEntry*>(
4611 reinterpret_cast<const i::HeapEntry*>(entry));
4612}
4613
4614
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004615HeapGraphNode::Type HeapGraphNode::GetType() const {
4616 IsDeadCheck("v8::HeapGraphNode::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004617 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004618}
4619
4620
4621Handle<String> HeapGraphNode::GetName() const {
4622 IsDeadCheck("v8::HeapGraphNode::GetName");
4623 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004624 ToInternal(this)->name())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004625}
4626
4627
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004628uint64_t HeapGraphNode::GetId() const {
4629 IsDeadCheck("v8::HeapGraphNode::GetId");
Steve Block791712a2010-08-27 10:21:07 +01004630 ASSERT(ToInternal(this)->snapshot()->type() != i::HeapSnapshot::kAggregated);
Iain Merrick75681382010-08-19 15:07:18 +01004631 return ToInternal(this)->id();
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004632}
4633
4634
Steve Block791712a2010-08-27 10:21:07 +01004635int HeapGraphNode::GetInstancesCount() const {
4636 IsDeadCheck("v8::HeapGraphNode::GetInstancesCount");
4637 ASSERT(ToInternal(this)->snapshot()->type() == i::HeapSnapshot::kAggregated);
4638 return static_cast<int>(ToInternal(this)->id());
4639}
4640
4641
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004642int HeapGraphNode::GetSelfSize() const {
4643 IsDeadCheck("v8::HeapGraphNode::GetSelfSize");
Iain Merrick75681382010-08-19 15:07:18 +01004644 return ToInternal(this)->self_size();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004645}
4646
4647
Iain Merrick75681382010-08-19 15:07:18 +01004648int HeapGraphNode::GetReachableSize() const {
4649 IsDeadCheck("v8::HeapSnapshot::GetReachableSize");
4650 return ToInternal(this)->ReachableSize();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004651}
4652
4653
Iain Merrick75681382010-08-19 15:07:18 +01004654int HeapGraphNode::GetRetainedSize() const {
4655 IsDeadCheck("v8::HeapSnapshot::GetRetainedSize");
4656 return ToInternal(this)->RetainedSize();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004657}
4658
4659
4660int HeapGraphNode::GetChildrenCount() const {
4661 IsDeadCheck("v8::HeapSnapshot::GetChildrenCount");
Iain Merrick75681382010-08-19 15:07:18 +01004662 return ToInternal(this)->children().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004663}
4664
4665
4666const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
4667 IsDeadCheck("v8::HeapSnapshot::GetChild");
4668 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004669 &ToInternal(this)->children()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004670}
4671
4672
4673int HeapGraphNode::GetRetainersCount() const {
4674 IsDeadCheck("v8::HeapSnapshot::GetRetainersCount");
Iain Merrick75681382010-08-19 15:07:18 +01004675 return ToInternal(this)->retainers().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004676}
4677
4678
4679const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const {
4680 IsDeadCheck("v8::HeapSnapshot::GetRetainer");
4681 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004682 ToInternal(this)->retainers()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004683}
4684
4685
4686int HeapGraphNode::GetRetainingPathsCount() const {
4687 IsDeadCheck("v8::HeapSnapshot::GetRetainingPathsCount");
Iain Merrick75681382010-08-19 15:07:18 +01004688 return ToInternal(this)->GetRetainingPaths()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004689}
4690
4691
4692const HeapGraphPath* HeapGraphNode::GetRetainingPath(int index) const {
4693 IsDeadCheck("v8::HeapSnapshot::GetRetainingPath");
4694 return reinterpret_cast<const HeapGraphPath*>(
Iain Merrick75681382010-08-19 15:07:18 +01004695 ToInternal(this)->GetRetainingPaths()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004696}
4697
4698
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004699const HeapGraphNode* HeapSnapshotsDiff::GetAdditionsRoot() const {
4700 IsDeadCheck("v8::HeapSnapshotsDiff::GetAdditionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004701 i::HeapSnapshotsDiff* diff =
4702 const_cast<i::HeapSnapshotsDiff*>(
4703 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004704 return reinterpret_cast<const HeapGraphNode*>(diff->additions_root());
4705}
4706
4707
4708const HeapGraphNode* HeapSnapshotsDiff::GetDeletionsRoot() const {
4709 IsDeadCheck("v8::HeapSnapshotsDiff::GetDeletionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004710 i::HeapSnapshotsDiff* diff =
4711 const_cast<i::HeapSnapshotsDiff*>(
4712 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004713 return reinterpret_cast<const HeapGraphNode*>(diff->deletions_root());
4714}
4715
4716
Iain Merrick75681382010-08-19 15:07:18 +01004717static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
4718 return const_cast<i::HeapSnapshot*>(
4719 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
4720}
4721
4722
Steve Block791712a2010-08-27 10:21:07 +01004723HeapSnapshot::Type HeapSnapshot::GetType() const {
4724 IsDeadCheck("v8::HeapSnapshot::GetType");
4725 return static_cast<HeapSnapshot::Type>(ToInternal(this)->type());
4726}
4727
4728
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004729unsigned HeapSnapshot::GetUid() const {
4730 IsDeadCheck("v8::HeapSnapshot::GetUid");
Iain Merrick75681382010-08-19 15:07:18 +01004731 return ToInternal(this)->uid();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004732}
4733
4734
4735Handle<String> HeapSnapshot::GetTitle() const {
4736 IsDeadCheck("v8::HeapSnapshot::GetTitle");
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004737 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004738 ToInternal(this)->title())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004739}
4740
4741
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004742const HeapGraphNode* HeapSnapshot::GetRoot() const {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004743 IsDeadCheck("v8::HeapSnapshot::GetHead");
Iain Merrick75681382010-08-19 15:07:18 +01004744 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004745}
4746
4747
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004748const HeapSnapshotsDiff* HeapSnapshot::CompareWith(
4749 const HeapSnapshot* snapshot) const {
4750 IsDeadCheck("v8::HeapSnapshot::CompareWith");
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004751 return reinterpret_cast<const HeapSnapshotsDiff*>(
Iain Merrick75681382010-08-19 15:07:18 +01004752 ToInternal(this)->CompareWith(ToInternal(snapshot)));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004753}
4754
4755
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004756void HeapSnapshot::Serialize(OutputStream* stream,
4757 HeapSnapshot::SerializationFormat format) const {
4758 IsDeadCheck("v8::HeapSnapshot::Serialize");
4759 ApiCheck(format == kJSON,
4760 "v8::HeapSnapshot::Serialize",
4761 "Unknown serialization format");
4762 ApiCheck(stream->GetOutputEncoding() == OutputStream::kAscii,
4763 "v8::HeapSnapshot::Serialize",
4764 "Unsupported output encoding");
4765 ApiCheck(stream->GetChunkSize() > 0,
4766 "v8::HeapSnapshot::Serialize",
4767 "Invalid stream chunk size");
4768 i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
4769 serializer.Serialize(stream);
4770}
4771
4772
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004773int HeapProfiler::GetSnapshotsCount() {
4774 IsDeadCheck("v8::HeapProfiler::GetSnapshotsCount");
4775 return i::HeapProfiler::GetSnapshotsCount();
4776}
4777
4778
4779const HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
4780 IsDeadCheck("v8::HeapProfiler::GetSnapshot");
4781 return reinterpret_cast<const HeapSnapshot*>(
4782 i::HeapProfiler::GetSnapshot(index));
4783}
4784
4785
4786const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
4787 IsDeadCheck("v8::HeapProfiler::FindSnapshot");
4788 return reinterpret_cast<const HeapSnapshot*>(
4789 i::HeapProfiler::FindSnapshot(uid));
4790}
4791
4792
Steve Block791712a2010-08-27 10:21:07 +01004793const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title,
4794 HeapSnapshot::Type type) {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004795 IsDeadCheck("v8::HeapProfiler::TakeSnapshot");
Steve Block791712a2010-08-27 10:21:07 +01004796 i::HeapSnapshot::Type internal_type = i::HeapSnapshot::kFull;
4797 switch (type) {
4798 case HeapSnapshot::kFull:
4799 internal_type = i::HeapSnapshot::kFull;
4800 break;
4801 case HeapSnapshot::kAggregated:
4802 internal_type = i::HeapSnapshot::kAggregated;
4803 break;
4804 default:
4805 UNREACHABLE();
4806 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004807 return reinterpret_cast<const HeapSnapshot*>(
Steve Block791712a2010-08-27 10:21:07 +01004808 i::HeapProfiler::TakeSnapshot(*Utils::OpenHandle(*title), internal_type));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004809}
4810
Steve Block6ded16b2010-05-10 14:33:55 +01004811#endif // ENABLE_LOGGING_AND_PROFILING
4812
4813
Steve Blocka7e24c12009-10-30 11:49:00 +00004814namespace internal {
4815
4816
4817HandleScopeImplementer* HandleScopeImplementer::instance() {
4818 return &thread_local;
4819}
4820
4821
4822void HandleScopeImplementer::FreeThreadResources() {
4823 thread_local.Free();
4824}
4825
4826
4827char* HandleScopeImplementer::ArchiveThread(char* storage) {
4828 return thread_local.ArchiveThreadHelper(storage);
4829}
4830
4831
4832char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
4833 v8::ImplementationUtilities::HandleScopeData* current =
4834 v8::ImplementationUtilities::CurrentHandleScope();
4835 handle_scope_data_ = *current;
4836 memcpy(storage, this, sizeof(*this));
4837
4838 ResetAfterArchive();
4839 current->Initialize();
4840
4841 return storage + ArchiveSpacePerThread();
4842}
4843
4844
4845int HandleScopeImplementer::ArchiveSpacePerThread() {
4846 return sizeof(thread_local);
4847}
4848
4849
4850char* HandleScopeImplementer::RestoreThread(char* storage) {
4851 return thread_local.RestoreThreadHelper(storage);
4852}
4853
4854
4855char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
4856 memcpy(this, storage, sizeof(*this));
4857 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
4858 return storage + ArchiveSpacePerThread();
4859}
4860
4861
4862void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
4863 // Iterate over all handles in the blocks except for the last.
4864 for (int i = blocks()->length() - 2; i >= 0; --i) {
4865 Object** block = blocks()->at(i);
4866 v->VisitPointers(block, &block[kHandleBlockSize]);
4867 }
4868
4869 // Iterate over live handles in the last block (if any).
4870 if (!blocks()->is_empty()) {
4871 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
4872 }
4873
4874 if (!saved_contexts_.is_empty()) {
4875 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
4876 v->VisitPointers(start, start + saved_contexts_.length());
4877 }
4878}
4879
4880
4881void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
4882 v8::ImplementationUtilities::HandleScopeData* current =
4883 v8::ImplementationUtilities::CurrentHandleScope();
4884 thread_local.handle_scope_data_ = *current;
4885 thread_local.IterateThis(v);
4886}
4887
4888
4889char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
4890 HandleScopeImplementer* thread_local =
4891 reinterpret_cast<HandleScopeImplementer*>(storage);
4892 thread_local->IterateThis(v);
4893 return storage + ArchiveSpacePerThread();
4894}
4895
4896} } // namespace v8::internal