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