blob: 7a967dbffd5a0e684c523a39586e54317d05820f [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
770void FunctionTemplate::SetCallHandler(InvocationCallback callback,
771 v8::Handle<Value> data) {
772 if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
773 ENTER_V8;
774 HandleScope scope;
775 i::Handle<i::Struct> struct_obj =
776 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
777 i::Handle<i::CallHandlerInfo> obj =
778 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
779 obj->set_callback(*FromCData(callback));
780 if (data.IsEmpty()) data = v8::Undefined();
781 obj->set_data(*Utils::OpenHandle(*data));
782 Utils::OpenHandle(this)->set_call_code(*obj);
783}
784
785
Leon Clarkef7060e22010-06-03 12:02:55 +0100786static i::Handle<i::AccessorInfo> MakeAccessorInfo(
787 v8::Handle<String> name,
788 AccessorGetter getter,
789 AccessorSetter setter,
790 v8::Handle<Value> data,
791 v8::AccessControl settings,
792 v8::PropertyAttribute attributes) {
793 i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
794 ASSERT(getter != NULL);
795 obj->set_getter(*FromCData(getter));
796 obj->set_setter(*FromCData(setter));
797 if (data.IsEmpty()) data = v8::Undefined();
798 obj->set_data(*Utils::OpenHandle(*data));
799 obj->set_name(*Utils::OpenHandle(*name));
800 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
801 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
802 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
803 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
804 return obj;
805}
806
807
Steve Blocka7e24c12009-10-30 11:49:00 +0000808void FunctionTemplate::AddInstancePropertyAccessor(
809 v8::Handle<String> name,
810 AccessorGetter getter,
811 AccessorSetter setter,
812 v8::Handle<Value> data,
813 v8::AccessControl settings,
814 v8::PropertyAttribute attributes) {
815 if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
816 return;
817 }
818 ENTER_V8;
819 HandleScope scope;
Steve Blocka7e24c12009-10-30 11:49:00 +0000820
Leon Clarkef7060e22010-06-03 12:02:55 +0100821 i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name,
822 getter, setter, data,
823 settings, attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000824 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
825 if (list->IsUndefined()) {
826 list = NeanderArray().value();
827 Utils::OpenHandle(this)->set_property_accessors(*list);
828 }
829 NeanderArray array(list);
830 array.add(obj);
831}
832
833
834Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
835 if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
836 || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
837 return Local<ObjectTemplate>();
838 ENTER_V8;
839 if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
840 Local<ObjectTemplate> templ =
841 ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
842 Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
843 }
844 i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
845 Utils::OpenHandle(this)->instance_template()));
846 return Utils::ToLocal(result);
847}
848
849
850void FunctionTemplate::SetClassName(Handle<String> name) {
851 if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
852 ENTER_V8;
853 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
854}
855
856
857void FunctionTemplate::SetHiddenPrototype(bool value) {
858 if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
859 ENTER_V8;
860 Utils::OpenHandle(this)->set_hidden_prototype(value);
861}
862
863
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100864void FunctionTemplate::SetNamedInstancePropertyHandler(
Steve Blocka7e24c12009-10-30 11:49:00 +0000865 NamedPropertyGetter getter,
866 NamedPropertySetter setter,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100867 NamedPropertyQuery query,
Steve Blocka7e24c12009-10-30 11:49:00 +0000868 NamedPropertyDeleter remover,
869 NamedPropertyEnumerator enumerator,
870 Handle<Value> data) {
871 if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
872 return;
873 }
874 ENTER_V8;
875 HandleScope scope;
876 i::Handle<i::Struct> struct_obj =
877 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
878 i::Handle<i::InterceptorInfo> obj =
879 i::Handle<i::InterceptorInfo>::cast(struct_obj);
880 if (getter != 0) obj->set_getter(*FromCData(getter));
881 if (setter != 0) obj->set_setter(*FromCData(setter));
882 if (query != 0) obj->set_query(*FromCData(query));
883 if (remover != 0) obj->set_deleter(*FromCData(remover));
884 if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
885 if (data.IsEmpty()) data = v8::Undefined();
886 obj->set_data(*Utils::OpenHandle(*data));
887 Utils::OpenHandle(this)->set_named_property_handler(*obj);
888}
889
890
891void FunctionTemplate::SetIndexedInstancePropertyHandler(
892 IndexedPropertyGetter getter,
893 IndexedPropertySetter setter,
894 IndexedPropertyQuery query,
895 IndexedPropertyDeleter remover,
896 IndexedPropertyEnumerator enumerator,
897 Handle<Value> data) {
898 if (IsDeadCheck(
899 "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
900 return;
901 }
902 ENTER_V8;
903 HandleScope scope;
904 i::Handle<i::Struct> struct_obj =
905 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
906 i::Handle<i::InterceptorInfo> obj =
907 i::Handle<i::InterceptorInfo>::cast(struct_obj);
908 if (getter != 0) obj->set_getter(*FromCData(getter));
909 if (setter != 0) obj->set_setter(*FromCData(setter));
910 if (query != 0) obj->set_query(*FromCData(query));
911 if (remover != 0) obj->set_deleter(*FromCData(remover));
912 if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
913 if (data.IsEmpty()) data = v8::Undefined();
914 obj->set_data(*Utils::OpenHandle(*data));
915 Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
916}
917
918
919void FunctionTemplate::SetInstanceCallAsFunctionHandler(
920 InvocationCallback callback,
921 Handle<Value> data) {
922 if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
923 return;
924 }
925 ENTER_V8;
926 HandleScope scope;
927 i::Handle<i::Struct> struct_obj =
928 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
929 i::Handle<i::CallHandlerInfo> obj =
930 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
931 obj->set_callback(*FromCData(callback));
932 if (data.IsEmpty()) data = v8::Undefined();
933 obj->set_data(*Utils::OpenHandle(*data));
934 Utils::OpenHandle(this)->set_instance_call_handler(*obj);
935}
936
937
938// --- O b j e c t T e m p l a t e ---
939
940
941Local<ObjectTemplate> ObjectTemplate::New() {
942 return New(Local<FunctionTemplate>());
943}
944
945
946Local<ObjectTemplate> ObjectTemplate::New(
947 v8::Handle<FunctionTemplate> constructor) {
948 if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
949 EnsureInitialized("v8::ObjectTemplate::New()");
950 LOG_API("ObjectTemplate::New");
951 ENTER_V8;
952 i::Handle<i::Struct> struct_obj =
953 i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
954 i::Handle<i::ObjectTemplateInfo> obj =
955 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
956 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
957 if (!constructor.IsEmpty())
958 obj->set_constructor(*Utils::OpenHandle(*constructor));
959 obj->set_internal_field_count(i::Smi::FromInt(0));
960 return Utils::ToLocal(obj);
961}
962
963
964// Ensure that the object template has a constructor. If no
965// constructor is available we create one.
966static void EnsureConstructor(ObjectTemplate* object_template) {
967 if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
968 Local<FunctionTemplate> templ = FunctionTemplate::New();
969 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
970 constructor->set_instance_template(*Utils::OpenHandle(object_template));
971 Utils::OpenHandle(object_template)->set_constructor(*constructor);
972 }
973}
974
975
976void ObjectTemplate::SetAccessor(v8::Handle<String> name,
977 AccessorGetter getter,
978 AccessorSetter setter,
979 v8::Handle<Value> data,
980 AccessControl settings,
981 PropertyAttribute attribute) {
982 if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
983 ENTER_V8;
984 HandleScope scope;
985 EnsureConstructor(this);
986 i::FunctionTemplateInfo* constructor =
987 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
988 i::Handle<i::FunctionTemplateInfo> cons(constructor);
989 Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
990 getter,
991 setter,
992 data,
993 settings,
994 attribute);
995}
996
997
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100998void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
999 NamedPropertySetter setter,
1000 NamedPropertyQuery query,
1001 NamedPropertyDeleter remover,
1002 NamedPropertyEnumerator enumerator,
1003 Handle<Value> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001004 if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
1005 ENTER_V8;
1006 HandleScope scope;
1007 EnsureConstructor(this);
1008 i::FunctionTemplateInfo* constructor =
1009 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1010 i::Handle<i::FunctionTemplateInfo> cons(constructor);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001011 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
1012 setter,
1013 query,
1014 remover,
1015 enumerator,
1016 data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001017}
1018
1019
1020void ObjectTemplate::MarkAsUndetectable() {
1021 if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
1022 ENTER_V8;
1023 HandleScope scope;
1024 EnsureConstructor(this);
1025 i::FunctionTemplateInfo* constructor =
1026 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1027 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1028 cons->set_undetectable(true);
1029}
1030
1031
1032void ObjectTemplate::SetAccessCheckCallbacks(
1033 NamedSecurityCallback named_callback,
1034 IndexedSecurityCallback indexed_callback,
1035 Handle<Value> data,
1036 bool turned_on_by_default) {
1037 if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
1038 ENTER_V8;
1039 HandleScope scope;
1040 EnsureConstructor(this);
1041
1042 i::Handle<i::Struct> struct_info =
1043 i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1044 i::Handle<i::AccessCheckInfo> info =
1045 i::Handle<i::AccessCheckInfo>::cast(struct_info);
1046 info->set_named_callback(*FromCData(named_callback));
1047 info->set_indexed_callback(*FromCData(indexed_callback));
1048 if (data.IsEmpty()) data = v8::Undefined();
1049 info->set_data(*Utils::OpenHandle(*data));
1050
1051 i::FunctionTemplateInfo* constructor =
1052 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1053 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1054 cons->set_access_check_info(*info);
1055 cons->set_needs_access_check(turned_on_by_default);
1056}
1057
1058
1059void ObjectTemplate::SetIndexedPropertyHandler(
1060 IndexedPropertyGetter getter,
1061 IndexedPropertySetter setter,
1062 IndexedPropertyQuery query,
1063 IndexedPropertyDeleter remover,
1064 IndexedPropertyEnumerator enumerator,
1065 Handle<Value> data) {
1066 if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
1067 ENTER_V8;
1068 HandleScope scope;
1069 EnsureConstructor(this);
1070 i::FunctionTemplateInfo* constructor =
1071 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1072 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1073 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
1074 setter,
1075 query,
1076 remover,
1077 enumerator,
1078 data);
1079}
1080
1081
1082void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1083 Handle<Value> data) {
1084 if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
1085 ENTER_V8;
1086 HandleScope scope;
1087 EnsureConstructor(this);
1088 i::FunctionTemplateInfo* constructor =
1089 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1090 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1091 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1092}
1093
1094
1095int ObjectTemplate::InternalFieldCount() {
1096 if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
1097 return 0;
1098 }
1099 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1100}
1101
1102
1103void ObjectTemplate::SetInternalFieldCount(int value) {
1104 if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
1105 if (!ApiCheck(i::Smi::IsValid(value),
1106 "v8::ObjectTemplate::SetInternalFieldCount()",
1107 "Invalid internal field count")) {
1108 return;
1109 }
1110 ENTER_V8;
1111 if (value > 0) {
1112 // The internal field count is set by the constructor function's
1113 // construct code, so we ensure that there is a constructor
1114 // function to do the setting.
1115 EnsureConstructor(this);
1116 }
1117 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1118}
1119
1120
1121// --- S c r i p t D a t a ---
1122
1123
1124ScriptData* ScriptData::PreCompile(const char* input, int length) {
1125 unibrow::Utf8InputBuffer<> buf(input, length);
1126 return i::PreParse(i::Handle<i::String>(), &buf, NULL);
1127}
1128
1129
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001130ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
1131 i::Handle<i::String> str = Utils::OpenHandle(*source);
1132 return i::PreParse(str, NULL, NULL);
1133}
1134
1135
Leon Clarkef7060e22010-06-03 12:02:55 +01001136ScriptData* ScriptData::New(const char* data, int length) {
1137 // Return an empty ScriptData if the length is obviously invalid.
1138 if (length % sizeof(unsigned) != 0) {
1139 return new i::ScriptDataImpl(i::Vector<unsigned>());
1140 }
1141
1142 // Copy the data to ensure it is properly aligned.
1143 int deserialized_data_length = length / sizeof(unsigned);
1144 unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
1145 memcpy(deserialized_data, data, length);
1146
1147 return new i::ScriptDataImpl(
1148 i::Vector<unsigned>(deserialized_data, deserialized_data_length));
Steve Blocka7e24c12009-10-30 11:49:00 +00001149}
1150
1151
1152// --- S c r i p t ---
1153
1154
1155Local<Script> Script::New(v8::Handle<String> source,
1156 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001157 v8::ScriptData* pre_data,
1158 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001159 ON_BAILOUT("v8::Script::New()", return Local<Script>());
1160 LOG_API("Script::New");
1161 ENTER_V8;
1162 i::Handle<i::String> str = Utils::OpenHandle(*source);
1163 i::Handle<i::Object> name_obj;
1164 int line_offset = 0;
1165 int column_offset = 0;
1166 if (origin != NULL) {
1167 if (!origin->ResourceName().IsEmpty()) {
1168 name_obj = Utils::OpenHandle(*origin->ResourceName());
1169 }
1170 if (!origin->ResourceLineOffset().IsEmpty()) {
1171 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1172 }
1173 if (!origin->ResourceColumnOffset().IsEmpty()) {
1174 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1175 }
1176 }
1177 EXCEPTION_PREAMBLE();
Andrei Popescu402d9372010-02-26 13:31:12 +00001178 i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001179 // We assert that the pre-data is sane, even though we can actually
1180 // handle it if it turns out not to be in release mode.
Andrei Popescu402d9372010-02-26 13:31:12 +00001181 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
Steve Blocka7e24c12009-10-30 11:49:00 +00001182 // If the pre-data isn't sane we simply ignore it
Andrei Popescu402d9372010-02-26 13:31:12 +00001183 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
1184 pre_data_impl = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001185 }
Steve Block6ded16b2010-05-10 14:33:55 +01001186 i::Handle<i::SharedFunctionInfo> result =
Andrei Popescu31002712010-02-23 13:46:05 +00001187 i::Compiler::Compile(str,
1188 name_obj,
1189 line_offset,
1190 column_offset,
1191 NULL,
Andrei Popescu402d9372010-02-26 13:31:12 +00001192 pre_data_impl,
1193 Utils::OpenHandle(*script_data),
Andrei Popescu31002712010-02-23 13:46:05 +00001194 i::NOT_NATIVES_CODE);
Steve Block6ded16b2010-05-10 14:33:55 +01001195 has_pending_exception = result.is_null();
Steve Blocka7e24c12009-10-30 11:49:00 +00001196 EXCEPTION_BAILOUT_CHECK(Local<Script>());
Steve Block6ded16b2010-05-10 14:33:55 +01001197 return Local<Script>(ToApi<Script>(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00001198}
1199
1200
1201Local<Script> Script::New(v8::Handle<String> source,
1202 v8::Handle<Value> file_name) {
1203 ScriptOrigin origin(file_name);
1204 return New(source, &origin);
1205}
1206
1207
1208Local<Script> Script::Compile(v8::Handle<String> source,
1209 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001210 v8::ScriptData* pre_data,
1211 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001212 ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1213 LOG_API("Script::Compile");
1214 ENTER_V8;
Andrei Popescu402d9372010-02-26 13:31:12 +00001215 Local<Script> generic = New(source, origin, pre_data, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001216 if (generic.IsEmpty())
1217 return generic;
Steve Block6ded16b2010-05-10 14:33:55 +01001218 i::Handle<i::Object> obj = Utils::OpenHandle(*generic);
1219 i::Handle<i::SharedFunctionInfo> function =
1220 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001221 i::Handle<i::JSFunction> result =
Steve Block6ded16b2010-05-10 14:33:55 +01001222 i::Factory::NewFunctionFromSharedFunctionInfo(function,
1223 i::Top::global_context());
Steve Blocka7e24c12009-10-30 11:49:00 +00001224 return Local<Script>(ToApi<Script>(result));
1225}
1226
1227
1228Local<Script> Script::Compile(v8::Handle<String> source,
Andrei Popescu402d9372010-02-26 13:31:12 +00001229 v8::Handle<Value> file_name,
1230 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001231 ScriptOrigin origin(file_name);
Andrei Popescu402d9372010-02-26 13:31:12 +00001232 return Compile(source, &origin, 0, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001233}
1234
1235
1236Local<Value> Script::Run() {
1237 ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1238 LOG_API("Script::Run");
1239 ENTER_V8;
1240 i::Object* raw_result = NULL;
1241 {
1242 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001243 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1244 i::Handle<i::JSFunction> fun;
1245 if (obj->IsSharedFunctionInfo()) {
1246 i::Handle<i::SharedFunctionInfo>
1247 function_info(i::SharedFunctionInfo::cast(*obj));
1248 fun = i::Factory::NewFunctionFromSharedFunctionInfo(
1249 function_info, i::Top::global_context());
1250 } else {
1251 fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001252 }
1253 EXCEPTION_PREAMBLE();
1254 i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
1255 i::Handle<i::Object> result =
1256 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
1257 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1258 raw_result = *result;
1259 }
1260 i::Handle<i::Object> result(raw_result);
1261 return Utils::ToLocal(result);
1262}
1263
1264
Steve Block6ded16b2010-05-10 14:33:55 +01001265static i::Handle<i::SharedFunctionInfo> OpenScript(Script* script) {
1266 i::Handle<i::Object> obj = Utils::OpenHandle(script);
1267 i::Handle<i::SharedFunctionInfo> result;
1268 if (obj->IsSharedFunctionInfo()) {
1269 result =
1270 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
1271 } else {
1272 result =
1273 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared());
1274 }
1275 return result;
1276}
1277
1278
Steve Blocka7e24c12009-10-30 11:49:00 +00001279Local<Value> Script::Id() {
1280 ON_BAILOUT("v8::Script::Id()", return Local<Value>());
1281 LOG_API("Script::Id");
1282 i::Object* raw_id = NULL;
1283 {
1284 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001285 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1286 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001287 i::Handle<i::Object> id(script->id());
1288 raw_id = *id;
1289 }
1290 i::Handle<i::Object> id(raw_id);
1291 return Utils::ToLocal(id);
1292}
1293
1294
Steve Blockd0582a62009-12-15 09:54:21 +00001295void Script::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001296 ON_BAILOUT("v8::Script::SetData()", return);
1297 LOG_API("Script::SetData");
1298 {
1299 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001300 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001301 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
Steve Block6ded16b2010-05-10 14:33:55 +01001302 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001303 script->set_data(*raw_data);
1304 }
1305}
1306
1307
1308// --- E x c e p t i o n s ---
1309
1310
1311v8::TryCatch::TryCatch()
Steve Blockd0582a62009-12-15 09:54:21 +00001312 : next_(i::Top::try_catch_handler_address()),
Steve Blocka7e24c12009-10-30 11:49:00 +00001313 exception_(i::Heap::the_hole_value()),
1314 message_(i::Smi::FromInt(0)),
1315 is_verbose_(false),
1316 can_continue_(true),
1317 capture_message_(true),
Steve Blockd0582a62009-12-15 09:54:21 +00001318 rethrow_(false) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001319 i::Top::RegisterTryCatchHandler(this);
1320}
1321
1322
1323v8::TryCatch::~TryCatch() {
Steve Blockd0582a62009-12-15 09:54:21 +00001324 if (rethrow_) {
1325 v8::HandleScope scope;
1326 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
1327 i::Top::UnregisterTryCatchHandler(this);
1328 v8::ThrowException(exc);
1329 } else {
1330 i::Top::UnregisterTryCatchHandler(this);
1331 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001332}
1333
1334
1335bool v8::TryCatch::HasCaught() const {
1336 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1337}
1338
1339
1340bool v8::TryCatch::CanContinue() const {
1341 return can_continue_;
1342}
1343
1344
Steve Blockd0582a62009-12-15 09:54:21 +00001345v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1346 if (!HasCaught()) return v8::Local<v8::Value>();
1347 rethrow_ = true;
1348 return v8::Undefined();
1349}
1350
1351
Steve Blocka7e24c12009-10-30 11:49:00 +00001352v8::Local<Value> v8::TryCatch::Exception() const {
1353 if (HasCaught()) {
1354 // Check for out of memory exception.
1355 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1356 return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1357 } else {
1358 return v8::Local<Value>();
1359 }
1360}
1361
1362
1363v8::Local<Value> v8::TryCatch::StackTrace() const {
1364 if (HasCaught()) {
1365 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1366 if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1367 v8::HandleScope scope;
1368 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
1369 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
1370 if (!obj->HasProperty(*name))
1371 return v8::Local<Value>();
1372 return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
1373 } else {
1374 return v8::Local<Value>();
1375 }
1376}
1377
1378
1379v8::Local<v8::Message> v8::TryCatch::Message() const {
1380 if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1381 i::Object* message = reinterpret_cast<i::Object*>(message_);
1382 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1383 } else {
1384 return v8::Local<v8::Message>();
1385 }
1386}
1387
1388
1389void v8::TryCatch::Reset() {
1390 exception_ = i::Heap::the_hole_value();
1391 message_ = i::Smi::FromInt(0);
1392}
1393
1394
1395void v8::TryCatch::SetVerbose(bool value) {
1396 is_verbose_ = value;
1397}
1398
1399
1400void v8::TryCatch::SetCaptureMessage(bool value) {
1401 capture_message_ = value;
1402}
1403
1404
1405// --- M e s s a g e ---
1406
1407
1408Local<String> Message::Get() const {
1409 ON_BAILOUT("v8::Message::Get()", return Local<String>());
1410 ENTER_V8;
1411 HandleScope scope;
1412 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1413 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1414 Local<String> result = Utils::ToLocal(raw_result);
1415 return scope.Close(result);
1416}
1417
1418
1419v8::Handle<Value> Message::GetScriptResourceName() const {
1420 if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1421 return Local<String>();
1422 }
1423 ENTER_V8;
1424 HandleScope scope;
1425 i::Handle<i::JSObject> obj =
1426 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1427 // Return this.script.name.
1428 i::Handle<i::JSValue> script =
1429 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1430 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
1431 return scope.Close(Utils::ToLocal(resource_name));
1432}
1433
1434
1435v8::Handle<Value> Message::GetScriptData() const {
1436 if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
1437 return Local<Value>();
1438 }
1439 ENTER_V8;
1440 HandleScope scope;
1441 i::Handle<i::JSObject> obj =
1442 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1443 // Return this.script.data.
1444 i::Handle<i::JSValue> script =
1445 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1446 i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1447 return scope.Close(Utils::ToLocal(data));
1448}
1449
1450
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001451v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
1452 if (IsDeadCheck("v8::Message::GetStackTrace()")) {
1453 return Local<v8::StackTrace>();
1454 }
1455 ENTER_V8;
1456 HandleScope scope;
1457 i::Handle<i::JSObject> obj =
1458 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1459 i::Handle<i::Object> stackFramesObj = GetProperty(obj, "stackFrames");
1460 if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
1461 i::Handle<i::JSArray> stackTrace =
1462 i::Handle<i::JSArray>::cast(stackFramesObj);
1463 return scope.Close(Utils::StackTraceToLocal(stackTrace));
1464}
1465
1466
Steve Blocka7e24c12009-10-30 11:49:00 +00001467static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1468 i::Handle<i::Object> recv,
1469 int argc,
1470 i::Object** argv[],
1471 bool* has_pending_exception) {
1472 i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
1473 i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
1474 i::Handle<i::JSFunction> fun =
1475 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1476 i::Handle<i::Object> value =
1477 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1478 return value;
1479}
1480
1481
1482static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1483 i::Handle<i::Object> data,
1484 bool* has_pending_exception) {
1485 i::Object** argv[1] = { data.location() };
1486 return CallV8HeapFunction(name,
1487 i::Top::builtins(),
1488 1,
1489 argv,
1490 has_pending_exception);
1491}
1492
1493
1494int Message::GetLineNumber() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001495 ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001496 ENTER_V8;
1497 HandleScope scope;
1498 EXCEPTION_PREAMBLE();
1499 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1500 Utils::OpenHandle(this),
1501 &has_pending_exception);
1502 EXCEPTION_BAILOUT_CHECK(0);
1503 return static_cast<int>(result->Number());
1504}
1505
1506
1507int Message::GetStartPosition() const {
1508 if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1509 ENTER_V8;
1510 HandleScope scope;
1511
1512 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1513 return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1514}
1515
1516
1517int Message::GetEndPosition() const {
1518 if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1519 ENTER_V8;
1520 HandleScope scope;
1521 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1522 return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1523}
1524
1525
1526int Message::GetStartColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001527 if (IsDeadCheck("v8::Message::GetStartColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001528 ENTER_V8;
1529 HandleScope scope;
1530 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1531 EXCEPTION_PREAMBLE();
1532 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1533 "GetPositionInLine",
1534 data_obj,
1535 &has_pending_exception);
1536 EXCEPTION_BAILOUT_CHECK(0);
1537 return static_cast<int>(start_col_obj->Number());
1538}
1539
1540
1541int Message::GetEndColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001542 if (IsDeadCheck("v8::Message::GetEndColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001543 ENTER_V8;
1544 HandleScope scope;
1545 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1546 EXCEPTION_PREAMBLE();
1547 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1548 "GetPositionInLine",
1549 data_obj,
1550 &has_pending_exception);
1551 EXCEPTION_BAILOUT_CHECK(0);
1552 int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1553 int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1554 return static_cast<int>(start_col_obj->Number()) + (end - start);
1555}
1556
1557
1558Local<String> Message::GetSourceLine() const {
1559 ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
1560 ENTER_V8;
1561 HandleScope scope;
1562 EXCEPTION_PREAMBLE();
1563 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1564 Utils::OpenHandle(this),
1565 &has_pending_exception);
1566 EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1567 if (result->IsString()) {
1568 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1569 } else {
1570 return Local<String>();
1571 }
1572}
1573
1574
1575void Message::PrintCurrentStackTrace(FILE* out) {
1576 if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1577 ENTER_V8;
1578 i::Top::PrintCurrentStackTrace(out);
1579}
1580
1581
Kristian Monsen25f61362010-05-21 11:50:48 +01001582// --- S t a c k T r a c e ---
1583
1584Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
1585 if (IsDeadCheck("v8::StackTrace::GetFrame()")) return Local<StackFrame>();
1586 ENTER_V8;
1587 HandleScope scope;
1588 i::Handle<i::JSArray> self = Utils::OpenHandle(this);
1589 i::Handle<i::JSObject> obj(i::JSObject::cast(self->GetElement(index)));
1590 return scope.Close(Utils::StackFrameToLocal(obj));
1591}
1592
1593
1594int StackTrace::GetFrameCount() const {
1595 if (IsDeadCheck("v8::StackTrace::GetFrameCount()")) return -1;
1596 ENTER_V8;
1597 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
1598}
1599
1600
1601Local<Array> StackTrace::AsArray() {
1602 if (IsDeadCheck("v8::StackTrace::AsArray()")) Local<Array>();
1603 ENTER_V8;
1604 return Utils::ToLocal(Utils::OpenHandle(this));
1605}
1606
1607
1608Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
1609 StackTraceOptions options) {
1610 if (IsDeadCheck("v8::StackTrace::CurrentStackTrace()")) Local<StackTrace>();
1611 ENTER_V8;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001612 i::Handle<i::JSArray> stackTrace =
1613 i::Top::CaptureCurrentStackTrace(frame_limit, options);
1614 return Utils::StackTraceToLocal(stackTrace);
Kristian Monsen25f61362010-05-21 11:50:48 +01001615}
1616
1617
1618// --- S t a c k F r a m e ---
1619
1620int StackFrame::GetLineNumber() const {
1621 if (IsDeadCheck("v8::StackFrame::GetLineNumber()")) {
1622 return Message::kNoLineNumberInfo;
1623 }
1624 ENTER_V8;
1625 i::HandleScope scope;
1626 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1627 i::Handle<i::Object> line = GetProperty(self, "lineNumber");
1628 if (!line->IsSmi()) {
1629 return Message::kNoLineNumberInfo;
1630 }
1631 return i::Smi::cast(*line)->value();
1632}
1633
1634
1635int StackFrame::GetColumn() const {
1636 if (IsDeadCheck("v8::StackFrame::GetColumn()")) {
1637 return Message::kNoColumnInfo;
1638 }
1639 ENTER_V8;
1640 i::HandleScope scope;
1641 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1642 i::Handle<i::Object> column = GetProperty(self, "column");
1643 if (!column->IsSmi()) {
1644 return Message::kNoColumnInfo;
1645 }
1646 return i::Smi::cast(*column)->value();
1647}
1648
1649
1650Local<String> StackFrame::GetScriptName() const {
1651 if (IsDeadCheck("v8::StackFrame::GetScriptName()")) return Local<String>();
1652 ENTER_V8;
1653 HandleScope scope;
1654 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1655 i::Handle<i::Object> name = GetProperty(self, "scriptName");
1656 if (!name->IsString()) {
1657 return Local<String>();
1658 }
1659 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1660}
1661
1662
1663Local<String> StackFrame::GetFunctionName() const {
1664 if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
1665 ENTER_V8;
1666 HandleScope scope;
1667 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1668 i::Handle<i::Object> name = GetProperty(self, "functionName");
1669 if (!name->IsString()) {
1670 return Local<String>();
1671 }
1672 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1673}
1674
1675
1676bool StackFrame::IsEval() const {
1677 if (IsDeadCheck("v8::StackFrame::IsEval()")) return false;
1678 ENTER_V8;
1679 i::HandleScope scope;
1680 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1681 i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
1682 return is_eval->IsTrue();
1683}
1684
1685
1686bool StackFrame::IsConstructor() const {
1687 if (IsDeadCheck("v8::StackFrame::IsConstructor()")) return false;
1688 ENTER_V8;
1689 i::HandleScope scope;
1690 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1691 i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
1692 return is_constructor->IsTrue();
1693}
1694
1695
Steve Blocka7e24c12009-10-30 11:49:00 +00001696// --- D a t a ---
1697
1698bool Value::IsUndefined() const {
1699 if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1700 return Utils::OpenHandle(this)->IsUndefined();
1701}
1702
1703
1704bool Value::IsNull() const {
1705 if (IsDeadCheck("v8::Value::IsNull()")) return false;
1706 return Utils::OpenHandle(this)->IsNull();
1707}
1708
1709
1710bool Value::IsTrue() const {
1711 if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1712 return Utils::OpenHandle(this)->IsTrue();
1713}
1714
1715
1716bool Value::IsFalse() const {
1717 if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1718 return Utils::OpenHandle(this)->IsFalse();
1719}
1720
1721
1722bool Value::IsFunction() const {
1723 if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1724 return Utils::OpenHandle(this)->IsJSFunction();
1725}
1726
1727
1728bool Value::FullIsString() const {
1729 if (IsDeadCheck("v8::Value::IsString()")) return false;
1730 bool result = Utils::OpenHandle(this)->IsString();
1731 ASSERT_EQ(result, QuickIsString());
1732 return result;
1733}
1734
1735
1736bool Value::IsArray() const {
1737 if (IsDeadCheck("v8::Value::IsArray()")) return false;
1738 return Utils::OpenHandle(this)->IsJSArray();
1739}
1740
1741
1742bool Value::IsObject() const {
1743 if (IsDeadCheck("v8::Value::IsObject()")) return false;
1744 return Utils::OpenHandle(this)->IsJSObject();
1745}
1746
1747
1748bool Value::IsNumber() const {
1749 if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1750 return Utils::OpenHandle(this)->IsNumber();
1751}
1752
1753
1754bool Value::IsBoolean() const {
1755 if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1756 return Utils::OpenHandle(this)->IsBoolean();
1757}
1758
1759
1760bool Value::IsExternal() const {
1761 if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1762 return Utils::OpenHandle(this)->IsProxy();
1763}
1764
1765
1766bool Value::IsInt32() const {
1767 if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1768 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1769 if (obj->IsSmi()) return true;
1770 if (obj->IsNumber()) {
1771 double value = obj->Number();
1772 return i::FastI2D(i::FastD2I(value)) == value;
1773 }
1774 return false;
1775}
1776
1777
Steve Block6ded16b2010-05-10 14:33:55 +01001778bool Value::IsUint32() const {
1779 if (IsDeadCheck("v8::Value::IsUint32()")) return false;
1780 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1781 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
1782 if (obj->IsNumber()) {
1783 double value = obj->Number();
1784 return i::FastUI2D(i::FastD2UI(value)) == value;
1785 }
1786 return false;
1787}
1788
1789
Steve Blocka7e24c12009-10-30 11:49:00 +00001790bool Value::IsDate() const {
1791 if (IsDeadCheck("v8::Value::IsDate()")) return false;
1792 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1793 return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1794}
1795
1796
Iain Merrick75681382010-08-19 15:07:18 +01001797bool Value::IsRegExp() const {
1798 if (IsDeadCheck("v8::Value::IsRegExp()")) return false;
1799 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1800 return obj->IsJSRegExp();
1801}
1802
1803
Steve Blocka7e24c12009-10-30 11:49:00 +00001804Local<String> Value::ToString() const {
1805 if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1806 LOG_API("ToString");
1807 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1808 i::Handle<i::Object> str;
1809 if (obj->IsString()) {
1810 str = obj;
1811 } else {
1812 ENTER_V8;
1813 EXCEPTION_PREAMBLE();
1814 str = i::Execution::ToString(obj, &has_pending_exception);
1815 EXCEPTION_BAILOUT_CHECK(Local<String>());
1816 }
1817 return Local<String>(ToApi<String>(str));
1818}
1819
1820
1821Local<String> Value::ToDetailString() const {
1822 if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1823 LOG_API("ToDetailString");
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::ToDetailString(obj, &has_pending_exception);
1832 EXCEPTION_BAILOUT_CHECK(Local<String>());
1833 }
1834 return Local<String>(ToApi<String>(str));
1835}
1836
1837
1838Local<v8::Object> Value::ToObject() const {
1839 if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1840 LOG_API("ToObject");
1841 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1842 i::Handle<i::Object> val;
1843 if (obj->IsJSObject()) {
1844 val = obj;
1845 } else {
1846 ENTER_V8;
1847 EXCEPTION_PREAMBLE();
1848 val = i::Execution::ToObject(obj, &has_pending_exception);
1849 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1850 }
1851 return Local<v8::Object>(ToApi<Object>(val));
1852}
1853
1854
1855Local<Boolean> Value::ToBoolean() const {
1856 if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1857 LOG_API("ToBoolean");
1858 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1859 if (obj->IsBoolean()) {
1860 return Local<Boolean>(ToApi<Boolean>(obj));
1861 } else {
1862 ENTER_V8;
1863 i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1864 return Local<Boolean>(ToApi<Boolean>(val));
1865 }
1866}
1867
1868
1869Local<Number> Value::ToNumber() const {
1870 if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1871 LOG_API("ToNumber");
1872 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1873 i::Handle<i::Object> num;
1874 if (obj->IsNumber()) {
1875 num = obj;
1876 } else {
1877 ENTER_V8;
1878 EXCEPTION_PREAMBLE();
1879 num = i::Execution::ToNumber(obj, &has_pending_exception);
1880 EXCEPTION_BAILOUT_CHECK(Local<Number>());
1881 }
1882 return Local<Number>(ToApi<Number>(num));
1883}
1884
1885
1886Local<Integer> Value::ToInteger() const {
1887 if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1888 LOG_API("ToInteger");
1889 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1890 i::Handle<i::Object> num;
1891 if (obj->IsSmi()) {
1892 num = obj;
1893 } else {
1894 ENTER_V8;
1895 EXCEPTION_PREAMBLE();
1896 num = i::Execution::ToInteger(obj, &has_pending_exception);
1897 EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1898 }
1899 return Local<Integer>(ToApi<Integer>(num));
1900}
1901
1902
1903void External::CheckCast(v8::Value* that) {
1904 if (IsDeadCheck("v8::External::Cast()")) return;
1905 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1906 ApiCheck(obj->IsProxy(),
1907 "v8::External::Cast()",
1908 "Could not convert to external");
1909}
1910
1911
1912void v8::Object::CheckCast(Value* that) {
1913 if (IsDeadCheck("v8::Object::Cast()")) return;
1914 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1915 ApiCheck(obj->IsJSObject(),
1916 "v8::Object::Cast()",
1917 "Could not convert to object");
1918}
1919
1920
1921void v8::Function::CheckCast(Value* that) {
1922 if (IsDeadCheck("v8::Function::Cast()")) return;
1923 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1924 ApiCheck(obj->IsJSFunction(),
1925 "v8::Function::Cast()",
1926 "Could not convert to function");
1927}
1928
1929
1930void v8::String::CheckCast(v8::Value* that) {
1931 if (IsDeadCheck("v8::String::Cast()")) return;
1932 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1933 ApiCheck(obj->IsString(),
1934 "v8::String::Cast()",
1935 "Could not convert to string");
1936}
1937
1938
1939void v8::Number::CheckCast(v8::Value* that) {
1940 if (IsDeadCheck("v8::Number::Cast()")) return;
1941 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1942 ApiCheck(obj->IsNumber(),
1943 "v8::Number::Cast()",
1944 "Could not convert to number");
1945}
1946
1947
1948void v8::Integer::CheckCast(v8::Value* that) {
1949 if (IsDeadCheck("v8::Integer::Cast()")) return;
1950 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1951 ApiCheck(obj->IsNumber(),
1952 "v8::Integer::Cast()",
1953 "Could not convert to number");
1954}
1955
1956
1957void v8::Array::CheckCast(Value* that) {
1958 if (IsDeadCheck("v8::Array::Cast()")) return;
1959 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1960 ApiCheck(obj->IsJSArray(),
1961 "v8::Array::Cast()",
1962 "Could not convert to array");
1963}
1964
1965
1966void v8::Date::CheckCast(v8::Value* that) {
1967 if (IsDeadCheck("v8::Date::Cast()")) return;
1968 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1969 ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
1970 "v8::Date::Cast()",
1971 "Could not convert to date");
1972}
1973
1974
1975bool Value::BooleanValue() const {
1976 if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
1977 LOG_API("BooleanValue");
1978 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1979 if (obj->IsBoolean()) {
1980 return obj->IsTrue();
1981 } else {
1982 ENTER_V8;
1983 i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
1984 return value->IsTrue();
1985 }
1986}
1987
1988
1989double Value::NumberValue() const {
1990 if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
1991 LOG_API("NumberValue");
1992 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1993 i::Handle<i::Object> num;
1994 if (obj->IsNumber()) {
1995 num = obj;
1996 } else {
1997 ENTER_V8;
1998 EXCEPTION_PREAMBLE();
1999 num = i::Execution::ToNumber(obj, &has_pending_exception);
2000 EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
2001 }
2002 return num->Number();
2003}
2004
2005
2006int64_t Value::IntegerValue() const {
2007 if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
2008 LOG_API("IntegerValue");
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::ToInteger(obj, &has_pending_exception);
2017 EXCEPTION_BAILOUT_CHECK(0);
2018 }
2019 if (num->IsSmi()) {
2020 return i::Smi::cast(*num)->value();
2021 } else {
2022 return static_cast<int64_t>(num->Number());
2023 }
2024}
2025
2026
2027Local<Int32> Value::ToInt32() const {
2028 if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
2029 LOG_API("ToInt32");
2030 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2031 i::Handle<i::Object> num;
2032 if (obj->IsSmi()) {
2033 num = obj;
2034 } else {
2035 ENTER_V8;
2036 EXCEPTION_PREAMBLE();
2037 num = i::Execution::ToInt32(obj, &has_pending_exception);
2038 EXCEPTION_BAILOUT_CHECK(Local<Int32>());
2039 }
2040 return Local<Int32>(ToApi<Int32>(num));
2041}
2042
2043
2044Local<Uint32> Value::ToUint32() const {
2045 if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
2046 LOG_API("ToUInt32");
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::ToUint32(obj, &has_pending_exception);
2055 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2056 }
2057 return Local<Uint32>(ToApi<Uint32>(num));
2058}
2059
2060
2061Local<Uint32> Value::ToArrayIndex() const {
2062 if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
2063 LOG_API("ToArrayIndex");
2064 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2065 if (obj->IsSmi()) {
2066 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2067 return Local<Uint32>();
2068 }
2069 ENTER_V8;
2070 EXCEPTION_PREAMBLE();
2071 i::Handle<i::Object> string_obj =
2072 i::Execution::ToString(obj, &has_pending_exception);
2073 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2074 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2075 uint32_t index;
2076 if (str->AsArrayIndex(&index)) {
2077 i::Handle<i::Object> value;
2078 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2079 value = i::Handle<i::Object>(i::Smi::FromInt(index));
2080 } else {
2081 value = i::Factory::NewNumber(index);
2082 }
2083 return Utils::Uint32ToLocal(value);
2084 }
2085 return Local<Uint32>();
2086}
2087
2088
2089int32_t Value::Int32Value() const {
2090 if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
2091 LOG_API("Int32Value");
2092 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2093 if (obj->IsSmi()) {
2094 return i::Smi::cast(*obj)->value();
2095 } else {
2096 LOG_API("Int32Value (slow)");
2097 ENTER_V8;
2098 EXCEPTION_PREAMBLE();
2099 i::Handle<i::Object> num =
2100 i::Execution::ToInt32(obj, &has_pending_exception);
2101 EXCEPTION_BAILOUT_CHECK(0);
2102 if (num->IsSmi()) {
2103 return i::Smi::cast(*num)->value();
2104 } else {
2105 return static_cast<int32_t>(num->Number());
2106 }
2107 }
2108}
2109
2110
2111bool Value::Equals(Handle<Value> that) const {
2112 if (IsDeadCheck("v8::Value::Equals()")
2113 || EmptyCheck("v8::Value::Equals()", this)
2114 || EmptyCheck("v8::Value::Equals()", that)) {
2115 return false;
2116 }
2117 LOG_API("Equals");
2118 ENTER_V8;
2119 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2120 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2121 i::Object** args[1] = { other.location() };
2122 EXCEPTION_PREAMBLE();
2123 i::Handle<i::Object> result =
2124 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
2125 EXCEPTION_BAILOUT_CHECK(false);
2126 return *result == i::Smi::FromInt(i::EQUAL);
2127}
2128
2129
2130bool Value::StrictEquals(Handle<Value> that) const {
2131 if (IsDeadCheck("v8::Value::StrictEquals()")
2132 || EmptyCheck("v8::Value::StrictEquals()", this)
2133 || EmptyCheck("v8::Value::StrictEquals()", that)) {
2134 return false;
2135 }
2136 LOG_API("StrictEquals");
2137 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2138 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2139 // Must check HeapNumber first, since NaN !== NaN.
2140 if (obj->IsHeapNumber()) {
2141 if (!other->IsNumber()) return false;
2142 double x = obj->Number();
2143 double y = other->Number();
2144 // Must check explicitly for NaN:s on Windows, but -0 works fine.
2145 return x == y && !isnan(x) && !isnan(y);
2146 } else if (*obj == *other) { // Also covers Booleans.
2147 return true;
2148 } else if (obj->IsSmi()) {
2149 return other->IsNumber() && obj->Number() == other->Number();
2150 } else if (obj->IsString()) {
2151 return other->IsString() &&
2152 i::String::cast(*obj)->Equals(i::String::cast(*other));
2153 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2154 return other->IsUndefined() || other->IsUndetectableObject();
2155 } else {
2156 return false;
2157 }
2158}
2159
2160
2161uint32_t Value::Uint32Value() const {
2162 if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
2163 LOG_API("Uint32Value");
2164 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2165 if (obj->IsSmi()) {
2166 return i::Smi::cast(*obj)->value();
2167 } else {
2168 ENTER_V8;
2169 EXCEPTION_PREAMBLE();
2170 i::Handle<i::Object> num =
2171 i::Execution::ToUint32(obj, &has_pending_exception);
2172 EXCEPTION_BAILOUT_CHECK(0);
2173 if (num->IsSmi()) {
2174 return i::Smi::cast(*num)->value();
2175 } else {
2176 return static_cast<uint32_t>(num->Number());
2177 }
2178 }
2179}
2180
2181
2182bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
2183 v8::PropertyAttribute attribs) {
2184 ON_BAILOUT("v8::Object::Set()", return false);
2185 ENTER_V8;
2186 HandleScope scope;
2187 i::Handle<i::Object> self = Utils::OpenHandle(this);
2188 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2189 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2190 EXCEPTION_PREAMBLE();
2191 i::Handle<i::Object> obj = i::SetProperty(
2192 self,
2193 key_obj,
2194 value_obj,
2195 static_cast<PropertyAttributes>(attribs));
2196 has_pending_exception = obj.is_null();
2197 EXCEPTION_BAILOUT_CHECK(false);
2198 return true;
2199}
2200
2201
Steve Block6ded16b2010-05-10 14:33:55 +01002202bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
2203 ON_BAILOUT("v8::Object::Set()", return false);
2204 ENTER_V8;
2205 HandleScope scope;
2206 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2207 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2208 EXCEPTION_PREAMBLE();
2209 i::Handle<i::Object> obj = i::SetElement(
2210 self,
2211 index,
2212 value_obj);
2213 has_pending_exception = obj.is_null();
2214 EXCEPTION_BAILOUT_CHECK(false);
2215 return true;
2216}
2217
2218
Steve Blocka7e24c12009-10-30 11:49:00 +00002219bool v8::Object::ForceSet(v8::Handle<Value> key,
2220 v8::Handle<Value> value,
2221 v8::PropertyAttribute attribs) {
2222 ON_BAILOUT("v8::Object::ForceSet()", return false);
2223 ENTER_V8;
2224 HandleScope scope;
2225 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2226 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2227 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2228 EXCEPTION_PREAMBLE();
2229 i::Handle<i::Object> obj = i::ForceSetProperty(
2230 self,
2231 key_obj,
2232 value_obj,
2233 static_cast<PropertyAttributes>(attribs));
2234 has_pending_exception = obj.is_null();
2235 EXCEPTION_BAILOUT_CHECK(false);
2236 return true;
2237}
2238
2239
2240bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2241 ON_BAILOUT("v8::Object::ForceDelete()", return false);
2242 ENTER_V8;
2243 HandleScope scope;
2244 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2245 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2246 EXCEPTION_PREAMBLE();
2247 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2248 has_pending_exception = obj.is_null();
2249 EXCEPTION_BAILOUT_CHECK(false);
2250 return obj->IsTrue();
2251}
2252
2253
2254Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2255 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2256 ENTER_V8;
2257 i::Handle<i::Object> self = Utils::OpenHandle(this);
2258 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2259 EXCEPTION_PREAMBLE();
2260 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2261 has_pending_exception = result.is_null();
2262 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2263 return Utils::ToLocal(result);
2264}
2265
2266
Steve Block6ded16b2010-05-10 14:33:55 +01002267Local<Value> v8::Object::Get(uint32_t index) {
2268 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2269 ENTER_V8;
2270 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2271 EXCEPTION_PREAMBLE();
2272 i::Handle<i::Object> result = i::GetElement(self, index);
2273 has_pending_exception = result.is_null();
2274 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2275 return Utils::ToLocal(result);
2276}
2277
2278
Steve Blocka7e24c12009-10-30 11:49:00 +00002279Local<Value> v8::Object::GetPrototype() {
2280 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
2281 ENTER_V8;
2282 i::Handle<i::Object> self = Utils::OpenHandle(this);
2283 i::Handle<i::Object> result = i::GetPrototype(self);
2284 return Utils::ToLocal(result);
2285}
2286
2287
Andrei Popescu402d9372010-02-26 13:31:12 +00002288bool v8::Object::SetPrototype(Handle<Value> value) {
2289 ON_BAILOUT("v8::Object::SetPrototype()", return false);
2290 ENTER_V8;
2291 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2292 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2293 EXCEPTION_PREAMBLE();
2294 i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2295 has_pending_exception = result.is_null();
2296 EXCEPTION_BAILOUT_CHECK(false);
2297 return true;
2298}
2299
2300
Steve Blocka7e24c12009-10-30 11:49:00 +00002301Local<Object> v8::Object::FindInstanceInPrototypeChain(
2302 v8::Handle<FunctionTemplate> tmpl) {
2303 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
2304 return Local<v8::Object>());
2305 ENTER_V8;
2306 i::JSObject* object = *Utils::OpenHandle(this);
2307 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2308 while (!object->IsInstanceOf(tmpl_info)) {
2309 i::Object* prototype = object->GetPrototype();
2310 if (!prototype->IsJSObject()) return Local<Object>();
2311 object = i::JSObject::cast(prototype);
2312 }
2313 return Utils::ToLocal(i::Handle<i::JSObject>(object));
2314}
2315
2316
2317Local<Array> v8::Object::GetPropertyNames() {
2318 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
2319 ENTER_V8;
2320 v8::HandleScope scope;
2321 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2322 i::Handle<i::FixedArray> value =
2323 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2324 // Because we use caching to speed up enumeration it is important
2325 // to never change the result of the basic enumeration function so
2326 // we clone the result.
2327 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
2328 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
2329 return scope.Close(Utils::ToLocal(result));
2330}
2331
2332
2333Local<String> v8::Object::ObjectProtoToString() {
2334 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2335 ENTER_V8;
2336 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2337
2338 i::Handle<i::Object> name(self->class_name());
2339
2340 // Native implementation of Object.prototype.toString (v8natives.js):
2341 // var c = %ClassOf(this);
2342 // if (c === 'Arguments') c = 'Object';
2343 // return "[object " + c + "]";
2344
2345 if (!name->IsString()) {
2346 return v8::String::New("[object ]");
2347
2348 } else {
2349 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2350 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2351 return v8::String::New("[object Object]");
2352
2353 } else {
2354 const char* prefix = "[object ";
2355 Local<String> str = Utils::ToLocal(class_name);
2356 const char* postfix = "]";
2357
Steve Blockd0582a62009-12-15 09:54:21 +00002358 int prefix_len = i::StrLength(prefix);
2359 int str_len = str->Length();
2360 int postfix_len = i::StrLength(postfix);
Steve Blocka7e24c12009-10-30 11:49:00 +00002361
Steve Blockd0582a62009-12-15 09:54:21 +00002362 int buf_len = prefix_len + str_len + postfix_len;
Kristian Monsen25f61362010-05-21 11:50:48 +01002363 i::ScopedVector<char> buf(buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002364
2365 // Write prefix.
Kristian Monsen25f61362010-05-21 11:50:48 +01002366 char* ptr = buf.start();
Steve Blocka7e24c12009-10-30 11:49:00 +00002367 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2368 ptr += prefix_len;
2369
2370 // Write real content.
2371 str->WriteAscii(ptr, 0, str_len);
2372 ptr += str_len;
2373
2374 // Write postfix.
2375 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2376
2377 // Copy the buffer into a heap-allocated string and return it.
Kristian Monsen25f61362010-05-21 11:50:48 +01002378 Local<String> result = v8::String::New(buf.start(), buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002379 return result;
2380 }
2381 }
2382}
2383
2384
2385bool v8::Object::Delete(v8::Handle<String> key) {
2386 ON_BAILOUT("v8::Object::Delete()", return false);
2387 ENTER_V8;
2388 HandleScope scope;
2389 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2390 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2391 return i::DeleteProperty(self, key_obj)->IsTrue();
2392}
2393
2394
2395bool v8::Object::Has(v8::Handle<String> key) {
2396 ON_BAILOUT("v8::Object::Has()", return false);
2397 ENTER_V8;
2398 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2399 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2400 return self->HasProperty(*key_obj);
2401}
2402
2403
2404bool v8::Object::Delete(uint32_t index) {
2405 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2406 ENTER_V8;
2407 HandleScope scope;
2408 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2409 return i::DeleteElement(self, index)->IsTrue();
2410}
2411
2412
2413bool v8::Object::Has(uint32_t index) {
2414 ON_BAILOUT("v8::Object::HasProperty()", return false);
2415 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2416 return self->HasElement(index);
2417}
2418
2419
Leon Clarkef7060e22010-06-03 12:02:55 +01002420bool Object::SetAccessor(Handle<String> name,
2421 AccessorGetter getter,
2422 AccessorSetter setter,
2423 v8::Handle<Value> data,
2424 AccessControl settings,
2425 PropertyAttribute attributes) {
2426 ON_BAILOUT("v8::Object::SetAccessor()", return false);
2427 ENTER_V8;
2428 HandleScope scope;
2429 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name,
2430 getter, setter, data,
2431 settings, attributes);
2432 i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info);
2433 return !result.is_null() && !result->IsUndefined();
2434}
2435
2436
Steve Blocka7e24c12009-10-30 11:49:00 +00002437bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2438 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2439 return Utils::OpenHandle(this)->HasRealNamedProperty(
2440 *Utils::OpenHandle(*key));
2441}
2442
2443
2444bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2445 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2446 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2447}
2448
2449
2450bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2451 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2452 ENTER_V8;
2453 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2454 *Utils::OpenHandle(*key));
2455}
2456
2457
2458bool v8::Object::HasNamedLookupInterceptor() {
2459 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2460 return Utils::OpenHandle(this)->HasNamedInterceptor();
2461}
2462
2463
2464bool v8::Object::HasIndexedLookupInterceptor() {
2465 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2466 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2467}
2468
2469
2470Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2471 Handle<String> key) {
2472 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2473 return Local<Value>());
2474 ENTER_V8;
2475 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2476 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2477 i::LookupResult lookup;
2478 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002479 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002480 PropertyAttributes attributes;
2481 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2482 &lookup,
2483 *key_obj,
2484 &attributes));
2485 return Utils::ToLocal(result);
2486 }
2487 return Local<Value>(); // No real property was found in prototype chain.
2488}
2489
2490
2491Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2492 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
2493 ENTER_V8;
2494 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2495 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2496 i::LookupResult lookup;
2497 self_obj->LookupRealNamedProperty(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002498 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002499 PropertyAttributes attributes;
2500 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2501 &lookup,
2502 *key_obj,
2503 &attributes));
2504 return Utils::ToLocal(result);
2505 }
2506 return Local<Value>(); // No real property was found in prototype chain.
2507}
2508
2509
2510// Turns on access checks by copying the map and setting the check flag.
2511// Because the object gets a new map, existing inline cache caching
2512// the old map of this object will fail.
2513void v8::Object::TurnOnAccessCheck() {
2514 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2515 ENTER_V8;
2516 HandleScope scope;
2517 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2518
2519 i::Handle<i::Map> new_map =
2520 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2521 new_map->set_is_access_check_needed(true);
2522 obj->set_map(*new_map);
2523}
2524
2525
2526bool v8::Object::IsDirty() {
2527 return Utils::OpenHandle(this)->IsDirty();
2528}
2529
2530
2531Local<v8::Object> v8::Object::Clone() {
2532 ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2533 ENTER_V8;
2534 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2535 EXCEPTION_PREAMBLE();
2536 i::Handle<i::JSObject> result = i::Copy(self);
2537 has_pending_exception = result.is_null();
2538 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2539 return Utils::ToLocal(result);
2540}
2541
2542
2543int v8::Object::GetIdentityHash() {
2544 ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2545 ENTER_V8;
2546 HandleScope scope;
2547 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2548 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2549 i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
2550 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2551 int hash_value;
2552 if (hash->IsSmi()) {
2553 hash_value = i::Smi::cast(*hash)->value();
2554 } else {
2555 int attempts = 0;
2556 do {
2557 // Generate a random 32-bit hash value but limit range to fit
2558 // within a smi.
2559 hash_value = i::V8::Random() & i::Smi::kMaxValue;
2560 attempts++;
2561 } while (hash_value == 0 && attempts < 30);
2562 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
2563 i::SetProperty(hidden_props,
2564 hash_symbol,
2565 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2566 static_cast<PropertyAttributes>(None));
2567 }
2568 return hash_value;
2569}
2570
2571
2572bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2573 v8::Handle<v8::Value> value) {
2574 ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
2575 ENTER_V8;
2576 HandleScope scope;
2577 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2578 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2579 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2580 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2581 EXCEPTION_PREAMBLE();
2582 i::Handle<i::Object> obj = i::SetProperty(
2583 hidden_props,
2584 key_obj,
2585 value_obj,
2586 static_cast<PropertyAttributes>(None));
2587 has_pending_exception = obj.is_null();
2588 EXCEPTION_BAILOUT_CHECK(false);
2589 return true;
2590}
2591
2592
2593v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2594 ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2595 ENTER_V8;
2596 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2597 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2598 if (hidden_props->IsUndefined()) {
2599 return v8::Local<v8::Value>();
2600 }
2601 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2602 EXCEPTION_PREAMBLE();
2603 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2604 has_pending_exception = result.is_null();
2605 EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2606 if (result->IsUndefined()) {
2607 return v8::Local<v8::Value>();
2608 }
2609 return Utils::ToLocal(result);
2610}
2611
2612
2613bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2614 ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2615 ENTER_V8;
2616 HandleScope scope;
2617 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2618 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2619 if (hidden_props->IsUndefined()) {
2620 return true;
2621 }
2622 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2623 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2624 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2625}
2626
2627
2628void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2629 ON_BAILOUT("v8::SetElementsToPixelData()", return);
2630 ENTER_V8;
2631 HandleScope scope;
Steve Block3ce2e202009-11-05 08:53:23 +00002632 if (!ApiCheck(length <= i::PixelArray::kMaxLength,
Steve Blocka7e24c12009-10-30 11:49:00 +00002633 "v8::Object::SetIndexedPropertiesToPixelData()",
2634 "length exceeds max acceptable value")) {
2635 return;
2636 }
2637 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2638 if (!ApiCheck(!self->IsJSArray(),
2639 "v8::Object::SetIndexedPropertiesToPixelData()",
2640 "JSArray is not supported")) {
2641 return;
2642 }
2643 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
Steve Block8defd9f2010-07-08 12:39:36 +01002644 self->set_map(
2645 *i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map())));
Steve Blocka7e24c12009-10-30 11:49:00 +00002646 self->set_elements(*pixels);
2647}
2648
2649
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002650bool v8::Object::HasIndexedPropertiesInPixelData() {
2651 ON_BAILOUT("v8::HasIndexedPropertiesInPixelData()", return false);
2652 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2653 return self->HasPixelElements();
2654}
2655
2656
2657uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
2658 ON_BAILOUT("v8::GetIndexedPropertiesPixelData()", return NULL);
2659 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2660 if (self->HasPixelElements()) {
2661 return i::PixelArray::cast(self->elements())->external_pointer();
2662 } else {
2663 return NULL;
2664 }
2665}
2666
2667
2668int v8::Object::GetIndexedPropertiesPixelDataLength() {
2669 ON_BAILOUT("v8::GetIndexedPropertiesPixelDataLength()", return -1);
2670 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2671 if (self->HasPixelElements()) {
2672 return i::PixelArray::cast(self->elements())->length();
2673 } else {
2674 return -1;
2675 }
2676}
2677
2678
Steve Block3ce2e202009-11-05 08:53:23 +00002679void v8::Object::SetIndexedPropertiesToExternalArrayData(
2680 void* data,
2681 ExternalArrayType array_type,
2682 int length) {
2683 ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
2684 ENTER_V8;
2685 HandleScope scope;
2686 if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
2687 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2688 "length exceeds max acceptable value")) {
2689 return;
2690 }
2691 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2692 if (!ApiCheck(!self->IsJSArray(),
2693 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2694 "JSArray is not supported")) {
2695 return;
2696 }
2697 i::Handle<i::ExternalArray> array =
2698 i::Factory::NewExternalArray(length, array_type, data);
Steve Block8defd9f2010-07-08 12:39:36 +01002699 self->set_map(
2700 *i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map())));
Steve Block3ce2e202009-11-05 08:53:23 +00002701 self->set_elements(*array);
2702}
2703
2704
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002705bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
2706 ON_BAILOUT("v8::HasIndexedPropertiesInExternalArrayData()", return false);
2707 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2708 return self->HasExternalArrayElements();
2709}
2710
2711
2712void* v8::Object::GetIndexedPropertiesExternalArrayData() {
2713 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayData()", return NULL);
2714 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2715 if (self->HasExternalArrayElements()) {
2716 return i::ExternalArray::cast(self->elements())->external_pointer();
2717 } else {
2718 return NULL;
2719 }
2720}
2721
2722
2723ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
2724 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataType()",
2725 return static_cast<ExternalArrayType>(-1));
2726 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2727 switch (self->elements()->map()->instance_type()) {
2728 case i::EXTERNAL_BYTE_ARRAY_TYPE:
2729 return kExternalByteArray;
2730 case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2731 return kExternalUnsignedByteArray;
2732 case i::EXTERNAL_SHORT_ARRAY_TYPE:
2733 return kExternalShortArray;
2734 case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2735 return kExternalUnsignedShortArray;
2736 case i::EXTERNAL_INT_ARRAY_TYPE:
2737 return kExternalIntArray;
2738 case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2739 return kExternalUnsignedIntArray;
2740 case i::EXTERNAL_FLOAT_ARRAY_TYPE:
2741 return kExternalFloatArray;
2742 default:
2743 return static_cast<ExternalArrayType>(-1);
2744 }
2745}
2746
2747
2748int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
2749 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataLength()", return 0);
2750 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2751 if (self->HasExternalArrayElements()) {
2752 return i::ExternalArray::cast(self->elements())->length();
2753 } else {
2754 return -1;
2755 }
2756}
2757
2758
Steve Blocka7e24c12009-10-30 11:49:00 +00002759Local<v8::Object> Function::NewInstance() const {
2760 return NewInstance(0, NULL);
2761}
2762
2763
2764Local<v8::Object> Function::NewInstance(int argc,
2765 v8::Handle<v8::Value> argv[]) const {
2766 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2767 LOG_API("Function::NewInstance");
2768 ENTER_V8;
2769 HandleScope scope;
2770 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2771 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2772 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2773 EXCEPTION_PREAMBLE();
2774 i::Handle<i::Object> returned =
2775 i::Execution::New(function, argc, args, &has_pending_exception);
2776 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2777 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2778}
2779
2780
2781Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2782 v8::Handle<v8::Value> argv[]) {
2783 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2784 LOG_API("Function::Call");
2785 ENTER_V8;
2786 i::Object* raw_result = NULL;
2787 {
2788 HandleScope scope;
2789 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2790 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2791 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2792 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2793 EXCEPTION_PREAMBLE();
2794 i::Handle<i::Object> returned =
2795 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2796 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2797 raw_result = *returned;
2798 }
2799 i::Handle<i::Object> result(raw_result);
2800 return Utils::ToLocal(result);
2801}
2802
2803
2804void Function::SetName(v8::Handle<v8::String> name) {
2805 ENTER_V8;
2806 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2807 func->shared()->set_name(*Utils::OpenHandle(*name));
2808}
2809
2810
2811Handle<Value> Function::GetName() const {
2812 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2813 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2814}
2815
2816
Andrei Popescu402d9372010-02-26 13:31:12 +00002817ScriptOrigin Function::GetScriptOrigin() const {
2818 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2819 if (func->shared()->script()->IsScript()) {
2820 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2821 v8::ScriptOrigin origin(
2822 Utils::ToLocal(i::Handle<i::Object>(script->name())),
2823 v8::Integer::New(script->line_offset()->value()),
2824 v8::Integer::New(script->column_offset()->value()));
2825 return origin;
2826 }
2827 return v8::ScriptOrigin(Handle<Value>());
2828}
2829
2830
2831const int Function::kLineOffsetNotFound = -1;
2832
2833
2834int Function::GetScriptLineNumber() const {
2835 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2836 if (func->shared()->script()->IsScript()) {
2837 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2838 return i::GetScriptLineNumber(script, func->shared()->start_position());
2839 }
2840 return kLineOffsetNotFound;
2841}
2842
2843
2844namespace {
2845
2846// Tracks string usage to help make better decisions when
2847// externalizing strings.
2848//
2849// Implementation note: internally this class only tracks fresh
2850// strings and keeps a single use counter for them.
2851class StringTracker {
2852 public:
2853 // Records that the given string's characters were copied to some
2854 // external buffer. If this happens often we should honor
2855 // externalization requests for the string.
2856 static void RecordWrite(i::Handle<i::String> string) {
2857 i::Address address = reinterpret_cast<i::Address>(*string);
2858 i::Address top = i::Heap::NewSpaceTop();
2859 if (IsFreshString(address, top)) {
2860 IncrementUseCount(top);
2861 }
2862 }
2863
2864 // Estimates freshness and use frequency of the given string based
2865 // on how close it is to the new space top and the recorded usage
2866 // history.
2867 static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
2868 i::Address address = reinterpret_cast<i::Address>(*string);
2869 i::Address top = i::Heap::NewSpaceTop();
2870 return IsFreshString(address, top) && IsUseCountLow(top);
2871 }
2872
2873 private:
2874 static inline bool IsFreshString(i::Address string, i::Address top) {
2875 return top - kFreshnessLimit <= string && string <= top;
2876 }
2877
2878 static inline bool IsUseCountLow(i::Address top) {
2879 if (last_top_ != top) return true;
2880 return use_count_ < kUseLimit;
2881 }
2882
2883 static inline void IncrementUseCount(i::Address top) {
2884 if (last_top_ != top) {
2885 use_count_ = 0;
2886 last_top_ = top;
2887 }
2888 ++use_count_;
2889 }
2890
2891 // How close to the new space top a fresh string has to be.
2892 static const int kFreshnessLimit = 1024;
2893
2894 // The number of uses required to consider a string useful.
2895 static const int kUseLimit = 32;
2896
2897 // Single use counter shared by all fresh strings.
2898 static int use_count_;
2899
2900 // Last new space top when the use count above was valid.
2901 static i::Address last_top_;
2902};
2903
2904int StringTracker::use_count_ = 0;
2905i::Address StringTracker::last_top_ = NULL;
2906
2907} // namespace
2908
2909
Steve Blocka7e24c12009-10-30 11:49:00 +00002910int String::Length() const {
2911 if (IsDeadCheck("v8::String::Length()")) return 0;
2912 return Utils::OpenHandle(this)->length();
2913}
2914
2915
2916int String::Utf8Length() const {
2917 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
2918 return Utils::OpenHandle(this)->Utf8Length();
2919}
2920
2921
Steve Block6ded16b2010-05-10 14:33:55 +01002922int String::WriteUtf8(char* buffer,
2923 int capacity,
2924 int* nchars_ref,
2925 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002926 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
2927 LOG_API("String::WriteUtf8");
2928 ENTER_V8;
2929 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002930 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002931 if (hints & HINT_MANY_WRITES_EXPECTED) {
2932 // Flatten the string for efficiency. This applies whether we are
2933 // using StringInputBuffer or Get(i) to access the characters.
2934 str->TryFlatten();
2935 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002936 write_input_buffer.Reset(0, *str);
2937 int len = str->length();
2938 // Encode the first K - 3 bytes directly into the buffer since we
2939 // know there's room for them. If no capacity is given we copy all
2940 // of them here.
2941 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
2942 int i;
2943 int pos = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01002944 int nchars = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002945 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
2946 i::uc32 c = write_input_buffer.GetNext();
2947 int written = unibrow::Utf8::Encode(buffer + pos, c);
2948 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002949 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002950 }
2951 if (i < len) {
2952 // For the last characters we need to check the length for each one
2953 // because they may be longer than the remaining space in the
2954 // buffer.
2955 char intermediate[unibrow::Utf8::kMaxEncodedSize];
2956 for (; i < len && pos < capacity; i++) {
2957 i::uc32 c = write_input_buffer.GetNext();
2958 int written = unibrow::Utf8::Encode(intermediate, c);
2959 if (pos + written <= capacity) {
2960 for (int j = 0; j < written; j++)
2961 buffer[pos + j] = intermediate[j];
2962 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002963 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002964 } else {
2965 // We've reached the end of the buffer
2966 break;
2967 }
2968 }
2969 }
Steve Block6ded16b2010-05-10 14:33:55 +01002970 if (nchars_ref != NULL) *nchars_ref = nchars;
Steve Blocka7e24c12009-10-30 11:49:00 +00002971 if (i == len && (capacity == -1 || pos < capacity))
2972 buffer[pos++] = '\0';
2973 return pos;
2974}
2975
2976
Steve Block6ded16b2010-05-10 14:33:55 +01002977int String::WriteAscii(char* buffer,
2978 int start,
2979 int length,
2980 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002981 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
2982 LOG_API("String::WriteAscii");
2983 ENTER_V8;
2984 ASSERT(start >= 0 && length >= -1);
2985 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002986 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002987 if (hints & HINT_MANY_WRITES_EXPECTED) {
2988 // Flatten the string for efficiency. This applies whether we are
2989 // using StringInputBuffer or Get(i) to access the characters.
2990 str->TryFlatten();
2991 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002992 int end = length;
2993 if ( (length == -1) || (length > str->length() - start) )
2994 end = str->length() - start;
2995 if (end < 0) return 0;
2996 write_input_buffer.Reset(start, *str);
2997 int i;
2998 for (i = 0; i < end; i++) {
2999 char c = static_cast<char>(write_input_buffer.GetNext());
3000 if (c == '\0') c = ' ';
3001 buffer[i] = c;
3002 }
3003 if (length == -1 || i < length)
3004 buffer[i] = '\0';
3005 return i;
3006}
3007
3008
Steve Block6ded16b2010-05-10 14:33:55 +01003009int String::Write(uint16_t* buffer,
3010 int start,
3011 int length,
3012 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003013 if (IsDeadCheck("v8::String::Write()")) return 0;
3014 LOG_API("String::Write");
3015 ENTER_V8;
3016 ASSERT(start >= 0 && length >= -1);
3017 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003018 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003019 if (hints & HINT_MANY_WRITES_EXPECTED) {
3020 // Flatten the string for efficiency. This applies whether we are
3021 // using StringInputBuffer or Get(i) to access the characters.
3022 str->TryFlatten();
3023 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003024 int end = length;
3025 if ( (length == -1) || (length > str->length() - start) )
3026 end = str->length() - start;
3027 if (end < 0) return 0;
3028 i::String::WriteToFlat(*str, buffer, start, end);
3029 if (length == -1 || end < length)
3030 buffer[end] = '\0';
3031 return end;
3032}
3033
3034
3035bool v8::String::IsExternal() const {
3036 EnsureInitialized("v8::String::IsExternal()");
3037 i::Handle<i::String> str = Utils::OpenHandle(this);
3038 return i::StringShape(*str).IsExternalTwoByte();
3039}
3040
3041
3042bool v8::String::IsExternalAscii() const {
3043 EnsureInitialized("v8::String::IsExternalAscii()");
3044 i::Handle<i::String> str = Utils::OpenHandle(this);
3045 return i::StringShape(*str).IsExternalAscii();
3046}
3047
3048
3049void v8::String::VerifyExternalStringResource(
3050 v8::String::ExternalStringResource* value) const {
3051 i::Handle<i::String> str = Utils::OpenHandle(this);
3052 v8::String::ExternalStringResource* expected;
3053 if (i::StringShape(*str).IsExternalTwoByte()) {
3054 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
3055 expected = reinterpret_cast<ExternalStringResource*>(resource);
3056 } else {
3057 expected = NULL;
3058 }
3059 CHECK_EQ(expected, value);
3060}
3061
3062
3063v8::String::ExternalAsciiStringResource*
3064 v8::String::GetExternalAsciiStringResource() const {
3065 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
3066 i::Handle<i::String> str = Utils::OpenHandle(this);
3067 if (i::StringShape(*str).IsExternalAscii()) {
3068 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
3069 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
3070 } else {
3071 return NULL;
3072 }
3073}
3074
3075
3076double Number::Value() const {
3077 if (IsDeadCheck("v8::Number::Value()")) return 0;
3078 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3079 return obj->Number();
3080}
3081
3082
3083bool Boolean::Value() const {
3084 if (IsDeadCheck("v8::Boolean::Value()")) return false;
3085 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3086 return obj->IsTrue();
3087}
3088
3089
3090int64_t Integer::Value() const {
3091 if (IsDeadCheck("v8::Integer::Value()")) return 0;
3092 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3093 if (obj->IsSmi()) {
3094 return i::Smi::cast(*obj)->value();
3095 } else {
3096 return static_cast<int64_t>(obj->Number());
3097 }
3098}
3099
3100
3101int32_t Int32::Value() const {
3102 if (IsDeadCheck("v8::Int32::Value()")) return 0;
3103 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3104 if (obj->IsSmi()) {
3105 return i::Smi::cast(*obj)->value();
3106 } else {
3107 return static_cast<int32_t>(obj->Number());
3108 }
3109}
3110
3111
Steve Block6ded16b2010-05-10 14:33:55 +01003112uint32_t Uint32::Value() const {
3113 if (IsDeadCheck("v8::Uint32::Value()")) return 0;
3114 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3115 if (obj->IsSmi()) {
3116 return i::Smi::cast(*obj)->value();
3117 } else {
3118 return static_cast<uint32_t>(obj->Number());
3119 }
3120}
3121
3122
Steve Blocka7e24c12009-10-30 11:49:00 +00003123int v8::Object::InternalFieldCount() {
3124 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
3125 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3126 return obj->GetInternalFieldCount();
3127}
3128
3129
3130Local<Value> v8::Object::CheckedGetInternalField(int index) {
3131 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
3132 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3133 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3134 "v8::Object::GetInternalField()",
3135 "Reading internal field out of bounds")) {
3136 return Local<Value>();
3137 }
3138 i::Handle<i::Object> value(obj->GetInternalField(index));
3139 Local<Value> result = Utils::ToLocal(value);
3140#ifdef DEBUG
3141 Local<Value> unchecked = UncheckedGetInternalField(index);
3142 ASSERT(unchecked.IsEmpty() || (unchecked == result));
3143#endif
3144 return result;
3145}
3146
3147
3148void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
3149 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
3150 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3151 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3152 "v8::Object::SetInternalField()",
3153 "Writing internal field out of bounds")) {
3154 return;
3155 }
3156 ENTER_V8;
3157 i::Handle<i::Object> val = Utils::OpenHandle(*value);
3158 obj->SetInternalField(index, *val);
3159}
3160
3161
3162void v8::Object::SetPointerInInternalField(int index, void* value) {
Steve Block6ded16b2010-05-10 14:33:55 +01003163 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003164 i::Object* as_object = reinterpret_cast<i::Object*>(value);
3165 if (as_object->IsSmi()) {
3166 Utils::OpenHandle(this)->SetInternalField(index, as_object);
3167 return;
3168 }
3169 HandleScope scope;
3170 i::Handle<i::Proxy> proxy =
3171 i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
3172 if (!proxy.is_null())
3173 Utils::OpenHandle(this)->SetInternalField(index, *proxy);
Steve Blocka7e24c12009-10-30 11:49:00 +00003174}
3175
3176
3177// --- E n v i r o n m e n t ---
3178
3179bool v8::V8::Initialize() {
3180 if (i::V8::IsRunning()) return true;
3181 ENTER_V8;
3182 HandleScope scope;
Steve Blockd0582a62009-12-15 09:54:21 +00003183 if (i::Snapshot::Initialize()) return true;
3184 return i::V8::Initialize(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00003185}
3186
3187
3188bool v8::V8::Dispose() {
3189 i::V8::TearDown();
3190 return true;
3191}
3192
3193
Steve Block3ce2e202009-11-05 08:53:23 +00003194HeapStatistics::HeapStatistics(): total_heap_size_(0), used_heap_size_(0) { }
3195
3196
3197void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
3198 heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
3199 heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
3200}
3201
3202
3203bool v8::V8::IdleNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003204 // Returning true tells the caller that it need not
3205 // continue to call IdleNotification.
3206 if (!i::V8::IsRunning()) return true;
Steve Block3ce2e202009-11-05 08:53:23 +00003207 return i::V8::IdleNotification();
Steve Blocka7e24c12009-10-30 11:49:00 +00003208}
3209
3210
3211void v8::V8::LowMemoryNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003212 if (!i::V8::IsRunning()) return;
3213 i::Heap::CollectAllGarbage(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00003214}
3215
3216
Steve Block6ded16b2010-05-10 14:33:55 +01003217int v8::V8::ContextDisposedNotification() {
3218 if (!i::V8::IsRunning()) return 0;
3219 return i::Heap::NotifyContextDisposed();
3220}
3221
3222
Steve Blocka7e24c12009-10-30 11:49:00 +00003223const char* v8::V8::GetVersion() {
3224 static v8::internal::EmbeddedVector<char, 128> buffer;
3225 v8::internal::Version::GetString(buffer);
3226 return buffer.start();
3227}
3228
3229
3230static i::Handle<i::FunctionTemplateInfo>
3231 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
3232 if (templ->constructor()->IsUndefined()) {
3233 Local<FunctionTemplate> constructor = FunctionTemplate::New();
3234 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
3235 templ->set_constructor(*Utils::OpenHandle(*constructor));
3236 }
3237 return i::Handle<i::FunctionTemplateInfo>(
3238 i::FunctionTemplateInfo::cast(templ->constructor()));
3239}
3240
3241
3242Persistent<Context> v8::Context::New(
3243 v8::ExtensionConfiguration* extensions,
3244 v8::Handle<ObjectTemplate> global_template,
3245 v8::Handle<Value> global_object) {
3246 EnsureInitialized("v8::Context::New()");
3247 LOG_API("Context::New");
3248 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
3249
3250 // Enter V8 via an ENTER_V8 scope.
3251 i::Handle<i::Context> env;
3252 {
3253 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003254 v8::Handle<ObjectTemplate> proxy_template = global_template;
3255 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
3256 i::Handle<i::FunctionTemplateInfo> global_constructor;
3257
3258 if (!global_template.IsEmpty()) {
3259 // Make sure that the global_template has a constructor.
3260 global_constructor =
3261 EnsureConstructor(Utils::OpenHandle(*global_template));
3262
3263 // Create a fresh template for the global proxy object.
3264 proxy_template = ObjectTemplate::New();
3265 proxy_constructor =
3266 EnsureConstructor(Utils::OpenHandle(*proxy_template));
3267
3268 // Set the global template to be the prototype template of
3269 // global proxy template.
3270 proxy_constructor->set_prototype_template(
3271 *Utils::OpenHandle(*global_template));
3272
3273 // Migrate security handlers from global_template to
3274 // proxy_template. Temporarily removing access check
3275 // information from the global template.
3276 if (!global_constructor->access_check_info()->IsUndefined()) {
3277 proxy_constructor->set_access_check_info(
3278 global_constructor->access_check_info());
3279 proxy_constructor->set_needs_access_check(
3280 global_constructor->needs_access_check());
3281 global_constructor->set_needs_access_check(false);
3282 global_constructor->set_access_check_info(i::Heap::undefined_value());
3283 }
3284 }
3285
3286 // Create the environment.
3287 env = i::Bootstrapper::CreateEnvironment(
3288 Utils::OpenHandle(*global_object),
3289 proxy_template,
3290 extensions);
3291
3292 // Restore the access check info on the global template.
3293 if (!global_template.IsEmpty()) {
3294 ASSERT(!global_constructor.is_null());
3295 ASSERT(!proxy_constructor.is_null());
3296 global_constructor->set_access_check_info(
3297 proxy_constructor->access_check_info());
3298 global_constructor->set_needs_access_check(
3299 proxy_constructor->needs_access_check());
3300 }
3301 }
3302 // Leave V8.
3303
3304 if (env.is_null())
3305 return Persistent<Context>();
3306 return Persistent<Context>(Utils::ToLocal(env));
3307}
3308
3309
3310void v8::Context::SetSecurityToken(Handle<Value> token) {
3311 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
3312 ENTER_V8;
3313 i::Handle<i::Context> env = Utils::OpenHandle(this);
3314 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
3315 env->set_security_token(*token_handle);
3316}
3317
3318
3319void v8::Context::UseDefaultSecurityToken() {
3320 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
3321 ENTER_V8;
3322 i::Handle<i::Context> env = Utils::OpenHandle(this);
3323 env->set_security_token(env->global());
3324}
3325
3326
3327Handle<Value> v8::Context::GetSecurityToken() {
3328 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
3329 i::Handle<i::Context> env = Utils::OpenHandle(this);
3330 i::Object* security_token = env->security_token();
3331 i::Handle<i::Object> token_handle(security_token);
3332 return Utils::ToLocal(token_handle);
3333}
3334
3335
3336bool Context::HasOutOfMemoryException() {
3337 i::Handle<i::Context> env = Utils::OpenHandle(this);
3338 return env->has_out_of_memory();
3339}
3340
3341
3342bool Context::InContext() {
3343 return i::Top::context() != NULL;
3344}
3345
3346
3347v8::Local<v8::Context> Context::GetEntered() {
3348 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
3349 i::Handle<i::Object> last = thread_local.LastEnteredContext();
3350 if (last.is_null()) return Local<Context>();
3351 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
3352 return Utils::ToLocal(context);
3353}
3354
3355
3356v8::Local<v8::Context> Context::GetCurrent() {
3357 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
Steve Block3ce2e202009-11-05 08:53:23 +00003358 i::Handle<i::Object> current = i::Top::global_context();
3359 if (current.is_null()) return Local<Context>();
3360 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
Steve Blocka7e24c12009-10-30 11:49:00 +00003361 return Utils::ToLocal(context);
3362}
3363
3364
3365v8::Local<v8::Context> Context::GetCalling() {
3366 if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
3367 i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
3368 if (calling.is_null()) return Local<Context>();
3369 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
3370 return Utils::ToLocal(context);
3371}
3372
3373
3374v8::Local<v8::Object> Context::Global() {
3375 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
3376 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3377 i::Handle<i::Context> context =
3378 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3379 i::Handle<i::Object> global(context->global_proxy());
3380 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
3381}
3382
3383
3384void Context::DetachGlobal() {
3385 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
3386 ENTER_V8;
3387 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3388 i::Handle<i::Context> context =
3389 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3390 i::Bootstrapper::DetachGlobal(context);
3391}
3392
3393
Andrei Popescu74b3c142010-03-29 12:03:09 +01003394void Context::ReattachGlobal(Handle<Object> global_object) {
3395 if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
3396 ENTER_V8;
3397 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3398 i::Handle<i::Context> context =
3399 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3400 i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
3401}
3402
3403
Steve Blocka7e24c12009-10-30 11:49:00 +00003404Local<v8::Object> ObjectTemplate::NewInstance() {
3405 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
3406 LOG_API("ObjectTemplate::NewInstance");
3407 ENTER_V8;
3408 EXCEPTION_PREAMBLE();
3409 i::Handle<i::Object> obj =
3410 i::Execution::InstantiateObject(Utils::OpenHandle(this),
3411 &has_pending_exception);
3412 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
3413 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3414}
3415
3416
3417Local<v8::Function> FunctionTemplate::GetFunction() {
3418 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
3419 return Local<v8::Function>());
3420 LOG_API("FunctionTemplate::GetFunction");
3421 ENTER_V8;
3422 EXCEPTION_PREAMBLE();
3423 i::Handle<i::Object> obj =
3424 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3425 &has_pending_exception);
3426 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
3427 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3428}
3429
3430
3431bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3432 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
3433 i::Object* obj = *Utils::OpenHandle(*value);
3434 return obj->IsInstanceOf(*Utils::OpenHandle(this));
3435}
3436
3437
3438static Local<External> ExternalNewImpl(void* data) {
3439 return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
3440}
3441
3442static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3443 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3444}
3445
3446
Steve Blocka7e24c12009-10-30 11:49:00 +00003447Local<Value> v8::External::Wrap(void* data) {
3448 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3449 LOG_API("External::Wrap");
3450 EnsureInitialized("v8::External::Wrap()");
3451 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003452 i::Object* as_object = reinterpret_cast<i::Object*>(data);
3453 if (as_object->IsSmi()) {
3454 return Utils::ToLocal(i::Handle<i::Object>(as_object));
Steve Blocka7e24c12009-10-30 11:49:00 +00003455 }
3456 return ExternalNewImpl(data);
3457}
3458
3459
Steve Block3ce2e202009-11-05 08:53:23 +00003460void* v8::Object::SlowGetPointerFromInternalField(int index) {
3461 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3462 i::Object* value = obj->GetInternalField(index);
3463 if (value->IsSmi()) {
3464 return value;
3465 } else if (value->IsProxy()) {
3466 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3467 } else {
3468 return NULL;
3469 }
3470}
3471
3472
Steve Blocka7e24c12009-10-30 11:49:00 +00003473void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3474 if (IsDeadCheck("v8::External::Unwrap()")) return 0;
3475 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3476 void* result;
3477 if (obj->IsSmi()) {
3478 // The external value was an aligned pointer.
Steve Block3ce2e202009-11-05 08:53:23 +00003479 result = *obj;
Steve Blocka7e24c12009-10-30 11:49:00 +00003480 } else if (obj->IsProxy()) {
3481 result = ExternalValueImpl(obj);
3482 } else {
3483 result = NULL;
3484 }
3485 ASSERT_EQ(result, QuickUnwrap(wrapper));
3486 return result;
3487}
3488
3489
3490Local<External> v8::External::New(void* data) {
3491 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3492 LOG_API("External::New");
3493 EnsureInitialized("v8::External::New()");
3494 ENTER_V8;
3495 return ExternalNewImpl(data);
3496}
3497
3498
3499void* External::Value() const {
3500 if (IsDeadCheck("v8::External::Value()")) return 0;
3501 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3502 return ExternalValueImpl(obj);
3503}
3504
3505
3506Local<String> v8::String::Empty() {
3507 EnsureInitialized("v8::String::Empty()");
3508 LOG_API("String::Empty()");
3509 return Utils::ToLocal(i::Factory::empty_symbol());
3510}
3511
3512
3513Local<String> v8::String::New(const char* data, int length) {
3514 EnsureInitialized("v8::String::New()");
3515 LOG_API("String::New(char)");
3516 if (length == 0) return Empty();
3517 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003518 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003519 i::Handle<i::String> result =
3520 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3521 return Utils::ToLocal(result);
3522}
3523
3524
Steve Block3ce2e202009-11-05 08:53:23 +00003525Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3526 EnsureInitialized("v8::String::New()");
3527 LOG_API("String::New(char)");
3528 ENTER_V8;
3529 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3530 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3531 i::Handle<i::String> result = i::Factory::NewConsString(left_string,
3532 right_string);
3533 return Utils::ToLocal(result);
3534}
3535
3536
Steve Blocka7e24c12009-10-30 11:49:00 +00003537Local<String> v8::String::NewUndetectable(const char* data, int length) {
3538 EnsureInitialized("v8::String::NewUndetectable()");
3539 LOG_API("String::NewUndetectable(char)");
3540 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003541 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003542 i::Handle<i::String> result =
3543 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3544 result->MarkAsUndetectable();
3545 return Utils::ToLocal(result);
3546}
3547
3548
3549static int TwoByteStringLength(const uint16_t* data) {
3550 int length = 0;
3551 while (data[length] != '\0') length++;
3552 return length;
3553}
3554
3555
3556Local<String> v8::String::New(const uint16_t* data, int length) {
3557 EnsureInitialized("v8::String::New()");
3558 LOG_API("String::New(uint16_)");
3559 if (length == 0) return Empty();
3560 ENTER_V8;
3561 if (length == -1) length = TwoByteStringLength(data);
3562 i::Handle<i::String> result =
3563 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3564 return Utils::ToLocal(result);
3565}
3566
3567
3568Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
3569 EnsureInitialized("v8::String::NewUndetectable()");
3570 LOG_API("String::NewUndetectable(uint16_)");
3571 ENTER_V8;
3572 if (length == -1) length = TwoByteStringLength(data);
3573 i::Handle<i::String> result =
3574 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3575 result->MarkAsUndetectable();
3576 return Utils::ToLocal(result);
3577}
3578
3579
3580i::Handle<i::String> NewExternalStringHandle(
3581 v8::String::ExternalStringResource* resource) {
3582 i::Handle<i::String> result =
3583 i::Factory::NewExternalStringFromTwoByte(resource);
3584 return result;
3585}
3586
3587
3588i::Handle<i::String> NewExternalAsciiStringHandle(
3589 v8::String::ExternalAsciiStringResource* resource) {
3590 i::Handle<i::String> result =
3591 i::Factory::NewExternalStringFromAscii(resource);
3592 return result;
3593}
3594
3595
Steve Blocka7e24c12009-10-30 11:49:00 +00003596Local<String> v8::String::NewExternal(
3597 v8::String::ExternalStringResource* resource) {
3598 EnsureInitialized("v8::String::NewExternal()");
3599 LOG_API("String::NewExternal");
3600 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003601 i::Handle<i::String> result = NewExternalStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003602 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003603 return Utils::ToLocal(result);
3604}
3605
3606
3607bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3608 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3609 if (this->IsExternal()) return false; // Already an external string.
3610 ENTER_V8;
3611 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003612 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003613 bool result = obj->MakeExternal(resource);
3614 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003615 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003616 }
3617 return result;
3618}
3619
3620
3621Local<String> v8::String::NewExternal(
3622 v8::String::ExternalAsciiStringResource* resource) {
3623 EnsureInitialized("v8::String::NewExternal()");
3624 LOG_API("String::NewExternal");
3625 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003626 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003627 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003628 return Utils::ToLocal(result);
3629}
3630
3631
3632bool v8::String::MakeExternal(
3633 v8::String::ExternalAsciiStringResource* resource) {
3634 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3635 if (this->IsExternal()) return false; // Already an external string.
3636 ENTER_V8;
3637 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003638 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003639 bool result = obj->MakeExternal(resource);
3640 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003641 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003642 }
3643 return result;
3644}
3645
3646
3647bool v8::String::CanMakeExternal() {
3648 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3649 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003650 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003651 int size = obj->Size(); // Byte size of the original string.
3652 if (size < i::ExternalString::kSize)
3653 return false;
3654 i::StringShape shape(*obj);
3655 return !shape.IsExternal();
3656}
3657
3658
3659Local<v8::Object> v8::Object::New() {
3660 EnsureInitialized("v8::Object::New()");
3661 LOG_API("Object::New");
3662 ENTER_V8;
3663 i::Handle<i::JSObject> obj =
3664 i::Factory::NewJSObject(i::Top::object_function());
3665 return Utils::ToLocal(obj);
3666}
3667
3668
3669Local<v8::Value> v8::Date::New(double time) {
3670 EnsureInitialized("v8::Date::New()");
3671 LOG_API("Date::New");
Steve Blockd0582a62009-12-15 09:54:21 +00003672 if (isnan(time)) {
3673 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3674 time = i::OS::nan_value();
3675 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003676 ENTER_V8;
3677 EXCEPTION_PREAMBLE();
3678 i::Handle<i::Object> obj =
3679 i::Execution::NewDate(time, &has_pending_exception);
3680 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3681 return Utils::ToLocal(obj);
3682}
3683
3684
3685double v8::Date::NumberValue() const {
3686 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3687 LOG_API("Date::NumberValue");
3688 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3689 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3690 return jsvalue->value()->Number();
3691}
3692
3693
3694Local<v8::Array> v8::Array::New(int length) {
3695 EnsureInitialized("v8::Array::New()");
3696 LOG_API("Array::New");
3697 ENTER_V8;
3698 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3699 return Utils::ToLocal(obj);
3700}
3701
3702
3703uint32_t v8::Array::Length() const {
3704 if (IsDeadCheck("v8::Array::Length()")) return 0;
3705 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3706 i::Object* length = obj->length();
3707 if (length->IsSmi()) {
3708 return i::Smi::cast(length)->value();
3709 } else {
3710 return static_cast<uint32_t>(length->Number());
3711 }
3712}
3713
3714
3715Local<Object> Array::CloneElementAt(uint32_t index) {
3716 ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3717 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3718 if (!self->HasFastElements()) {
3719 return Local<Object>();
3720 }
3721 i::FixedArray* elms = i::FixedArray::cast(self->elements());
3722 i::Object* paragon = elms->get(index);
3723 if (!paragon->IsJSObject()) {
3724 return Local<Object>();
3725 }
3726 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3727 EXCEPTION_PREAMBLE();
Steve Block6ded16b2010-05-10 14:33:55 +01003728 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003729 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3730 has_pending_exception = result.is_null();
3731 EXCEPTION_BAILOUT_CHECK(Local<Object>());
3732 return Utils::ToLocal(result);
3733}
3734
3735
3736Local<String> v8::String::NewSymbol(const char* data, int length) {
3737 EnsureInitialized("v8::String::NewSymbol()");
3738 LOG_API("String::NewSymbol(char)");
3739 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003740 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003741 i::Handle<i::String> result =
3742 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3743 return Utils::ToLocal(result);
3744}
3745
3746
3747Local<Number> v8::Number::New(double value) {
3748 EnsureInitialized("v8::Number::New()");
Steve Blockd0582a62009-12-15 09:54:21 +00003749 if (isnan(value)) {
3750 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3751 value = i::OS::nan_value();
3752 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003753 ENTER_V8;
3754 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3755 return Utils::NumberToLocal(result);
3756}
3757
3758
3759Local<Integer> v8::Integer::New(int32_t value) {
3760 EnsureInitialized("v8::Integer::New()");
3761 if (i::Smi::IsValid(value)) {
3762 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3763 }
3764 ENTER_V8;
3765 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3766 return Utils::IntegerToLocal(result);
3767}
3768
3769
Steve Block3ce2e202009-11-05 08:53:23 +00003770Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
3771 bool fits_into_int32_t = (value & (1 << 31)) == 0;
3772 if (fits_into_int32_t) {
3773 return Integer::New(static_cast<int32_t>(value));
3774 }
3775 ENTER_V8;
3776 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3777 return Utils::IntegerToLocal(result);
3778}
3779
3780
Steve Blocka7e24c12009-10-30 11:49:00 +00003781void V8::IgnoreOutOfMemoryException() {
3782 thread_local.set_ignore_out_of_memory(true);
3783}
3784
3785
3786bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
3787 EnsureInitialized("v8::V8::AddMessageListener()");
3788 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
3789 ENTER_V8;
3790 HandleScope scope;
3791 NeanderArray listeners(i::Factory::message_listeners());
3792 NeanderObject obj(2);
3793 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
3794 obj.set(1, data.IsEmpty() ?
3795 i::Heap::undefined_value() :
3796 *Utils::OpenHandle(*data));
3797 listeners.add(obj.value());
3798 return true;
3799}
3800
3801
3802void V8::RemoveMessageListeners(MessageCallback that) {
3803 EnsureInitialized("v8::V8::RemoveMessageListener()");
3804 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
3805 ENTER_V8;
3806 HandleScope scope;
3807 NeanderArray listeners(i::Factory::message_listeners());
3808 for (int i = 0; i < listeners.length(); i++) {
3809 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
3810
3811 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
3812 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
3813 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
3814 listeners.set(i, i::Heap::undefined_value());
3815 }
3816 }
3817}
3818
3819
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003820void V8::SetCaptureStackTraceForUncaughtExceptions(
3821 bool capture,
3822 int frame_limit,
3823 StackTrace::StackTraceOptions options) {
3824 i::Top::SetCaptureStackTraceForUncaughtExceptions(
3825 capture,
3826 frame_limit,
3827 options);
3828}
3829
3830
Steve Blocka7e24c12009-10-30 11:49:00 +00003831void V8::SetCounterFunction(CounterLookupCallback callback) {
3832 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
3833 i::StatsTable::SetCounterFunction(callback);
3834}
3835
3836void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
3837 if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
3838 i::StatsTable::SetCreateHistogramFunction(callback);
3839}
3840
3841void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
3842 if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
3843 i::StatsTable::SetAddHistogramSampleFunction(callback);
3844}
3845
3846void V8::EnableSlidingStateWindow() {
3847 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
3848 i::Logger::EnableSlidingStateWindow();
3849}
3850
3851
3852void V8::SetFailedAccessCheckCallbackFunction(
3853 FailedAccessCheckCallback callback) {
3854 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
3855 i::Top::SetFailedAccessCheckCallback(callback);
3856}
3857
3858
3859void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
3860 if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
3861 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
3862 i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
3863}
3864
3865
3866int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
3867 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
3868 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
3869}
3870
3871
3872void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
3873 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
3874 i::Heap::SetGlobalGCPrologueCallback(callback);
3875}
3876
3877
3878void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
3879 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
3880 i::Heap::SetGlobalGCEpilogueCallback(callback);
3881}
3882
3883
Steve Block6ded16b2010-05-10 14:33:55 +01003884void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
3885 if (IsDeadCheck("v8::V8::AddGCPrologueCallback()")) return;
3886 i::Heap::AddGCPrologueCallback(callback, gc_type);
3887}
3888
3889
3890void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
3891 if (IsDeadCheck("v8::V8::RemoveGCPrologueCallback()")) return;
3892 i::Heap::RemoveGCPrologueCallback(callback);
3893}
3894
3895
3896void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
3897 if (IsDeadCheck("v8::V8::AddGCEpilogueCallback()")) return;
3898 i::Heap::AddGCEpilogueCallback(callback, gc_type);
3899}
3900
3901
3902void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
3903 if (IsDeadCheck("v8::V8::RemoveGCEpilogueCallback()")) return;
3904 i::Heap::RemoveGCEpilogueCallback(callback);
3905}
3906
3907
Steve Blocka7e24c12009-10-30 11:49:00 +00003908void V8::PauseProfiler() {
3909#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003910 PauseProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003911#endif
3912}
3913
3914
3915void V8::ResumeProfiler() {
3916#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003917 ResumeProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003918#endif
3919}
3920
3921
3922bool V8::IsProfilerPaused() {
3923#ifdef ENABLE_LOGGING_AND_PROFILING
3924 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
3925#else
3926 return true;
3927#endif
3928}
3929
3930
Andrei Popescu402d9372010-02-26 13:31:12 +00003931void V8::ResumeProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003932#ifdef ENABLE_LOGGING_AND_PROFILING
3933 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
3934 // Snapshot mode: resume modules, perform GC, then pause only
3935 // those modules which haven't been started prior to making a
3936 // snapshot.
3937
Steve Block6ded16b2010-05-10 14:33:55 +01003938 // Make a GC prior to taking a snapshot.
3939 i::Heap::CollectAllGarbage(false);
Steve Blocka7e24c12009-10-30 11:49:00 +00003940 // Reset snapshot flag and CPU module flags.
3941 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
3942 const int current_flags = i::Logger::GetActiveProfilerModules();
Andrei Popescu402d9372010-02-26 13:31:12 +00003943 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003944 i::Heap::CollectAllGarbage(false);
Andrei Popescu402d9372010-02-26 13:31:12 +00003945 i::Logger::PauseProfiler(~current_flags & flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003946 } else {
Andrei Popescu402d9372010-02-26 13:31:12 +00003947 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003948 }
3949#endif
3950}
3951
3952
Andrei Popescu402d9372010-02-26 13:31:12 +00003953void V8::PauseProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003954#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003955 i::Logger::PauseProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003956#endif
3957}
3958
3959
3960int V8::GetActiveProfilerModules() {
3961#ifdef ENABLE_LOGGING_AND_PROFILING
3962 return i::Logger::GetActiveProfilerModules();
3963#else
3964 return PROFILER_MODULE_NONE;
3965#endif
3966}
3967
3968
3969int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
3970#ifdef ENABLE_LOGGING_AND_PROFILING
Steve Block6ded16b2010-05-10 14:33:55 +01003971 ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
Steve Blocka7e24c12009-10-30 11:49:00 +00003972 return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
3973#endif
3974 return 0;
3975}
3976
3977
3978int V8::GetCurrentThreadId() {
3979 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3980 EnsureInitialized("V8::GetCurrentThreadId()");
3981 return i::Top::thread_id();
3982}
3983
3984
3985void V8::TerminateExecution(int thread_id) {
3986 if (!i::V8::IsRunning()) return;
3987 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3988 // If the thread_id identifies the current thread just terminate
3989 // execution right away. Otherwise, ask the thread manager to
3990 // terminate the thread with the given id if any.
3991 if (thread_id == i::Top::thread_id()) {
3992 i::StackGuard::TerminateExecution();
3993 } else {
3994 i::ThreadManager::TerminateExecution(thread_id);
3995 }
3996}
3997
3998
3999void V8::TerminateExecution() {
4000 if (!i::V8::IsRunning()) return;
4001 i::StackGuard::TerminateExecution();
4002}
4003
4004
Steve Block6ded16b2010-05-10 14:33:55 +01004005bool V8::IsExecutionTerminating() {
4006 if (!i::V8::IsRunning()) return false;
4007 if (i::Top::has_scheduled_exception()) {
4008 return i::Top::scheduled_exception() == i::Heap::termination_exception();
4009 }
4010 return false;
4011}
4012
4013
Steve Blocka7e24c12009-10-30 11:49:00 +00004014String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
4015 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
4016 if (obj.IsEmpty()) {
4017 str_ = NULL;
4018 length_ = 0;
4019 return;
4020 }
4021 ENTER_V8;
4022 HandleScope scope;
4023 TryCatch try_catch;
4024 Handle<String> str = obj->ToString();
4025 if (str.IsEmpty()) {
4026 str_ = NULL;
4027 length_ = 0;
4028 } else {
4029 length_ = str->Utf8Length();
4030 str_ = i::NewArray<char>(length_ + 1);
4031 str->WriteUtf8(str_);
4032 }
4033}
4034
4035
4036String::Utf8Value::~Utf8Value() {
4037 i::DeleteArray(str_);
4038}
4039
4040
4041String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
4042 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
4043 if (obj.IsEmpty()) {
4044 str_ = NULL;
4045 length_ = 0;
4046 return;
4047 }
4048 ENTER_V8;
4049 HandleScope scope;
4050 TryCatch try_catch;
4051 Handle<String> str = obj->ToString();
4052 if (str.IsEmpty()) {
4053 str_ = NULL;
4054 length_ = 0;
4055 } else {
4056 length_ = str->Length();
4057 str_ = i::NewArray<char>(length_ + 1);
4058 str->WriteAscii(str_);
4059 }
4060}
4061
4062
4063String::AsciiValue::~AsciiValue() {
4064 i::DeleteArray(str_);
4065}
4066
4067
4068String::Value::Value(v8::Handle<v8::Value> obj) {
4069 EnsureInitialized("v8::String::Value::Value()");
4070 if (obj.IsEmpty()) {
4071 str_ = NULL;
4072 length_ = 0;
4073 return;
4074 }
4075 ENTER_V8;
4076 HandleScope scope;
4077 TryCatch try_catch;
4078 Handle<String> str = obj->ToString();
4079 if (str.IsEmpty()) {
4080 str_ = NULL;
4081 length_ = 0;
4082 } else {
4083 length_ = str->Length();
4084 str_ = i::NewArray<uint16_t>(length_ + 1);
4085 str->Write(str_);
4086 }
4087}
4088
4089
4090String::Value::~Value() {
4091 i::DeleteArray(str_);
4092}
4093
4094Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
4095 LOG_API("RangeError");
4096 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
4097 ENTER_V8;
4098 i::Object* error;
4099 {
4100 HandleScope scope;
4101 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4102 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
4103 error = *result;
4104 }
4105 i::Handle<i::Object> result(error);
4106 return Utils::ToLocal(result);
4107}
4108
4109Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
4110 LOG_API("ReferenceError");
4111 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
4112 ENTER_V8;
4113 i::Object* error;
4114 {
4115 HandleScope scope;
4116 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4117 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
4118 error = *result;
4119 }
4120 i::Handle<i::Object> result(error);
4121 return Utils::ToLocal(result);
4122}
4123
4124Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
4125 LOG_API("SyntaxError");
4126 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
4127 ENTER_V8;
4128 i::Object* error;
4129 {
4130 HandleScope scope;
4131 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4132 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
4133 error = *result;
4134 }
4135 i::Handle<i::Object> result(error);
4136 return Utils::ToLocal(result);
4137}
4138
4139Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
4140 LOG_API("TypeError");
4141 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
4142 ENTER_V8;
4143 i::Object* error;
4144 {
4145 HandleScope scope;
4146 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4147 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
4148 error = *result;
4149 }
4150 i::Handle<i::Object> result(error);
4151 return Utils::ToLocal(result);
4152}
4153
4154Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
4155 LOG_API("Error");
4156 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
4157 ENTER_V8;
4158 i::Object* error;
4159 {
4160 HandleScope scope;
4161 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4162 i::Handle<i::Object> result = i::Factory::NewError(message);
4163 error = *result;
4164 }
4165 i::Handle<i::Object> result(error);
4166 return Utils::ToLocal(result);
4167}
4168
4169
4170// --- D e b u g S u p p o r t ---
4171
4172#ifdef ENABLE_DEBUGGER_SUPPORT
Leon Clarkef7060e22010-06-03 12:02:55 +01004173
4174static v8::Debug::EventCallback event_callback = NULL;
4175
4176static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) {
4177 if (event_callback) {
4178 event_callback(event_details.GetEvent(),
4179 event_details.GetExecutionState(),
4180 event_details.GetEventData(),
4181 event_details.GetCallbackData());
4182 }
4183}
4184
4185
Steve Blocka7e24c12009-10-30 11:49:00 +00004186bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
4187 EnsureInitialized("v8::Debug::SetDebugEventListener()");
4188 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4189 ENTER_V8;
Leon Clarkef7060e22010-06-03 12:02:55 +01004190
4191 event_callback = that;
4192
4193 HandleScope scope;
4194 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4195 if (that != NULL) {
4196 proxy = i::Factory::NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
4197 }
4198 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4199 return true;
4200}
4201
4202
4203bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
4204 EnsureInitialized("v8::Debug::SetDebugEventListener2()");
4205 ON_BAILOUT("v8::Debug::SetDebugEventListener2()", return false);
4206 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004207 HandleScope scope;
4208 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4209 if (that != NULL) {
4210 proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
4211 }
4212 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4213 return true;
4214}
4215
4216
4217bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
4218 Handle<Value> data) {
4219 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4220 ENTER_V8;
4221 i::Debugger::SetEventListener(Utils::OpenHandle(*that),
4222 Utils::OpenHandle(*data));
4223 return true;
4224}
4225
4226
4227void Debug::DebugBreak() {
4228 if (!i::V8::IsRunning()) return;
4229 i::StackGuard::DebugBreak();
4230}
4231
4232
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004233void Debug::DebugBreakForCommand(ClientData* data) {
4234 if (!i::V8::IsRunning()) return;
4235 i::Debugger::EnqueueDebugCommand(data);
4236}
4237
4238
Steve Blocka7e24c12009-10-30 11:49:00 +00004239static v8::Debug::MessageHandler message_handler = NULL;
4240
4241static void MessageHandlerWrapper(const v8::Debug::Message& message) {
4242 if (message_handler) {
4243 v8::String::Value json(message.GetJSON());
4244 message_handler(*json, json.length(), message.GetClientData());
4245 }
4246}
4247
4248
4249void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
4250 bool message_handler_thread) {
4251 EnsureInitialized("v8::Debug::SetMessageHandler");
4252 ENTER_V8;
4253 // Message handler thread not supported any more. Parameter temporally left in
4254 // the API for client compatability reasons.
4255 CHECK(!message_handler_thread);
4256
4257 // TODO(sgjesse) support the old message handler API through a simple wrapper.
4258 message_handler = handler;
4259 if (message_handler != NULL) {
4260 i::Debugger::SetMessageHandler(MessageHandlerWrapper);
4261 } else {
4262 i::Debugger::SetMessageHandler(NULL);
4263 }
4264}
4265
4266
4267void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
4268 EnsureInitialized("v8::Debug::SetMessageHandler");
4269 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004270 i::Debugger::SetMessageHandler(handler);
4271}
4272
4273
4274void Debug::SendCommand(const uint16_t* command, int length,
4275 ClientData* client_data) {
4276 if (!i::V8::IsRunning()) return;
4277 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
4278 client_data);
4279}
4280
4281
4282void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
4283 int period) {
4284 EnsureInitialized("v8::Debug::SetHostDispatchHandler");
4285 ENTER_V8;
4286 i::Debugger::SetHostDispatchHandler(handler, period);
4287}
4288
4289
Steve Blockd0582a62009-12-15 09:54:21 +00004290void Debug::SetDebugMessageDispatchHandler(
Leon Clarkee46be812010-01-19 14:06:41 +00004291 DebugMessageDispatchHandler handler, bool provide_locker) {
Steve Blockd0582a62009-12-15 09:54:21 +00004292 EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
4293 ENTER_V8;
Leon Clarkee46be812010-01-19 14:06:41 +00004294 i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
Steve Blockd0582a62009-12-15 09:54:21 +00004295}
4296
4297
Steve Blocka7e24c12009-10-30 11:49:00 +00004298Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
4299 v8::Handle<v8::Value> data) {
4300 if (!i::V8::IsRunning()) return Local<Value>();
4301 ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
4302 ENTER_V8;
4303 i::Handle<i::Object> result;
4304 EXCEPTION_PREAMBLE();
4305 if (data.IsEmpty()) {
4306 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4307 i::Factory::undefined_value(),
4308 &has_pending_exception);
4309 } else {
4310 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4311 Utils::OpenHandle(*data),
4312 &has_pending_exception);
4313 }
4314 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4315 return Utils::ToLocal(result);
4316}
4317
4318
4319Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
4320 if (!i::V8::IsRunning()) return Local<Value>();
4321 ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
4322 ENTER_V8;
4323 v8::HandleScope scope;
4324 i::Debug::Load();
4325 i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
4326 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
4327 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
4328 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
4329 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
4330 const int kArgc = 1;
4331 v8::Handle<v8::Value> argv[kArgc] = { obj };
4332 EXCEPTION_PREAMBLE();
4333 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
4334 kArgc,
4335 argv);
4336 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4337 return scope.Close(result);
4338}
4339
4340
Leon Clarkee46be812010-01-19 14:06:41 +00004341bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
4342 return i::Debugger::StartAgent(name, port, wait_for_connection);
Steve Blocka7e24c12009-10-30 11:49:00 +00004343}
Leon Clarkee46be812010-01-19 14:06:41 +00004344
4345void Debug::ProcessDebugMessages() {
4346 i::Execution::ProcessDebugMesssages(true);
4347}
4348
Steve Block6ded16b2010-05-10 14:33:55 +01004349Local<Context> Debug::GetDebugContext() {
4350 EnsureInitialized("v8::Debug::GetDebugContext()");
4351 ENTER_V8;
4352 return Utils::ToLocal(i::Debugger::GetDebugContext());
4353}
4354
Steve Blocka7e24c12009-10-30 11:49:00 +00004355#endif // ENABLE_DEBUGGER_SUPPORT
4356
Steve Block6ded16b2010-05-10 14:33:55 +01004357
4358#ifdef ENABLE_LOGGING_AND_PROFILING
4359
4360Handle<String> CpuProfileNode::GetFunctionName() const {
4361 IsDeadCheck("v8::CpuProfileNode::GetFunctionName");
4362 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4363 const i::CodeEntry* entry = node->entry();
4364 if (!entry->has_name_prefix()) {
4365 return Handle<String>(ToApi<String>(
4366 i::Factory::LookupAsciiSymbol(entry->name())));
4367 } else {
4368 return Handle<String>(ToApi<String>(i::Factory::NewConsString(
4369 i::Factory::LookupAsciiSymbol(entry->name_prefix()),
4370 i::Factory::LookupAsciiSymbol(entry->name()))));
4371 }
4372}
4373
4374
4375Handle<String> CpuProfileNode::GetScriptResourceName() const {
4376 IsDeadCheck("v8::CpuProfileNode::GetScriptResourceName");
4377 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4378 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4379 node->entry()->resource_name())));
4380}
4381
4382
4383int CpuProfileNode::GetLineNumber() const {
4384 IsDeadCheck("v8::CpuProfileNode::GetLineNumber");
4385 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
4386}
4387
4388
4389double CpuProfileNode::GetTotalTime() const {
4390 IsDeadCheck("v8::CpuProfileNode::GetTotalTime");
4391 return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis();
4392}
4393
4394
4395double CpuProfileNode::GetSelfTime() const {
4396 IsDeadCheck("v8::CpuProfileNode::GetSelfTime");
4397 return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis();
4398}
4399
4400
4401double CpuProfileNode::GetTotalSamplesCount() const {
4402 IsDeadCheck("v8::CpuProfileNode::GetTotalSamplesCount");
4403 return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
4404}
4405
4406
4407double CpuProfileNode::GetSelfSamplesCount() const {
4408 IsDeadCheck("v8::CpuProfileNode::GetSelfSamplesCount");
4409 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
4410}
4411
4412
4413unsigned CpuProfileNode::GetCallUid() const {
4414 IsDeadCheck("v8::CpuProfileNode::GetCallUid");
4415 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->call_uid();
4416}
4417
4418
4419int CpuProfileNode::GetChildrenCount() const {
4420 IsDeadCheck("v8::CpuProfileNode::GetChildrenCount");
4421 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
4422}
4423
4424
4425const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
4426 IsDeadCheck("v8::CpuProfileNode::GetChild");
4427 const i::ProfileNode* child =
4428 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
4429 return reinterpret_cast<const CpuProfileNode*>(child);
4430}
4431
4432
4433unsigned CpuProfile::GetUid() const {
4434 IsDeadCheck("v8::CpuProfile::GetUid");
4435 return reinterpret_cast<const i::CpuProfile*>(this)->uid();
4436}
4437
4438
4439Handle<String> CpuProfile::GetTitle() const {
4440 IsDeadCheck("v8::CpuProfile::GetTitle");
4441 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4442 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4443 profile->title())));
4444}
4445
4446
4447const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
4448 IsDeadCheck("v8::CpuProfile::GetBottomUpRoot");
4449 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4450 return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
4451}
4452
4453
4454const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
4455 IsDeadCheck("v8::CpuProfile::GetTopDownRoot");
4456 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4457 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
4458}
4459
4460
4461int CpuProfiler::GetProfilesCount() {
4462 IsDeadCheck("v8::CpuProfiler::GetProfilesCount");
4463 return i::CpuProfiler::GetProfilesCount();
4464}
4465
4466
Leon Clarkef7060e22010-06-03 12:02:55 +01004467const CpuProfile* CpuProfiler::GetProfile(int index,
4468 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004469 IsDeadCheck("v8::CpuProfiler::GetProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004470 return reinterpret_cast<const CpuProfile*>(
4471 i::CpuProfiler::GetProfile(
4472 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4473 index));
Steve Block6ded16b2010-05-10 14:33:55 +01004474}
4475
4476
Leon Clarkef7060e22010-06-03 12:02:55 +01004477const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
4478 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004479 IsDeadCheck("v8::CpuProfiler::FindProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004480 return reinterpret_cast<const CpuProfile*>(
4481 i::CpuProfiler::FindProfile(
4482 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4483 uid));
Steve Block6ded16b2010-05-10 14:33:55 +01004484}
4485
4486
4487void CpuProfiler::StartProfiling(Handle<String> title) {
4488 IsDeadCheck("v8::CpuProfiler::StartProfiling");
4489 i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
4490}
4491
4492
Leon Clarkef7060e22010-06-03 12:02:55 +01004493const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
4494 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004495 IsDeadCheck("v8::CpuProfiler::StopProfiling");
4496 return reinterpret_cast<const CpuProfile*>(
Leon Clarkef7060e22010-06-03 12:02:55 +01004497 i::CpuProfiler::StopProfiling(
4498 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4499 *Utils::OpenHandle(*title)));
Steve Block6ded16b2010-05-10 14:33:55 +01004500}
4501
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004502
Iain Merrick75681382010-08-19 15:07:18 +01004503static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
4504 return const_cast<i::HeapGraphEdge*>(
4505 reinterpret_cast<const i::HeapGraphEdge*>(edge));
4506}
4507
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004508HeapGraphEdge::Type HeapGraphEdge::GetType() const {
4509 IsDeadCheck("v8::HeapGraphEdge::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004510 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004511}
4512
4513
4514Handle<Value> HeapGraphEdge::GetName() const {
4515 IsDeadCheck("v8::HeapGraphEdge::GetName");
Iain Merrick75681382010-08-19 15:07:18 +01004516 i::HeapGraphEdge* edge = ToInternal(this);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004517 switch (edge->type()) {
Iain Merrick75681382010-08-19 15:07:18 +01004518 case i::HeapGraphEdge::kContextVariable:
4519 case i::HeapGraphEdge::kInternal:
4520 case i::HeapGraphEdge::kProperty:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004521 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4522 edge->name())));
Iain Merrick75681382010-08-19 15:07:18 +01004523 case i::HeapGraphEdge::kElement:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004524 return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt(
4525 edge->index())));
4526 default: UNREACHABLE();
4527 }
4528 return ImplementationUtilities::Undefined();
4529}
4530
4531
4532const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
4533 IsDeadCheck("v8::HeapGraphEdge::GetFromNode");
Iain Merrick75681382010-08-19 15:07:18 +01004534 const i::HeapEntry* from = ToInternal(this)->From();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004535 return reinterpret_cast<const HeapGraphNode*>(from);
4536}
4537
4538
4539const HeapGraphNode* HeapGraphEdge::GetToNode() const {
4540 IsDeadCheck("v8::HeapGraphEdge::GetToNode");
Iain Merrick75681382010-08-19 15:07:18 +01004541 const i::HeapEntry* to = ToInternal(this)->to();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004542 return reinterpret_cast<const HeapGraphNode*>(to);
4543}
4544
4545
Iain Merrick75681382010-08-19 15:07:18 +01004546static i::HeapGraphPath* ToInternal(const HeapGraphPath* path) {
4547 return const_cast<i::HeapGraphPath*>(
4548 reinterpret_cast<const i::HeapGraphPath*>(path));
4549}
4550
4551
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004552int HeapGraphPath::GetEdgesCount() const {
Iain Merrick75681382010-08-19 15:07:18 +01004553 return ToInternal(this)->path()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004554}
4555
4556
4557const HeapGraphEdge* HeapGraphPath::GetEdge(int index) const {
4558 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004559 ToInternal(this)->path()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004560}
4561
4562
4563const HeapGraphNode* HeapGraphPath::GetFromNode() const {
4564 return GetEdgesCount() > 0 ? GetEdge(0)->GetFromNode() : NULL;
4565}
4566
4567
4568const HeapGraphNode* HeapGraphPath::GetToNode() const {
4569 const int count = GetEdgesCount();
4570 return count > 0 ? GetEdge(count - 1)->GetToNode() : NULL;
4571}
4572
4573
Iain Merrick75681382010-08-19 15:07:18 +01004574static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
4575 return const_cast<i::HeapEntry*>(
4576 reinterpret_cast<const i::HeapEntry*>(entry));
4577}
4578
4579
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004580HeapGraphNode::Type HeapGraphNode::GetType() const {
4581 IsDeadCheck("v8::HeapGraphNode::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004582 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004583}
4584
4585
4586Handle<String> HeapGraphNode::GetName() const {
4587 IsDeadCheck("v8::HeapGraphNode::GetName");
4588 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004589 ToInternal(this)->name())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004590}
4591
4592
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004593uint64_t HeapGraphNode::GetId() const {
4594 IsDeadCheck("v8::HeapGraphNode::GetId");
Iain Merrick75681382010-08-19 15:07:18 +01004595 return ToInternal(this)->id();
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004596}
4597
4598
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004599int HeapGraphNode::GetSelfSize() const {
4600 IsDeadCheck("v8::HeapGraphNode::GetSelfSize");
Iain Merrick75681382010-08-19 15:07:18 +01004601 return ToInternal(this)->self_size();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004602}
4603
4604
Iain Merrick75681382010-08-19 15:07:18 +01004605int HeapGraphNode::GetReachableSize() const {
4606 IsDeadCheck("v8::HeapSnapshot::GetReachableSize");
4607 return ToInternal(this)->ReachableSize();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004608}
4609
4610
Iain Merrick75681382010-08-19 15:07:18 +01004611int HeapGraphNode::GetRetainedSize() const {
4612 IsDeadCheck("v8::HeapSnapshot::GetRetainedSize");
4613 return ToInternal(this)->RetainedSize();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004614}
4615
4616
4617int HeapGraphNode::GetChildrenCount() const {
4618 IsDeadCheck("v8::HeapSnapshot::GetChildrenCount");
Iain Merrick75681382010-08-19 15:07:18 +01004619 return ToInternal(this)->children().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004620}
4621
4622
4623const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
4624 IsDeadCheck("v8::HeapSnapshot::GetChild");
4625 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004626 &ToInternal(this)->children()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004627}
4628
4629
4630int HeapGraphNode::GetRetainersCount() const {
4631 IsDeadCheck("v8::HeapSnapshot::GetRetainersCount");
Iain Merrick75681382010-08-19 15:07:18 +01004632 return ToInternal(this)->retainers().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004633}
4634
4635
4636const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const {
4637 IsDeadCheck("v8::HeapSnapshot::GetRetainer");
4638 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004639 ToInternal(this)->retainers()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004640}
4641
4642
4643int HeapGraphNode::GetRetainingPathsCount() const {
4644 IsDeadCheck("v8::HeapSnapshot::GetRetainingPathsCount");
Iain Merrick75681382010-08-19 15:07:18 +01004645 return ToInternal(this)->GetRetainingPaths()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004646}
4647
4648
4649const HeapGraphPath* HeapGraphNode::GetRetainingPath(int index) const {
4650 IsDeadCheck("v8::HeapSnapshot::GetRetainingPath");
4651 return reinterpret_cast<const HeapGraphPath*>(
Iain Merrick75681382010-08-19 15:07:18 +01004652 ToInternal(this)->GetRetainingPaths()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004653}
4654
4655
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004656const HeapGraphNode* HeapSnapshotsDiff::GetAdditionsRoot() const {
4657 IsDeadCheck("v8::HeapSnapshotsDiff::GetAdditionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004658 i::HeapSnapshotsDiff* diff =
4659 const_cast<i::HeapSnapshotsDiff*>(
4660 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004661 return reinterpret_cast<const HeapGraphNode*>(diff->additions_root());
4662}
4663
4664
4665const HeapGraphNode* HeapSnapshotsDiff::GetDeletionsRoot() const {
4666 IsDeadCheck("v8::HeapSnapshotsDiff::GetDeletionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004667 i::HeapSnapshotsDiff* diff =
4668 const_cast<i::HeapSnapshotsDiff*>(
4669 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004670 return reinterpret_cast<const HeapGraphNode*>(diff->deletions_root());
4671}
4672
4673
Iain Merrick75681382010-08-19 15:07:18 +01004674static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
4675 return const_cast<i::HeapSnapshot*>(
4676 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
4677}
4678
4679
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004680unsigned HeapSnapshot::GetUid() const {
4681 IsDeadCheck("v8::HeapSnapshot::GetUid");
Iain Merrick75681382010-08-19 15:07:18 +01004682 return ToInternal(this)->uid();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004683}
4684
4685
4686Handle<String> HeapSnapshot::GetTitle() const {
4687 IsDeadCheck("v8::HeapSnapshot::GetTitle");
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004688 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004689 ToInternal(this)->title())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004690}
4691
4692
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004693const HeapGraphNode* HeapSnapshot::GetRoot() const {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004694 IsDeadCheck("v8::HeapSnapshot::GetHead");
Iain Merrick75681382010-08-19 15:07:18 +01004695 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004696}
4697
4698
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004699const HeapSnapshotsDiff* HeapSnapshot::CompareWith(
4700 const HeapSnapshot* snapshot) const {
4701 IsDeadCheck("v8::HeapSnapshot::CompareWith");
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004702 return reinterpret_cast<const HeapSnapshotsDiff*>(
Iain Merrick75681382010-08-19 15:07:18 +01004703 ToInternal(this)->CompareWith(ToInternal(snapshot)));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004704}
4705
4706
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004707int HeapProfiler::GetSnapshotsCount() {
4708 IsDeadCheck("v8::HeapProfiler::GetSnapshotsCount");
4709 return i::HeapProfiler::GetSnapshotsCount();
4710}
4711
4712
4713const HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
4714 IsDeadCheck("v8::HeapProfiler::GetSnapshot");
4715 return reinterpret_cast<const HeapSnapshot*>(
4716 i::HeapProfiler::GetSnapshot(index));
4717}
4718
4719
4720const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
4721 IsDeadCheck("v8::HeapProfiler::FindSnapshot");
4722 return reinterpret_cast<const HeapSnapshot*>(
4723 i::HeapProfiler::FindSnapshot(uid));
4724}
4725
4726
4727const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title) {
4728 IsDeadCheck("v8::HeapProfiler::TakeSnapshot");
4729 return reinterpret_cast<const HeapSnapshot*>(
4730 i::HeapProfiler::TakeSnapshot(*Utils::OpenHandle(*title)));
4731}
4732
Steve Block6ded16b2010-05-10 14:33:55 +01004733#endif // ENABLE_LOGGING_AND_PROFILING
4734
4735
Steve Blocka7e24c12009-10-30 11:49:00 +00004736namespace internal {
4737
4738
4739HandleScopeImplementer* HandleScopeImplementer::instance() {
4740 return &thread_local;
4741}
4742
4743
4744void HandleScopeImplementer::FreeThreadResources() {
4745 thread_local.Free();
4746}
4747
4748
4749char* HandleScopeImplementer::ArchiveThread(char* storage) {
4750 return thread_local.ArchiveThreadHelper(storage);
4751}
4752
4753
4754char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
4755 v8::ImplementationUtilities::HandleScopeData* current =
4756 v8::ImplementationUtilities::CurrentHandleScope();
4757 handle_scope_data_ = *current;
4758 memcpy(storage, this, sizeof(*this));
4759
4760 ResetAfterArchive();
4761 current->Initialize();
4762
4763 return storage + ArchiveSpacePerThread();
4764}
4765
4766
4767int HandleScopeImplementer::ArchiveSpacePerThread() {
4768 return sizeof(thread_local);
4769}
4770
4771
4772char* HandleScopeImplementer::RestoreThread(char* storage) {
4773 return thread_local.RestoreThreadHelper(storage);
4774}
4775
4776
4777char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
4778 memcpy(this, storage, sizeof(*this));
4779 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
4780 return storage + ArchiveSpacePerThread();
4781}
4782
4783
4784void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
4785 // Iterate over all handles in the blocks except for the last.
4786 for (int i = blocks()->length() - 2; i >= 0; --i) {
4787 Object** block = blocks()->at(i);
4788 v->VisitPointers(block, &block[kHandleBlockSize]);
4789 }
4790
4791 // Iterate over live handles in the last block (if any).
4792 if (!blocks()->is_empty()) {
4793 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
4794 }
4795
4796 if (!saved_contexts_.is_empty()) {
4797 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
4798 v->VisitPointers(start, start + saved_contexts_.length());
4799 }
4800}
4801
4802
4803void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
4804 v8::ImplementationUtilities::HandleScopeData* current =
4805 v8::ImplementationUtilities::CurrentHandleScope();
4806 thread_local.handle_scope_data_ = *current;
4807 thread_local.IterateThis(v);
4808}
4809
4810
4811char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
4812 HandleScopeImplementer* thread_local =
4813 reinterpret_cast<HandleScopeImplementer*>(storage);
4814 thread_local->IterateThis(v);
4815 return storage + ArchiveSpacePerThread();
4816}
4817
4818} } // namespace v8::internal