blob: 0f64dd45ec58a165ee3856c5df5ad04e7831e899 [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
1441static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1442 i::Handle<i::Object> recv,
1443 int argc,
1444 i::Object** argv[],
1445 bool* has_pending_exception) {
1446 i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
1447 i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
1448 i::Handle<i::JSFunction> fun =
1449 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1450 i::Handle<i::Object> value =
1451 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1452 return value;
1453}
1454
1455
1456static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1457 i::Handle<i::Object> data,
1458 bool* has_pending_exception) {
1459 i::Object** argv[1] = { data.location() };
1460 return CallV8HeapFunction(name,
1461 i::Top::builtins(),
1462 1,
1463 argv,
1464 has_pending_exception);
1465}
1466
1467
1468int Message::GetLineNumber() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001469 ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001470 ENTER_V8;
1471 HandleScope scope;
1472 EXCEPTION_PREAMBLE();
1473 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1474 Utils::OpenHandle(this),
1475 &has_pending_exception);
1476 EXCEPTION_BAILOUT_CHECK(0);
1477 return static_cast<int>(result->Number());
1478}
1479
1480
1481int Message::GetStartPosition() const {
1482 if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1483 ENTER_V8;
1484 HandleScope scope;
1485
1486 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1487 return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1488}
1489
1490
1491int Message::GetEndPosition() const {
1492 if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1493 ENTER_V8;
1494 HandleScope scope;
1495 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1496 return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1497}
1498
1499
1500int Message::GetStartColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001501 if (IsDeadCheck("v8::Message::GetStartColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001502 ENTER_V8;
1503 HandleScope scope;
1504 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1505 EXCEPTION_PREAMBLE();
1506 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1507 "GetPositionInLine",
1508 data_obj,
1509 &has_pending_exception);
1510 EXCEPTION_BAILOUT_CHECK(0);
1511 return static_cast<int>(start_col_obj->Number());
1512}
1513
1514
1515int Message::GetEndColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001516 if (IsDeadCheck("v8::Message::GetEndColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001517 ENTER_V8;
1518 HandleScope scope;
1519 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1520 EXCEPTION_PREAMBLE();
1521 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1522 "GetPositionInLine",
1523 data_obj,
1524 &has_pending_exception);
1525 EXCEPTION_BAILOUT_CHECK(0);
1526 int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1527 int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1528 return static_cast<int>(start_col_obj->Number()) + (end - start);
1529}
1530
1531
1532Local<String> Message::GetSourceLine() const {
1533 ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
1534 ENTER_V8;
1535 HandleScope scope;
1536 EXCEPTION_PREAMBLE();
1537 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1538 Utils::OpenHandle(this),
1539 &has_pending_exception);
1540 EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1541 if (result->IsString()) {
1542 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1543 } else {
1544 return Local<String>();
1545 }
1546}
1547
1548
1549void Message::PrintCurrentStackTrace(FILE* out) {
1550 if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1551 ENTER_V8;
1552 i::Top::PrintCurrentStackTrace(out);
1553}
1554
1555
Kristian Monsen25f61362010-05-21 11:50:48 +01001556// --- S t a c k T r a c e ---
1557
1558Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
1559 if (IsDeadCheck("v8::StackTrace::GetFrame()")) return Local<StackFrame>();
1560 ENTER_V8;
1561 HandleScope scope;
1562 i::Handle<i::JSArray> self = Utils::OpenHandle(this);
1563 i::Handle<i::JSObject> obj(i::JSObject::cast(self->GetElement(index)));
1564 return scope.Close(Utils::StackFrameToLocal(obj));
1565}
1566
1567
1568int StackTrace::GetFrameCount() const {
1569 if (IsDeadCheck("v8::StackTrace::GetFrameCount()")) return -1;
1570 ENTER_V8;
1571 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
1572}
1573
1574
1575Local<Array> StackTrace::AsArray() {
1576 if (IsDeadCheck("v8::StackTrace::AsArray()")) Local<Array>();
1577 ENTER_V8;
1578 return Utils::ToLocal(Utils::OpenHandle(this));
1579}
1580
1581
1582Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
1583 StackTraceOptions options) {
1584 if (IsDeadCheck("v8::StackTrace::CurrentStackTrace()")) Local<StackTrace>();
1585 ENTER_V8;
1586 return i::Top::CaptureCurrentStackTrace(frame_limit, options);
1587}
1588
1589
1590// --- S t a c k F r a m e ---
1591
1592int StackFrame::GetLineNumber() const {
1593 if (IsDeadCheck("v8::StackFrame::GetLineNumber()")) {
1594 return Message::kNoLineNumberInfo;
1595 }
1596 ENTER_V8;
1597 i::HandleScope scope;
1598 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1599 i::Handle<i::Object> line = GetProperty(self, "lineNumber");
1600 if (!line->IsSmi()) {
1601 return Message::kNoLineNumberInfo;
1602 }
1603 return i::Smi::cast(*line)->value();
1604}
1605
1606
1607int StackFrame::GetColumn() const {
1608 if (IsDeadCheck("v8::StackFrame::GetColumn()")) {
1609 return Message::kNoColumnInfo;
1610 }
1611 ENTER_V8;
1612 i::HandleScope scope;
1613 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1614 i::Handle<i::Object> column = GetProperty(self, "column");
1615 if (!column->IsSmi()) {
1616 return Message::kNoColumnInfo;
1617 }
1618 return i::Smi::cast(*column)->value();
1619}
1620
1621
1622Local<String> StackFrame::GetScriptName() const {
1623 if (IsDeadCheck("v8::StackFrame::GetScriptName()")) return Local<String>();
1624 ENTER_V8;
1625 HandleScope scope;
1626 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1627 i::Handle<i::Object> name = GetProperty(self, "scriptName");
1628 if (!name->IsString()) {
1629 return Local<String>();
1630 }
1631 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1632}
1633
1634
1635Local<String> StackFrame::GetFunctionName() const {
1636 if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
1637 ENTER_V8;
1638 HandleScope scope;
1639 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1640 i::Handle<i::Object> name = GetProperty(self, "functionName");
1641 if (!name->IsString()) {
1642 return Local<String>();
1643 }
1644 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1645}
1646
1647
1648bool StackFrame::IsEval() const {
1649 if (IsDeadCheck("v8::StackFrame::IsEval()")) return false;
1650 ENTER_V8;
1651 i::HandleScope scope;
1652 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1653 i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
1654 return is_eval->IsTrue();
1655}
1656
1657
1658bool StackFrame::IsConstructor() const {
1659 if (IsDeadCheck("v8::StackFrame::IsConstructor()")) return false;
1660 ENTER_V8;
1661 i::HandleScope scope;
1662 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1663 i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
1664 return is_constructor->IsTrue();
1665}
1666
1667
Steve Blocka7e24c12009-10-30 11:49:00 +00001668// --- D a t a ---
1669
1670bool Value::IsUndefined() const {
1671 if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1672 return Utils::OpenHandle(this)->IsUndefined();
1673}
1674
1675
1676bool Value::IsNull() const {
1677 if (IsDeadCheck("v8::Value::IsNull()")) return false;
1678 return Utils::OpenHandle(this)->IsNull();
1679}
1680
1681
1682bool Value::IsTrue() const {
1683 if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1684 return Utils::OpenHandle(this)->IsTrue();
1685}
1686
1687
1688bool Value::IsFalse() const {
1689 if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1690 return Utils::OpenHandle(this)->IsFalse();
1691}
1692
1693
1694bool Value::IsFunction() const {
1695 if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1696 return Utils::OpenHandle(this)->IsJSFunction();
1697}
1698
1699
1700bool Value::FullIsString() const {
1701 if (IsDeadCheck("v8::Value::IsString()")) return false;
1702 bool result = Utils::OpenHandle(this)->IsString();
1703 ASSERT_EQ(result, QuickIsString());
1704 return result;
1705}
1706
1707
1708bool Value::IsArray() const {
1709 if (IsDeadCheck("v8::Value::IsArray()")) return false;
1710 return Utils::OpenHandle(this)->IsJSArray();
1711}
1712
1713
1714bool Value::IsObject() const {
1715 if (IsDeadCheck("v8::Value::IsObject()")) return false;
1716 return Utils::OpenHandle(this)->IsJSObject();
1717}
1718
1719
1720bool Value::IsNumber() const {
1721 if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1722 return Utils::OpenHandle(this)->IsNumber();
1723}
1724
1725
1726bool Value::IsBoolean() const {
1727 if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1728 return Utils::OpenHandle(this)->IsBoolean();
1729}
1730
1731
1732bool Value::IsExternal() const {
1733 if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1734 return Utils::OpenHandle(this)->IsProxy();
1735}
1736
1737
1738bool Value::IsInt32() const {
1739 if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1740 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1741 if (obj->IsSmi()) return true;
1742 if (obj->IsNumber()) {
1743 double value = obj->Number();
1744 return i::FastI2D(i::FastD2I(value)) == value;
1745 }
1746 return false;
1747}
1748
1749
Steve Block6ded16b2010-05-10 14:33:55 +01001750bool Value::IsUint32() const {
1751 if (IsDeadCheck("v8::Value::IsUint32()")) return false;
1752 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1753 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
1754 if (obj->IsNumber()) {
1755 double value = obj->Number();
1756 return i::FastUI2D(i::FastD2UI(value)) == value;
1757 }
1758 return false;
1759}
1760
1761
Steve Blocka7e24c12009-10-30 11:49:00 +00001762bool Value::IsDate() const {
1763 if (IsDeadCheck("v8::Value::IsDate()")) return false;
1764 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1765 return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1766}
1767
1768
1769Local<String> Value::ToString() const {
1770 if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1771 LOG_API("ToString");
1772 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1773 i::Handle<i::Object> str;
1774 if (obj->IsString()) {
1775 str = obj;
1776 } else {
1777 ENTER_V8;
1778 EXCEPTION_PREAMBLE();
1779 str = i::Execution::ToString(obj, &has_pending_exception);
1780 EXCEPTION_BAILOUT_CHECK(Local<String>());
1781 }
1782 return Local<String>(ToApi<String>(str));
1783}
1784
1785
1786Local<String> Value::ToDetailString() const {
1787 if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1788 LOG_API("ToDetailString");
1789 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1790 i::Handle<i::Object> str;
1791 if (obj->IsString()) {
1792 str = obj;
1793 } else {
1794 ENTER_V8;
1795 EXCEPTION_PREAMBLE();
1796 str = i::Execution::ToDetailString(obj, &has_pending_exception);
1797 EXCEPTION_BAILOUT_CHECK(Local<String>());
1798 }
1799 return Local<String>(ToApi<String>(str));
1800}
1801
1802
1803Local<v8::Object> Value::ToObject() const {
1804 if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1805 LOG_API("ToObject");
1806 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1807 i::Handle<i::Object> val;
1808 if (obj->IsJSObject()) {
1809 val = obj;
1810 } else {
1811 ENTER_V8;
1812 EXCEPTION_PREAMBLE();
1813 val = i::Execution::ToObject(obj, &has_pending_exception);
1814 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1815 }
1816 return Local<v8::Object>(ToApi<Object>(val));
1817}
1818
1819
1820Local<Boolean> Value::ToBoolean() const {
1821 if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1822 LOG_API("ToBoolean");
1823 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1824 if (obj->IsBoolean()) {
1825 return Local<Boolean>(ToApi<Boolean>(obj));
1826 } else {
1827 ENTER_V8;
1828 i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1829 return Local<Boolean>(ToApi<Boolean>(val));
1830 }
1831}
1832
1833
1834Local<Number> Value::ToNumber() const {
1835 if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1836 LOG_API("ToNumber");
1837 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1838 i::Handle<i::Object> num;
1839 if (obj->IsNumber()) {
1840 num = obj;
1841 } else {
1842 ENTER_V8;
1843 EXCEPTION_PREAMBLE();
1844 num = i::Execution::ToNumber(obj, &has_pending_exception);
1845 EXCEPTION_BAILOUT_CHECK(Local<Number>());
1846 }
1847 return Local<Number>(ToApi<Number>(num));
1848}
1849
1850
1851Local<Integer> Value::ToInteger() const {
1852 if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1853 LOG_API("ToInteger");
1854 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1855 i::Handle<i::Object> num;
1856 if (obj->IsSmi()) {
1857 num = obj;
1858 } else {
1859 ENTER_V8;
1860 EXCEPTION_PREAMBLE();
1861 num = i::Execution::ToInteger(obj, &has_pending_exception);
1862 EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1863 }
1864 return Local<Integer>(ToApi<Integer>(num));
1865}
1866
1867
1868void External::CheckCast(v8::Value* that) {
1869 if (IsDeadCheck("v8::External::Cast()")) return;
1870 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1871 ApiCheck(obj->IsProxy(),
1872 "v8::External::Cast()",
1873 "Could not convert to external");
1874}
1875
1876
1877void v8::Object::CheckCast(Value* that) {
1878 if (IsDeadCheck("v8::Object::Cast()")) return;
1879 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1880 ApiCheck(obj->IsJSObject(),
1881 "v8::Object::Cast()",
1882 "Could not convert to object");
1883}
1884
1885
1886void v8::Function::CheckCast(Value* that) {
1887 if (IsDeadCheck("v8::Function::Cast()")) return;
1888 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1889 ApiCheck(obj->IsJSFunction(),
1890 "v8::Function::Cast()",
1891 "Could not convert to function");
1892}
1893
1894
1895void v8::String::CheckCast(v8::Value* that) {
1896 if (IsDeadCheck("v8::String::Cast()")) return;
1897 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1898 ApiCheck(obj->IsString(),
1899 "v8::String::Cast()",
1900 "Could not convert to string");
1901}
1902
1903
1904void v8::Number::CheckCast(v8::Value* that) {
1905 if (IsDeadCheck("v8::Number::Cast()")) return;
1906 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1907 ApiCheck(obj->IsNumber(),
1908 "v8::Number::Cast()",
1909 "Could not convert to number");
1910}
1911
1912
1913void v8::Integer::CheckCast(v8::Value* that) {
1914 if (IsDeadCheck("v8::Integer::Cast()")) return;
1915 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1916 ApiCheck(obj->IsNumber(),
1917 "v8::Integer::Cast()",
1918 "Could not convert to number");
1919}
1920
1921
1922void v8::Array::CheckCast(Value* that) {
1923 if (IsDeadCheck("v8::Array::Cast()")) return;
1924 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1925 ApiCheck(obj->IsJSArray(),
1926 "v8::Array::Cast()",
1927 "Could not convert to array");
1928}
1929
1930
1931void v8::Date::CheckCast(v8::Value* that) {
1932 if (IsDeadCheck("v8::Date::Cast()")) return;
1933 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1934 ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
1935 "v8::Date::Cast()",
1936 "Could not convert to date");
1937}
1938
1939
1940bool Value::BooleanValue() const {
1941 if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
1942 LOG_API("BooleanValue");
1943 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1944 if (obj->IsBoolean()) {
1945 return obj->IsTrue();
1946 } else {
1947 ENTER_V8;
1948 i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
1949 return value->IsTrue();
1950 }
1951}
1952
1953
1954double Value::NumberValue() const {
1955 if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
1956 LOG_API("NumberValue");
1957 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1958 i::Handle<i::Object> num;
1959 if (obj->IsNumber()) {
1960 num = obj;
1961 } else {
1962 ENTER_V8;
1963 EXCEPTION_PREAMBLE();
1964 num = i::Execution::ToNumber(obj, &has_pending_exception);
1965 EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
1966 }
1967 return num->Number();
1968}
1969
1970
1971int64_t Value::IntegerValue() const {
1972 if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
1973 LOG_API("IntegerValue");
1974 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1975 i::Handle<i::Object> num;
1976 if (obj->IsNumber()) {
1977 num = obj;
1978 } else {
1979 ENTER_V8;
1980 EXCEPTION_PREAMBLE();
1981 num = i::Execution::ToInteger(obj, &has_pending_exception);
1982 EXCEPTION_BAILOUT_CHECK(0);
1983 }
1984 if (num->IsSmi()) {
1985 return i::Smi::cast(*num)->value();
1986 } else {
1987 return static_cast<int64_t>(num->Number());
1988 }
1989}
1990
1991
1992Local<Int32> Value::ToInt32() const {
1993 if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
1994 LOG_API("ToInt32");
1995 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1996 i::Handle<i::Object> num;
1997 if (obj->IsSmi()) {
1998 num = obj;
1999 } else {
2000 ENTER_V8;
2001 EXCEPTION_PREAMBLE();
2002 num = i::Execution::ToInt32(obj, &has_pending_exception);
2003 EXCEPTION_BAILOUT_CHECK(Local<Int32>());
2004 }
2005 return Local<Int32>(ToApi<Int32>(num));
2006}
2007
2008
2009Local<Uint32> Value::ToUint32() const {
2010 if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
2011 LOG_API("ToUInt32");
2012 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2013 i::Handle<i::Object> num;
2014 if (obj->IsSmi()) {
2015 num = obj;
2016 } else {
2017 ENTER_V8;
2018 EXCEPTION_PREAMBLE();
2019 num = i::Execution::ToUint32(obj, &has_pending_exception);
2020 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2021 }
2022 return Local<Uint32>(ToApi<Uint32>(num));
2023}
2024
2025
2026Local<Uint32> Value::ToArrayIndex() const {
2027 if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
2028 LOG_API("ToArrayIndex");
2029 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2030 if (obj->IsSmi()) {
2031 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2032 return Local<Uint32>();
2033 }
2034 ENTER_V8;
2035 EXCEPTION_PREAMBLE();
2036 i::Handle<i::Object> string_obj =
2037 i::Execution::ToString(obj, &has_pending_exception);
2038 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2039 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2040 uint32_t index;
2041 if (str->AsArrayIndex(&index)) {
2042 i::Handle<i::Object> value;
2043 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2044 value = i::Handle<i::Object>(i::Smi::FromInt(index));
2045 } else {
2046 value = i::Factory::NewNumber(index);
2047 }
2048 return Utils::Uint32ToLocal(value);
2049 }
2050 return Local<Uint32>();
2051}
2052
2053
2054int32_t Value::Int32Value() const {
2055 if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
2056 LOG_API("Int32Value");
2057 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2058 if (obj->IsSmi()) {
2059 return i::Smi::cast(*obj)->value();
2060 } else {
2061 LOG_API("Int32Value (slow)");
2062 ENTER_V8;
2063 EXCEPTION_PREAMBLE();
2064 i::Handle<i::Object> num =
2065 i::Execution::ToInt32(obj, &has_pending_exception);
2066 EXCEPTION_BAILOUT_CHECK(0);
2067 if (num->IsSmi()) {
2068 return i::Smi::cast(*num)->value();
2069 } else {
2070 return static_cast<int32_t>(num->Number());
2071 }
2072 }
2073}
2074
2075
2076bool Value::Equals(Handle<Value> that) const {
2077 if (IsDeadCheck("v8::Value::Equals()")
2078 || EmptyCheck("v8::Value::Equals()", this)
2079 || EmptyCheck("v8::Value::Equals()", that)) {
2080 return false;
2081 }
2082 LOG_API("Equals");
2083 ENTER_V8;
2084 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2085 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2086 i::Object** args[1] = { other.location() };
2087 EXCEPTION_PREAMBLE();
2088 i::Handle<i::Object> result =
2089 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
2090 EXCEPTION_BAILOUT_CHECK(false);
2091 return *result == i::Smi::FromInt(i::EQUAL);
2092}
2093
2094
2095bool Value::StrictEquals(Handle<Value> that) const {
2096 if (IsDeadCheck("v8::Value::StrictEquals()")
2097 || EmptyCheck("v8::Value::StrictEquals()", this)
2098 || EmptyCheck("v8::Value::StrictEquals()", that)) {
2099 return false;
2100 }
2101 LOG_API("StrictEquals");
2102 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2103 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2104 // Must check HeapNumber first, since NaN !== NaN.
2105 if (obj->IsHeapNumber()) {
2106 if (!other->IsNumber()) return false;
2107 double x = obj->Number();
2108 double y = other->Number();
2109 // Must check explicitly for NaN:s on Windows, but -0 works fine.
2110 return x == y && !isnan(x) && !isnan(y);
2111 } else if (*obj == *other) { // Also covers Booleans.
2112 return true;
2113 } else if (obj->IsSmi()) {
2114 return other->IsNumber() && obj->Number() == other->Number();
2115 } else if (obj->IsString()) {
2116 return other->IsString() &&
2117 i::String::cast(*obj)->Equals(i::String::cast(*other));
2118 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2119 return other->IsUndefined() || other->IsUndetectableObject();
2120 } else {
2121 return false;
2122 }
2123}
2124
2125
2126uint32_t Value::Uint32Value() const {
2127 if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
2128 LOG_API("Uint32Value");
2129 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2130 if (obj->IsSmi()) {
2131 return i::Smi::cast(*obj)->value();
2132 } else {
2133 ENTER_V8;
2134 EXCEPTION_PREAMBLE();
2135 i::Handle<i::Object> num =
2136 i::Execution::ToUint32(obj, &has_pending_exception);
2137 EXCEPTION_BAILOUT_CHECK(0);
2138 if (num->IsSmi()) {
2139 return i::Smi::cast(*num)->value();
2140 } else {
2141 return static_cast<uint32_t>(num->Number());
2142 }
2143 }
2144}
2145
2146
2147bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
2148 v8::PropertyAttribute attribs) {
2149 ON_BAILOUT("v8::Object::Set()", return false);
2150 ENTER_V8;
2151 HandleScope scope;
2152 i::Handle<i::Object> self = Utils::OpenHandle(this);
2153 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2154 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2155 EXCEPTION_PREAMBLE();
2156 i::Handle<i::Object> obj = i::SetProperty(
2157 self,
2158 key_obj,
2159 value_obj,
2160 static_cast<PropertyAttributes>(attribs));
2161 has_pending_exception = obj.is_null();
2162 EXCEPTION_BAILOUT_CHECK(false);
2163 return true;
2164}
2165
2166
Steve Block6ded16b2010-05-10 14:33:55 +01002167bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
2168 ON_BAILOUT("v8::Object::Set()", return false);
2169 ENTER_V8;
2170 HandleScope scope;
2171 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2172 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2173 EXCEPTION_PREAMBLE();
2174 i::Handle<i::Object> obj = i::SetElement(
2175 self,
2176 index,
2177 value_obj);
2178 has_pending_exception = obj.is_null();
2179 EXCEPTION_BAILOUT_CHECK(false);
2180 return true;
2181}
2182
2183
Steve Blocka7e24c12009-10-30 11:49:00 +00002184bool v8::Object::ForceSet(v8::Handle<Value> key,
2185 v8::Handle<Value> value,
2186 v8::PropertyAttribute attribs) {
2187 ON_BAILOUT("v8::Object::ForceSet()", return false);
2188 ENTER_V8;
2189 HandleScope scope;
2190 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2191 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2192 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2193 EXCEPTION_PREAMBLE();
2194 i::Handle<i::Object> obj = i::ForceSetProperty(
2195 self,
2196 key_obj,
2197 value_obj,
2198 static_cast<PropertyAttributes>(attribs));
2199 has_pending_exception = obj.is_null();
2200 EXCEPTION_BAILOUT_CHECK(false);
2201 return true;
2202}
2203
2204
2205bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2206 ON_BAILOUT("v8::Object::ForceDelete()", return false);
2207 ENTER_V8;
2208 HandleScope scope;
2209 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2210 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2211 EXCEPTION_PREAMBLE();
2212 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2213 has_pending_exception = obj.is_null();
2214 EXCEPTION_BAILOUT_CHECK(false);
2215 return obj->IsTrue();
2216}
2217
2218
2219Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2220 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2221 ENTER_V8;
2222 i::Handle<i::Object> self = Utils::OpenHandle(this);
2223 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2224 EXCEPTION_PREAMBLE();
2225 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2226 has_pending_exception = result.is_null();
2227 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2228 return Utils::ToLocal(result);
2229}
2230
2231
Steve Block6ded16b2010-05-10 14:33:55 +01002232Local<Value> v8::Object::Get(uint32_t index) {
2233 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2234 ENTER_V8;
2235 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2236 EXCEPTION_PREAMBLE();
2237 i::Handle<i::Object> result = i::GetElement(self, index);
2238 has_pending_exception = result.is_null();
2239 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2240 return Utils::ToLocal(result);
2241}
2242
2243
Steve Blocka7e24c12009-10-30 11:49:00 +00002244Local<Value> v8::Object::GetPrototype() {
2245 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
2246 ENTER_V8;
2247 i::Handle<i::Object> self = Utils::OpenHandle(this);
2248 i::Handle<i::Object> result = i::GetPrototype(self);
2249 return Utils::ToLocal(result);
2250}
2251
2252
Andrei Popescu402d9372010-02-26 13:31:12 +00002253bool v8::Object::SetPrototype(Handle<Value> value) {
2254 ON_BAILOUT("v8::Object::SetPrototype()", return false);
2255 ENTER_V8;
2256 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2257 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2258 EXCEPTION_PREAMBLE();
2259 i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2260 has_pending_exception = result.is_null();
2261 EXCEPTION_BAILOUT_CHECK(false);
2262 return true;
2263}
2264
2265
Steve Blocka7e24c12009-10-30 11:49:00 +00002266Local<Object> v8::Object::FindInstanceInPrototypeChain(
2267 v8::Handle<FunctionTemplate> tmpl) {
2268 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
2269 return Local<v8::Object>());
2270 ENTER_V8;
2271 i::JSObject* object = *Utils::OpenHandle(this);
2272 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2273 while (!object->IsInstanceOf(tmpl_info)) {
2274 i::Object* prototype = object->GetPrototype();
2275 if (!prototype->IsJSObject()) return Local<Object>();
2276 object = i::JSObject::cast(prototype);
2277 }
2278 return Utils::ToLocal(i::Handle<i::JSObject>(object));
2279}
2280
2281
2282Local<Array> v8::Object::GetPropertyNames() {
2283 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
2284 ENTER_V8;
2285 v8::HandleScope scope;
2286 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2287 i::Handle<i::FixedArray> value =
2288 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2289 // Because we use caching to speed up enumeration it is important
2290 // to never change the result of the basic enumeration function so
2291 // we clone the result.
2292 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
2293 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
2294 return scope.Close(Utils::ToLocal(result));
2295}
2296
2297
2298Local<String> v8::Object::ObjectProtoToString() {
2299 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2300 ENTER_V8;
2301 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2302
2303 i::Handle<i::Object> name(self->class_name());
2304
2305 // Native implementation of Object.prototype.toString (v8natives.js):
2306 // var c = %ClassOf(this);
2307 // if (c === 'Arguments') c = 'Object';
2308 // return "[object " + c + "]";
2309
2310 if (!name->IsString()) {
2311 return v8::String::New("[object ]");
2312
2313 } else {
2314 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2315 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2316 return v8::String::New("[object Object]");
2317
2318 } else {
2319 const char* prefix = "[object ";
2320 Local<String> str = Utils::ToLocal(class_name);
2321 const char* postfix = "]";
2322
Steve Blockd0582a62009-12-15 09:54:21 +00002323 int prefix_len = i::StrLength(prefix);
2324 int str_len = str->Length();
2325 int postfix_len = i::StrLength(postfix);
Steve Blocka7e24c12009-10-30 11:49:00 +00002326
Steve Blockd0582a62009-12-15 09:54:21 +00002327 int buf_len = prefix_len + str_len + postfix_len;
Kristian Monsen25f61362010-05-21 11:50:48 +01002328 i::ScopedVector<char> buf(buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002329
2330 // Write prefix.
Kristian Monsen25f61362010-05-21 11:50:48 +01002331 char* ptr = buf.start();
Steve Blocka7e24c12009-10-30 11:49:00 +00002332 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2333 ptr += prefix_len;
2334
2335 // Write real content.
2336 str->WriteAscii(ptr, 0, str_len);
2337 ptr += str_len;
2338
2339 // Write postfix.
2340 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2341
2342 // Copy the buffer into a heap-allocated string and return it.
Kristian Monsen25f61362010-05-21 11:50:48 +01002343 Local<String> result = v8::String::New(buf.start(), buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002344 return result;
2345 }
2346 }
2347}
2348
2349
2350bool v8::Object::Delete(v8::Handle<String> key) {
2351 ON_BAILOUT("v8::Object::Delete()", return false);
2352 ENTER_V8;
2353 HandleScope scope;
2354 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2355 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2356 return i::DeleteProperty(self, key_obj)->IsTrue();
2357}
2358
2359
2360bool v8::Object::Has(v8::Handle<String> key) {
2361 ON_BAILOUT("v8::Object::Has()", return false);
2362 ENTER_V8;
2363 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2364 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2365 return self->HasProperty(*key_obj);
2366}
2367
2368
2369bool v8::Object::Delete(uint32_t index) {
2370 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2371 ENTER_V8;
2372 HandleScope scope;
2373 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2374 return i::DeleteElement(self, index)->IsTrue();
2375}
2376
2377
2378bool v8::Object::Has(uint32_t index) {
2379 ON_BAILOUT("v8::Object::HasProperty()", return false);
2380 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2381 return self->HasElement(index);
2382}
2383
2384
Leon Clarkef7060e22010-06-03 12:02:55 +01002385bool Object::SetAccessor(Handle<String> name,
2386 AccessorGetter getter,
2387 AccessorSetter setter,
2388 v8::Handle<Value> data,
2389 AccessControl settings,
2390 PropertyAttribute attributes) {
2391 ON_BAILOUT("v8::Object::SetAccessor()", return false);
2392 ENTER_V8;
2393 HandleScope scope;
2394 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name,
2395 getter, setter, data,
2396 settings, attributes);
2397 i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info);
2398 return !result.is_null() && !result->IsUndefined();
2399}
2400
2401
Steve Blocka7e24c12009-10-30 11:49:00 +00002402bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2403 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2404 return Utils::OpenHandle(this)->HasRealNamedProperty(
2405 *Utils::OpenHandle(*key));
2406}
2407
2408
2409bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2410 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2411 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2412}
2413
2414
2415bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2416 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2417 ENTER_V8;
2418 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2419 *Utils::OpenHandle(*key));
2420}
2421
2422
2423bool v8::Object::HasNamedLookupInterceptor() {
2424 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2425 return Utils::OpenHandle(this)->HasNamedInterceptor();
2426}
2427
2428
2429bool v8::Object::HasIndexedLookupInterceptor() {
2430 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2431 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2432}
2433
2434
2435Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2436 Handle<String> key) {
2437 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2438 return Local<Value>());
2439 ENTER_V8;
2440 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2441 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2442 i::LookupResult lookup;
2443 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002444 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002445 PropertyAttributes attributes;
2446 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2447 &lookup,
2448 *key_obj,
2449 &attributes));
2450 return Utils::ToLocal(result);
2451 }
2452 return Local<Value>(); // No real property was found in prototype chain.
2453}
2454
2455
2456Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2457 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
2458 ENTER_V8;
2459 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2460 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2461 i::LookupResult lookup;
2462 self_obj->LookupRealNamedProperty(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002463 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002464 PropertyAttributes attributes;
2465 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2466 &lookup,
2467 *key_obj,
2468 &attributes));
2469 return Utils::ToLocal(result);
2470 }
2471 return Local<Value>(); // No real property was found in prototype chain.
2472}
2473
2474
2475// Turns on access checks by copying the map and setting the check flag.
2476// Because the object gets a new map, existing inline cache caching
2477// the old map of this object will fail.
2478void v8::Object::TurnOnAccessCheck() {
2479 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2480 ENTER_V8;
2481 HandleScope scope;
2482 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2483
2484 i::Handle<i::Map> new_map =
2485 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2486 new_map->set_is_access_check_needed(true);
2487 obj->set_map(*new_map);
2488}
2489
2490
2491bool v8::Object::IsDirty() {
2492 return Utils::OpenHandle(this)->IsDirty();
2493}
2494
2495
2496Local<v8::Object> v8::Object::Clone() {
2497 ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2498 ENTER_V8;
2499 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2500 EXCEPTION_PREAMBLE();
2501 i::Handle<i::JSObject> result = i::Copy(self);
2502 has_pending_exception = result.is_null();
2503 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2504 return Utils::ToLocal(result);
2505}
2506
2507
2508int v8::Object::GetIdentityHash() {
2509 ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2510 ENTER_V8;
2511 HandleScope scope;
2512 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2513 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2514 i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
2515 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2516 int hash_value;
2517 if (hash->IsSmi()) {
2518 hash_value = i::Smi::cast(*hash)->value();
2519 } else {
2520 int attempts = 0;
2521 do {
2522 // Generate a random 32-bit hash value but limit range to fit
2523 // within a smi.
2524 hash_value = i::V8::Random() & i::Smi::kMaxValue;
2525 attempts++;
2526 } while (hash_value == 0 && attempts < 30);
2527 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
2528 i::SetProperty(hidden_props,
2529 hash_symbol,
2530 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2531 static_cast<PropertyAttributes>(None));
2532 }
2533 return hash_value;
2534}
2535
2536
2537bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2538 v8::Handle<v8::Value> value) {
2539 ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
2540 ENTER_V8;
2541 HandleScope scope;
2542 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2543 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2544 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2545 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2546 EXCEPTION_PREAMBLE();
2547 i::Handle<i::Object> obj = i::SetProperty(
2548 hidden_props,
2549 key_obj,
2550 value_obj,
2551 static_cast<PropertyAttributes>(None));
2552 has_pending_exception = obj.is_null();
2553 EXCEPTION_BAILOUT_CHECK(false);
2554 return true;
2555}
2556
2557
2558v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2559 ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2560 ENTER_V8;
2561 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2562 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2563 if (hidden_props->IsUndefined()) {
2564 return v8::Local<v8::Value>();
2565 }
2566 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2567 EXCEPTION_PREAMBLE();
2568 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2569 has_pending_exception = result.is_null();
2570 EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2571 if (result->IsUndefined()) {
2572 return v8::Local<v8::Value>();
2573 }
2574 return Utils::ToLocal(result);
2575}
2576
2577
2578bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2579 ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2580 ENTER_V8;
2581 HandleScope scope;
2582 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2583 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2584 if (hidden_props->IsUndefined()) {
2585 return true;
2586 }
2587 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2588 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2589 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2590}
2591
2592
2593void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2594 ON_BAILOUT("v8::SetElementsToPixelData()", return);
2595 ENTER_V8;
2596 HandleScope scope;
Steve Block3ce2e202009-11-05 08:53:23 +00002597 if (!ApiCheck(length <= i::PixelArray::kMaxLength,
Steve Blocka7e24c12009-10-30 11:49:00 +00002598 "v8::Object::SetIndexedPropertiesToPixelData()",
2599 "length exceeds max acceptable value")) {
2600 return;
2601 }
2602 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2603 if (!ApiCheck(!self->IsJSArray(),
2604 "v8::Object::SetIndexedPropertiesToPixelData()",
2605 "JSArray is not supported")) {
2606 return;
2607 }
2608 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
Steve Block8defd9f2010-07-08 12:39:36 +01002609 self->set_map(
2610 *i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map())));
Steve Blocka7e24c12009-10-30 11:49:00 +00002611 self->set_elements(*pixels);
2612}
2613
2614
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002615bool v8::Object::HasIndexedPropertiesInPixelData() {
2616 ON_BAILOUT("v8::HasIndexedPropertiesInPixelData()", return false);
2617 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2618 return self->HasPixelElements();
2619}
2620
2621
2622uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
2623 ON_BAILOUT("v8::GetIndexedPropertiesPixelData()", return NULL);
2624 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2625 if (self->HasPixelElements()) {
2626 return i::PixelArray::cast(self->elements())->external_pointer();
2627 } else {
2628 return NULL;
2629 }
2630}
2631
2632
2633int v8::Object::GetIndexedPropertiesPixelDataLength() {
2634 ON_BAILOUT("v8::GetIndexedPropertiesPixelDataLength()", return -1);
2635 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2636 if (self->HasPixelElements()) {
2637 return i::PixelArray::cast(self->elements())->length();
2638 } else {
2639 return -1;
2640 }
2641}
2642
2643
Steve Block3ce2e202009-11-05 08:53:23 +00002644void v8::Object::SetIndexedPropertiesToExternalArrayData(
2645 void* data,
2646 ExternalArrayType array_type,
2647 int length) {
2648 ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
2649 ENTER_V8;
2650 HandleScope scope;
2651 if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
2652 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2653 "length exceeds max acceptable value")) {
2654 return;
2655 }
2656 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2657 if (!ApiCheck(!self->IsJSArray(),
2658 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2659 "JSArray is not supported")) {
2660 return;
2661 }
2662 i::Handle<i::ExternalArray> array =
2663 i::Factory::NewExternalArray(length, array_type, data);
Steve Block8defd9f2010-07-08 12:39:36 +01002664 self->set_map(
2665 *i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map())));
Steve Block3ce2e202009-11-05 08:53:23 +00002666 self->set_elements(*array);
2667}
2668
2669
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002670bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
2671 ON_BAILOUT("v8::HasIndexedPropertiesInExternalArrayData()", return false);
2672 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2673 return self->HasExternalArrayElements();
2674}
2675
2676
2677void* v8::Object::GetIndexedPropertiesExternalArrayData() {
2678 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayData()", return NULL);
2679 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2680 if (self->HasExternalArrayElements()) {
2681 return i::ExternalArray::cast(self->elements())->external_pointer();
2682 } else {
2683 return NULL;
2684 }
2685}
2686
2687
2688ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
2689 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataType()",
2690 return static_cast<ExternalArrayType>(-1));
2691 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2692 switch (self->elements()->map()->instance_type()) {
2693 case i::EXTERNAL_BYTE_ARRAY_TYPE:
2694 return kExternalByteArray;
2695 case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2696 return kExternalUnsignedByteArray;
2697 case i::EXTERNAL_SHORT_ARRAY_TYPE:
2698 return kExternalShortArray;
2699 case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2700 return kExternalUnsignedShortArray;
2701 case i::EXTERNAL_INT_ARRAY_TYPE:
2702 return kExternalIntArray;
2703 case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2704 return kExternalUnsignedIntArray;
2705 case i::EXTERNAL_FLOAT_ARRAY_TYPE:
2706 return kExternalFloatArray;
2707 default:
2708 return static_cast<ExternalArrayType>(-1);
2709 }
2710}
2711
2712
2713int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
2714 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataLength()", return 0);
2715 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2716 if (self->HasExternalArrayElements()) {
2717 return i::ExternalArray::cast(self->elements())->length();
2718 } else {
2719 return -1;
2720 }
2721}
2722
2723
Steve Blocka7e24c12009-10-30 11:49:00 +00002724Local<v8::Object> Function::NewInstance() const {
2725 return NewInstance(0, NULL);
2726}
2727
2728
2729Local<v8::Object> Function::NewInstance(int argc,
2730 v8::Handle<v8::Value> argv[]) const {
2731 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2732 LOG_API("Function::NewInstance");
2733 ENTER_V8;
2734 HandleScope scope;
2735 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2736 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2737 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2738 EXCEPTION_PREAMBLE();
2739 i::Handle<i::Object> returned =
2740 i::Execution::New(function, argc, args, &has_pending_exception);
2741 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2742 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2743}
2744
2745
2746Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2747 v8::Handle<v8::Value> argv[]) {
2748 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2749 LOG_API("Function::Call");
2750 ENTER_V8;
2751 i::Object* raw_result = NULL;
2752 {
2753 HandleScope scope;
2754 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2755 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2756 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2757 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2758 EXCEPTION_PREAMBLE();
2759 i::Handle<i::Object> returned =
2760 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2761 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2762 raw_result = *returned;
2763 }
2764 i::Handle<i::Object> result(raw_result);
2765 return Utils::ToLocal(result);
2766}
2767
2768
2769void Function::SetName(v8::Handle<v8::String> name) {
2770 ENTER_V8;
2771 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2772 func->shared()->set_name(*Utils::OpenHandle(*name));
2773}
2774
2775
2776Handle<Value> Function::GetName() const {
2777 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2778 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2779}
2780
2781
Andrei Popescu402d9372010-02-26 13:31:12 +00002782ScriptOrigin Function::GetScriptOrigin() const {
2783 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2784 if (func->shared()->script()->IsScript()) {
2785 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2786 v8::ScriptOrigin origin(
2787 Utils::ToLocal(i::Handle<i::Object>(script->name())),
2788 v8::Integer::New(script->line_offset()->value()),
2789 v8::Integer::New(script->column_offset()->value()));
2790 return origin;
2791 }
2792 return v8::ScriptOrigin(Handle<Value>());
2793}
2794
2795
2796const int Function::kLineOffsetNotFound = -1;
2797
2798
2799int Function::GetScriptLineNumber() const {
2800 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2801 if (func->shared()->script()->IsScript()) {
2802 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2803 return i::GetScriptLineNumber(script, func->shared()->start_position());
2804 }
2805 return kLineOffsetNotFound;
2806}
2807
2808
2809namespace {
2810
2811// Tracks string usage to help make better decisions when
2812// externalizing strings.
2813//
2814// Implementation note: internally this class only tracks fresh
2815// strings and keeps a single use counter for them.
2816class StringTracker {
2817 public:
2818 // Records that the given string's characters were copied to some
2819 // external buffer. If this happens often we should honor
2820 // externalization requests for the string.
2821 static void RecordWrite(i::Handle<i::String> string) {
2822 i::Address address = reinterpret_cast<i::Address>(*string);
2823 i::Address top = i::Heap::NewSpaceTop();
2824 if (IsFreshString(address, top)) {
2825 IncrementUseCount(top);
2826 }
2827 }
2828
2829 // Estimates freshness and use frequency of the given string based
2830 // on how close it is to the new space top and the recorded usage
2831 // history.
2832 static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
2833 i::Address address = reinterpret_cast<i::Address>(*string);
2834 i::Address top = i::Heap::NewSpaceTop();
2835 return IsFreshString(address, top) && IsUseCountLow(top);
2836 }
2837
2838 private:
2839 static inline bool IsFreshString(i::Address string, i::Address top) {
2840 return top - kFreshnessLimit <= string && string <= top;
2841 }
2842
2843 static inline bool IsUseCountLow(i::Address top) {
2844 if (last_top_ != top) return true;
2845 return use_count_ < kUseLimit;
2846 }
2847
2848 static inline void IncrementUseCount(i::Address top) {
2849 if (last_top_ != top) {
2850 use_count_ = 0;
2851 last_top_ = top;
2852 }
2853 ++use_count_;
2854 }
2855
2856 // How close to the new space top a fresh string has to be.
2857 static const int kFreshnessLimit = 1024;
2858
2859 // The number of uses required to consider a string useful.
2860 static const int kUseLimit = 32;
2861
2862 // Single use counter shared by all fresh strings.
2863 static int use_count_;
2864
2865 // Last new space top when the use count above was valid.
2866 static i::Address last_top_;
2867};
2868
2869int StringTracker::use_count_ = 0;
2870i::Address StringTracker::last_top_ = NULL;
2871
2872} // namespace
2873
2874
Steve Blocka7e24c12009-10-30 11:49:00 +00002875int String::Length() const {
2876 if (IsDeadCheck("v8::String::Length()")) return 0;
2877 return Utils::OpenHandle(this)->length();
2878}
2879
2880
2881int String::Utf8Length() const {
2882 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
2883 return Utils::OpenHandle(this)->Utf8Length();
2884}
2885
2886
Steve Block6ded16b2010-05-10 14:33:55 +01002887int String::WriteUtf8(char* buffer,
2888 int capacity,
2889 int* nchars_ref,
2890 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002891 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
2892 LOG_API("String::WriteUtf8");
2893 ENTER_V8;
2894 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002895 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002896 if (hints & HINT_MANY_WRITES_EXPECTED) {
2897 // Flatten the string for efficiency. This applies whether we are
2898 // using StringInputBuffer or Get(i) to access the characters.
2899 str->TryFlatten();
2900 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002901 write_input_buffer.Reset(0, *str);
2902 int len = str->length();
2903 // Encode the first K - 3 bytes directly into the buffer since we
2904 // know there's room for them. If no capacity is given we copy all
2905 // of them here.
2906 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
2907 int i;
2908 int pos = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01002909 int nchars = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002910 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
2911 i::uc32 c = write_input_buffer.GetNext();
2912 int written = unibrow::Utf8::Encode(buffer + pos, c);
2913 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002914 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002915 }
2916 if (i < len) {
2917 // For the last characters we need to check the length for each one
2918 // because they may be longer than the remaining space in the
2919 // buffer.
2920 char intermediate[unibrow::Utf8::kMaxEncodedSize];
2921 for (; i < len && pos < capacity; i++) {
2922 i::uc32 c = write_input_buffer.GetNext();
2923 int written = unibrow::Utf8::Encode(intermediate, c);
2924 if (pos + written <= capacity) {
2925 for (int j = 0; j < written; j++)
2926 buffer[pos + j] = intermediate[j];
2927 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002928 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002929 } else {
2930 // We've reached the end of the buffer
2931 break;
2932 }
2933 }
2934 }
Steve Block6ded16b2010-05-10 14:33:55 +01002935 if (nchars_ref != NULL) *nchars_ref = nchars;
Steve Blocka7e24c12009-10-30 11:49:00 +00002936 if (i == len && (capacity == -1 || pos < capacity))
2937 buffer[pos++] = '\0';
2938 return pos;
2939}
2940
2941
Steve Block6ded16b2010-05-10 14:33:55 +01002942int String::WriteAscii(char* buffer,
2943 int start,
2944 int length,
2945 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002946 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
2947 LOG_API("String::WriteAscii");
2948 ENTER_V8;
2949 ASSERT(start >= 0 && length >= -1);
2950 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002951 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002952 if (hints & HINT_MANY_WRITES_EXPECTED) {
2953 // Flatten the string for efficiency. This applies whether we are
2954 // using StringInputBuffer or Get(i) to access the characters.
2955 str->TryFlatten();
2956 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002957 int end = length;
2958 if ( (length == -1) || (length > str->length() - start) )
2959 end = str->length() - start;
2960 if (end < 0) return 0;
2961 write_input_buffer.Reset(start, *str);
2962 int i;
2963 for (i = 0; i < end; i++) {
2964 char c = static_cast<char>(write_input_buffer.GetNext());
2965 if (c == '\0') c = ' ';
2966 buffer[i] = c;
2967 }
2968 if (length == -1 || i < length)
2969 buffer[i] = '\0';
2970 return i;
2971}
2972
2973
Steve Block6ded16b2010-05-10 14:33:55 +01002974int String::Write(uint16_t* buffer,
2975 int start,
2976 int length,
2977 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002978 if (IsDeadCheck("v8::String::Write()")) return 0;
2979 LOG_API("String::Write");
2980 ENTER_V8;
2981 ASSERT(start >= 0 && length >= -1);
2982 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002983 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002984 if (hints & HINT_MANY_WRITES_EXPECTED) {
2985 // Flatten the string for efficiency. This applies whether we are
2986 // using StringInputBuffer or Get(i) to access the characters.
2987 str->TryFlatten();
2988 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002989 int end = length;
2990 if ( (length == -1) || (length > str->length() - start) )
2991 end = str->length() - start;
2992 if (end < 0) return 0;
2993 i::String::WriteToFlat(*str, buffer, start, end);
2994 if (length == -1 || end < length)
2995 buffer[end] = '\0';
2996 return end;
2997}
2998
2999
3000bool v8::String::IsExternal() const {
3001 EnsureInitialized("v8::String::IsExternal()");
3002 i::Handle<i::String> str = Utils::OpenHandle(this);
3003 return i::StringShape(*str).IsExternalTwoByte();
3004}
3005
3006
3007bool v8::String::IsExternalAscii() const {
3008 EnsureInitialized("v8::String::IsExternalAscii()");
3009 i::Handle<i::String> str = Utils::OpenHandle(this);
3010 return i::StringShape(*str).IsExternalAscii();
3011}
3012
3013
3014void v8::String::VerifyExternalStringResource(
3015 v8::String::ExternalStringResource* value) const {
3016 i::Handle<i::String> str = Utils::OpenHandle(this);
3017 v8::String::ExternalStringResource* expected;
3018 if (i::StringShape(*str).IsExternalTwoByte()) {
3019 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
3020 expected = reinterpret_cast<ExternalStringResource*>(resource);
3021 } else {
3022 expected = NULL;
3023 }
3024 CHECK_EQ(expected, value);
3025}
3026
3027
3028v8::String::ExternalAsciiStringResource*
3029 v8::String::GetExternalAsciiStringResource() const {
3030 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
3031 i::Handle<i::String> str = Utils::OpenHandle(this);
3032 if (i::StringShape(*str).IsExternalAscii()) {
3033 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
3034 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
3035 } else {
3036 return NULL;
3037 }
3038}
3039
3040
3041double Number::Value() const {
3042 if (IsDeadCheck("v8::Number::Value()")) return 0;
3043 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3044 return obj->Number();
3045}
3046
3047
3048bool Boolean::Value() const {
3049 if (IsDeadCheck("v8::Boolean::Value()")) return false;
3050 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3051 return obj->IsTrue();
3052}
3053
3054
3055int64_t Integer::Value() const {
3056 if (IsDeadCheck("v8::Integer::Value()")) return 0;
3057 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3058 if (obj->IsSmi()) {
3059 return i::Smi::cast(*obj)->value();
3060 } else {
3061 return static_cast<int64_t>(obj->Number());
3062 }
3063}
3064
3065
3066int32_t Int32::Value() const {
3067 if (IsDeadCheck("v8::Int32::Value()")) return 0;
3068 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3069 if (obj->IsSmi()) {
3070 return i::Smi::cast(*obj)->value();
3071 } else {
3072 return static_cast<int32_t>(obj->Number());
3073 }
3074}
3075
3076
Steve Block6ded16b2010-05-10 14:33:55 +01003077uint32_t Uint32::Value() const {
3078 if (IsDeadCheck("v8::Uint32::Value()")) return 0;
3079 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3080 if (obj->IsSmi()) {
3081 return i::Smi::cast(*obj)->value();
3082 } else {
3083 return static_cast<uint32_t>(obj->Number());
3084 }
3085}
3086
3087
Steve Blocka7e24c12009-10-30 11:49:00 +00003088int v8::Object::InternalFieldCount() {
3089 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
3090 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3091 return obj->GetInternalFieldCount();
3092}
3093
3094
3095Local<Value> v8::Object::CheckedGetInternalField(int index) {
3096 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
3097 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3098 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3099 "v8::Object::GetInternalField()",
3100 "Reading internal field out of bounds")) {
3101 return Local<Value>();
3102 }
3103 i::Handle<i::Object> value(obj->GetInternalField(index));
3104 Local<Value> result = Utils::ToLocal(value);
3105#ifdef DEBUG
3106 Local<Value> unchecked = UncheckedGetInternalField(index);
3107 ASSERT(unchecked.IsEmpty() || (unchecked == result));
3108#endif
3109 return result;
3110}
3111
3112
3113void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
3114 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
3115 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3116 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3117 "v8::Object::SetInternalField()",
3118 "Writing internal field out of bounds")) {
3119 return;
3120 }
3121 ENTER_V8;
3122 i::Handle<i::Object> val = Utils::OpenHandle(*value);
3123 obj->SetInternalField(index, *val);
3124}
3125
3126
3127void v8::Object::SetPointerInInternalField(int index, void* value) {
Steve Block6ded16b2010-05-10 14:33:55 +01003128 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003129 i::Object* as_object = reinterpret_cast<i::Object*>(value);
3130 if (as_object->IsSmi()) {
3131 Utils::OpenHandle(this)->SetInternalField(index, as_object);
3132 return;
3133 }
3134 HandleScope scope;
3135 i::Handle<i::Proxy> proxy =
3136 i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
3137 if (!proxy.is_null())
3138 Utils::OpenHandle(this)->SetInternalField(index, *proxy);
Steve Blocka7e24c12009-10-30 11:49:00 +00003139}
3140
3141
3142// --- E n v i r o n m e n t ---
3143
3144bool v8::V8::Initialize() {
3145 if (i::V8::IsRunning()) return true;
3146 ENTER_V8;
3147 HandleScope scope;
Steve Blockd0582a62009-12-15 09:54:21 +00003148 if (i::Snapshot::Initialize()) return true;
3149 return i::V8::Initialize(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00003150}
3151
3152
3153bool v8::V8::Dispose() {
3154 i::V8::TearDown();
3155 return true;
3156}
3157
3158
Steve Block3ce2e202009-11-05 08:53:23 +00003159HeapStatistics::HeapStatistics(): total_heap_size_(0), used_heap_size_(0) { }
3160
3161
3162void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
3163 heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
3164 heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
3165}
3166
3167
3168bool v8::V8::IdleNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003169 // Returning true tells the caller that it need not
3170 // continue to call IdleNotification.
3171 if (!i::V8::IsRunning()) return true;
Steve Block3ce2e202009-11-05 08:53:23 +00003172 return i::V8::IdleNotification();
Steve Blocka7e24c12009-10-30 11:49:00 +00003173}
3174
3175
3176void v8::V8::LowMemoryNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003177 if (!i::V8::IsRunning()) return;
3178 i::Heap::CollectAllGarbage(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00003179}
3180
3181
Steve Block6ded16b2010-05-10 14:33:55 +01003182int v8::V8::ContextDisposedNotification() {
3183 if (!i::V8::IsRunning()) return 0;
3184 return i::Heap::NotifyContextDisposed();
3185}
3186
3187
Steve Blocka7e24c12009-10-30 11:49:00 +00003188const char* v8::V8::GetVersion() {
3189 static v8::internal::EmbeddedVector<char, 128> buffer;
3190 v8::internal::Version::GetString(buffer);
3191 return buffer.start();
3192}
3193
3194
3195static i::Handle<i::FunctionTemplateInfo>
3196 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
3197 if (templ->constructor()->IsUndefined()) {
3198 Local<FunctionTemplate> constructor = FunctionTemplate::New();
3199 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
3200 templ->set_constructor(*Utils::OpenHandle(*constructor));
3201 }
3202 return i::Handle<i::FunctionTemplateInfo>(
3203 i::FunctionTemplateInfo::cast(templ->constructor()));
3204}
3205
3206
3207Persistent<Context> v8::Context::New(
3208 v8::ExtensionConfiguration* extensions,
3209 v8::Handle<ObjectTemplate> global_template,
3210 v8::Handle<Value> global_object) {
3211 EnsureInitialized("v8::Context::New()");
3212 LOG_API("Context::New");
3213 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
3214
3215 // Enter V8 via an ENTER_V8 scope.
3216 i::Handle<i::Context> env;
3217 {
3218 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003219 v8::Handle<ObjectTemplate> proxy_template = global_template;
3220 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
3221 i::Handle<i::FunctionTemplateInfo> global_constructor;
3222
3223 if (!global_template.IsEmpty()) {
3224 // Make sure that the global_template has a constructor.
3225 global_constructor =
3226 EnsureConstructor(Utils::OpenHandle(*global_template));
3227
3228 // Create a fresh template for the global proxy object.
3229 proxy_template = ObjectTemplate::New();
3230 proxy_constructor =
3231 EnsureConstructor(Utils::OpenHandle(*proxy_template));
3232
3233 // Set the global template to be the prototype template of
3234 // global proxy template.
3235 proxy_constructor->set_prototype_template(
3236 *Utils::OpenHandle(*global_template));
3237
3238 // Migrate security handlers from global_template to
3239 // proxy_template. Temporarily removing access check
3240 // information from the global template.
3241 if (!global_constructor->access_check_info()->IsUndefined()) {
3242 proxy_constructor->set_access_check_info(
3243 global_constructor->access_check_info());
3244 proxy_constructor->set_needs_access_check(
3245 global_constructor->needs_access_check());
3246 global_constructor->set_needs_access_check(false);
3247 global_constructor->set_access_check_info(i::Heap::undefined_value());
3248 }
3249 }
3250
3251 // Create the environment.
3252 env = i::Bootstrapper::CreateEnvironment(
3253 Utils::OpenHandle(*global_object),
3254 proxy_template,
3255 extensions);
3256
3257 // Restore the access check info on the global template.
3258 if (!global_template.IsEmpty()) {
3259 ASSERT(!global_constructor.is_null());
3260 ASSERT(!proxy_constructor.is_null());
3261 global_constructor->set_access_check_info(
3262 proxy_constructor->access_check_info());
3263 global_constructor->set_needs_access_check(
3264 proxy_constructor->needs_access_check());
3265 }
3266 }
3267 // Leave V8.
3268
3269 if (env.is_null())
3270 return Persistent<Context>();
3271 return Persistent<Context>(Utils::ToLocal(env));
3272}
3273
3274
3275void v8::Context::SetSecurityToken(Handle<Value> token) {
3276 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
3277 ENTER_V8;
3278 i::Handle<i::Context> env = Utils::OpenHandle(this);
3279 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
3280 env->set_security_token(*token_handle);
3281}
3282
3283
3284void v8::Context::UseDefaultSecurityToken() {
3285 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
3286 ENTER_V8;
3287 i::Handle<i::Context> env = Utils::OpenHandle(this);
3288 env->set_security_token(env->global());
3289}
3290
3291
3292Handle<Value> v8::Context::GetSecurityToken() {
3293 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
3294 i::Handle<i::Context> env = Utils::OpenHandle(this);
3295 i::Object* security_token = env->security_token();
3296 i::Handle<i::Object> token_handle(security_token);
3297 return Utils::ToLocal(token_handle);
3298}
3299
3300
3301bool Context::HasOutOfMemoryException() {
3302 i::Handle<i::Context> env = Utils::OpenHandle(this);
3303 return env->has_out_of_memory();
3304}
3305
3306
3307bool Context::InContext() {
3308 return i::Top::context() != NULL;
3309}
3310
3311
3312v8::Local<v8::Context> Context::GetEntered() {
3313 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
3314 i::Handle<i::Object> last = thread_local.LastEnteredContext();
3315 if (last.is_null()) return Local<Context>();
3316 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
3317 return Utils::ToLocal(context);
3318}
3319
3320
3321v8::Local<v8::Context> Context::GetCurrent() {
3322 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
Steve Block3ce2e202009-11-05 08:53:23 +00003323 i::Handle<i::Object> current = i::Top::global_context();
3324 if (current.is_null()) return Local<Context>();
3325 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
Steve Blocka7e24c12009-10-30 11:49:00 +00003326 return Utils::ToLocal(context);
3327}
3328
3329
3330v8::Local<v8::Context> Context::GetCalling() {
3331 if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
3332 i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
3333 if (calling.is_null()) return Local<Context>();
3334 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
3335 return Utils::ToLocal(context);
3336}
3337
3338
3339v8::Local<v8::Object> Context::Global() {
3340 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
3341 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3342 i::Handle<i::Context> context =
3343 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3344 i::Handle<i::Object> global(context->global_proxy());
3345 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
3346}
3347
3348
3349void Context::DetachGlobal() {
3350 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
3351 ENTER_V8;
3352 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3353 i::Handle<i::Context> context =
3354 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3355 i::Bootstrapper::DetachGlobal(context);
3356}
3357
3358
Andrei Popescu74b3c142010-03-29 12:03:09 +01003359void Context::ReattachGlobal(Handle<Object> global_object) {
3360 if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
3361 ENTER_V8;
3362 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3363 i::Handle<i::Context> context =
3364 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3365 i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
3366}
3367
3368
Steve Blocka7e24c12009-10-30 11:49:00 +00003369Local<v8::Object> ObjectTemplate::NewInstance() {
3370 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
3371 LOG_API("ObjectTemplate::NewInstance");
3372 ENTER_V8;
3373 EXCEPTION_PREAMBLE();
3374 i::Handle<i::Object> obj =
3375 i::Execution::InstantiateObject(Utils::OpenHandle(this),
3376 &has_pending_exception);
3377 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
3378 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3379}
3380
3381
3382Local<v8::Function> FunctionTemplate::GetFunction() {
3383 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
3384 return Local<v8::Function>());
3385 LOG_API("FunctionTemplate::GetFunction");
3386 ENTER_V8;
3387 EXCEPTION_PREAMBLE();
3388 i::Handle<i::Object> obj =
3389 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3390 &has_pending_exception);
3391 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
3392 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3393}
3394
3395
3396bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3397 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
3398 i::Object* obj = *Utils::OpenHandle(*value);
3399 return obj->IsInstanceOf(*Utils::OpenHandle(this));
3400}
3401
3402
3403static Local<External> ExternalNewImpl(void* data) {
3404 return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
3405}
3406
3407static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3408 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3409}
3410
3411
Steve Blocka7e24c12009-10-30 11:49:00 +00003412Local<Value> v8::External::Wrap(void* data) {
3413 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3414 LOG_API("External::Wrap");
3415 EnsureInitialized("v8::External::Wrap()");
3416 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003417 i::Object* as_object = reinterpret_cast<i::Object*>(data);
3418 if (as_object->IsSmi()) {
3419 return Utils::ToLocal(i::Handle<i::Object>(as_object));
Steve Blocka7e24c12009-10-30 11:49:00 +00003420 }
3421 return ExternalNewImpl(data);
3422}
3423
3424
Steve Block3ce2e202009-11-05 08:53:23 +00003425void* v8::Object::SlowGetPointerFromInternalField(int index) {
3426 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3427 i::Object* value = obj->GetInternalField(index);
3428 if (value->IsSmi()) {
3429 return value;
3430 } else if (value->IsProxy()) {
3431 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3432 } else {
3433 return NULL;
3434 }
3435}
3436
3437
Steve Blocka7e24c12009-10-30 11:49:00 +00003438void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3439 if (IsDeadCheck("v8::External::Unwrap()")) return 0;
3440 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3441 void* result;
3442 if (obj->IsSmi()) {
3443 // The external value was an aligned pointer.
Steve Block3ce2e202009-11-05 08:53:23 +00003444 result = *obj;
Steve Blocka7e24c12009-10-30 11:49:00 +00003445 } else if (obj->IsProxy()) {
3446 result = ExternalValueImpl(obj);
3447 } else {
3448 result = NULL;
3449 }
3450 ASSERT_EQ(result, QuickUnwrap(wrapper));
3451 return result;
3452}
3453
3454
3455Local<External> v8::External::New(void* data) {
3456 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3457 LOG_API("External::New");
3458 EnsureInitialized("v8::External::New()");
3459 ENTER_V8;
3460 return ExternalNewImpl(data);
3461}
3462
3463
3464void* External::Value() const {
3465 if (IsDeadCheck("v8::External::Value()")) return 0;
3466 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3467 return ExternalValueImpl(obj);
3468}
3469
3470
3471Local<String> v8::String::Empty() {
3472 EnsureInitialized("v8::String::Empty()");
3473 LOG_API("String::Empty()");
3474 return Utils::ToLocal(i::Factory::empty_symbol());
3475}
3476
3477
3478Local<String> v8::String::New(const char* data, int length) {
3479 EnsureInitialized("v8::String::New()");
3480 LOG_API("String::New(char)");
3481 if (length == 0) return Empty();
3482 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003483 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003484 i::Handle<i::String> result =
3485 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3486 return Utils::ToLocal(result);
3487}
3488
3489
Steve Block3ce2e202009-11-05 08:53:23 +00003490Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3491 EnsureInitialized("v8::String::New()");
3492 LOG_API("String::New(char)");
3493 ENTER_V8;
3494 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3495 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3496 i::Handle<i::String> result = i::Factory::NewConsString(left_string,
3497 right_string);
3498 return Utils::ToLocal(result);
3499}
3500
3501
Steve Blocka7e24c12009-10-30 11:49:00 +00003502Local<String> v8::String::NewUndetectable(const char* data, int length) {
3503 EnsureInitialized("v8::String::NewUndetectable()");
3504 LOG_API("String::NewUndetectable(char)");
3505 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003506 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003507 i::Handle<i::String> result =
3508 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3509 result->MarkAsUndetectable();
3510 return Utils::ToLocal(result);
3511}
3512
3513
3514static int TwoByteStringLength(const uint16_t* data) {
3515 int length = 0;
3516 while (data[length] != '\0') length++;
3517 return length;
3518}
3519
3520
3521Local<String> v8::String::New(const uint16_t* data, int length) {
3522 EnsureInitialized("v8::String::New()");
3523 LOG_API("String::New(uint16_)");
3524 if (length == 0) return Empty();
3525 ENTER_V8;
3526 if (length == -1) length = TwoByteStringLength(data);
3527 i::Handle<i::String> result =
3528 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3529 return Utils::ToLocal(result);
3530}
3531
3532
3533Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
3534 EnsureInitialized("v8::String::NewUndetectable()");
3535 LOG_API("String::NewUndetectable(uint16_)");
3536 ENTER_V8;
3537 if (length == -1) length = TwoByteStringLength(data);
3538 i::Handle<i::String> result =
3539 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3540 result->MarkAsUndetectable();
3541 return Utils::ToLocal(result);
3542}
3543
3544
3545i::Handle<i::String> NewExternalStringHandle(
3546 v8::String::ExternalStringResource* resource) {
3547 i::Handle<i::String> result =
3548 i::Factory::NewExternalStringFromTwoByte(resource);
3549 return result;
3550}
3551
3552
3553i::Handle<i::String> NewExternalAsciiStringHandle(
3554 v8::String::ExternalAsciiStringResource* resource) {
3555 i::Handle<i::String> result =
3556 i::Factory::NewExternalStringFromAscii(resource);
3557 return result;
3558}
3559
3560
Steve Blocka7e24c12009-10-30 11:49:00 +00003561Local<String> v8::String::NewExternal(
3562 v8::String::ExternalStringResource* resource) {
3563 EnsureInitialized("v8::String::NewExternal()");
3564 LOG_API("String::NewExternal");
3565 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003566 i::Handle<i::String> result = NewExternalStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003567 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003568 return Utils::ToLocal(result);
3569}
3570
3571
3572bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3573 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3574 if (this->IsExternal()) return false; // Already an external string.
3575 ENTER_V8;
3576 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003577 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003578 bool result = obj->MakeExternal(resource);
3579 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003580 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003581 }
3582 return result;
3583}
3584
3585
3586Local<String> v8::String::NewExternal(
3587 v8::String::ExternalAsciiStringResource* resource) {
3588 EnsureInitialized("v8::String::NewExternal()");
3589 LOG_API("String::NewExternal");
3590 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003591 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003592 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003593 return Utils::ToLocal(result);
3594}
3595
3596
3597bool v8::String::MakeExternal(
3598 v8::String::ExternalAsciiStringResource* resource) {
3599 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3600 if (this->IsExternal()) return false; // Already an external string.
3601 ENTER_V8;
3602 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003603 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003604 bool result = obj->MakeExternal(resource);
3605 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003606 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003607 }
3608 return result;
3609}
3610
3611
3612bool v8::String::CanMakeExternal() {
3613 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3614 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003615 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003616 int size = obj->Size(); // Byte size of the original string.
3617 if (size < i::ExternalString::kSize)
3618 return false;
3619 i::StringShape shape(*obj);
3620 return !shape.IsExternal();
3621}
3622
3623
3624Local<v8::Object> v8::Object::New() {
3625 EnsureInitialized("v8::Object::New()");
3626 LOG_API("Object::New");
3627 ENTER_V8;
3628 i::Handle<i::JSObject> obj =
3629 i::Factory::NewJSObject(i::Top::object_function());
3630 return Utils::ToLocal(obj);
3631}
3632
3633
3634Local<v8::Value> v8::Date::New(double time) {
3635 EnsureInitialized("v8::Date::New()");
3636 LOG_API("Date::New");
Steve Blockd0582a62009-12-15 09:54:21 +00003637 if (isnan(time)) {
3638 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3639 time = i::OS::nan_value();
3640 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003641 ENTER_V8;
3642 EXCEPTION_PREAMBLE();
3643 i::Handle<i::Object> obj =
3644 i::Execution::NewDate(time, &has_pending_exception);
3645 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3646 return Utils::ToLocal(obj);
3647}
3648
3649
3650double v8::Date::NumberValue() const {
3651 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3652 LOG_API("Date::NumberValue");
3653 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3654 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3655 return jsvalue->value()->Number();
3656}
3657
3658
3659Local<v8::Array> v8::Array::New(int length) {
3660 EnsureInitialized("v8::Array::New()");
3661 LOG_API("Array::New");
3662 ENTER_V8;
3663 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3664 return Utils::ToLocal(obj);
3665}
3666
3667
3668uint32_t v8::Array::Length() const {
3669 if (IsDeadCheck("v8::Array::Length()")) return 0;
3670 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3671 i::Object* length = obj->length();
3672 if (length->IsSmi()) {
3673 return i::Smi::cast(length)->value();
3674 } else {
3675 return static_cast<uint32_t>(length->Number());
3676 }
3677}
3678
3679
3680Local<Object> Array::CloneElementAt(uint32_t index) {
3681 ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3682 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3683 if (!self->HasFastElements()) {
3684 return Local<Object>();
3685 }
3686 i::FixedArray* elms = i::FixedArray::cast(self->elements());
3687 i::Object* paragon = elms->get(index);
3688 if (!paragon->IsJSObject()) {
3689 return Local<Object>();
3690 }
3691 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3692 EXCEPTION_PREAMBLE();
Steve Block6ded16b2010-05-10 14:33:55 +01003693 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003694 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3695 has_pending_exception = result.is_null();
3696 EXCEPTION_BAILOUT_CHECK(Local<Object>());
3697 return Utils::ToLocal(result);
3698}
3699
3700
3701Local<String> v8::String::NewSymbol(const char* data, int length) {
3702 EnsureInitialized("v8::String::NewSymbol()");
3703 LOG_API("String::NewSymbol(char)");
3704 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003705 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003706 i::Handle<i::String> result =
3707 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3708 return Utils::ToLocal(result);
3709}
3710
3711
3712Local<Number> v8::Number::New(double value) {
3713 EnsureInitialized("v8::Number::New()");
Steve Blockd0582a62009-12-15 09:54:21 +00003714 if (isnan(value)) {
3715 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3716 value = i::OS::nan_value();
3717 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003718 ENTER_V8;
3719 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3720 return Utils::NumberToLocal(result);
3721}
3722
3723
3724Local<Integer> v8::Integer::New(int32_t value) {
3725 EnsureInitialized("v8::Integer::New()");
3726 if (i::Smi::IsValid(value)) {
3727 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3728 }
3729 ENTER_V8;
3730 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3731 return Utils::IntegerToLocal(result);
3732}
3733
3734
Steve Block3ce2e202009-11-05 08:53:23 +00003735Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
3736 bool fits_into_int32_t = (value & (1 << 31)) == 0;
3737 if (fits_into_int32_t) {
3738 return Integer::New(static_cast<int32_t>(value));
3739 }
3740 ENTER_V8;
3741 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3742 return Utils::IntegerToLocal(result);
3743}
3744
3745
Steve Blocka7e24c12009-10-30 11:49:00 +00003746void V8::IgnoreOutOfMemoryException() {
3747 thread_local.set_ignore_out_of_memory(true);
3748}
3749
3750
3751bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
3752 EnsureInitialized("v8::V8::AddMessageListener()");
3753 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
3754 ENTER_V8;
3755 HandleScope scope;
3756 NeanderArray listeners(i::Factory::message_listeners());
3757 NeanderObject obj(2);
3758 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
3759 obj.set(1, data.IsEmpty() ?
3760 i::Heap::undefined_value() :
3761 *Utils::OpenHandle(*data));
3762 listeners.add(obj.value());
3763 return true;
3764}
3765
3766
3767void V8::RemoveMessageListeners(MessageCallback that) {
3768 EnsureInitialized("v8::V8::RemoveMessageListener()");
3769 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
3770 ENTER_V8;
3771 HandleScope scope;
3772 NeanderArray listeners(i::Factory::message_listeners());
3773 for (int i = 0; i < listeners.length(); i++) {
3774 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
3775
3776 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
3777 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
3778 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
3779 listeners.set(i, i::Heap::undefined_value());
3780 }
3781 }
3782}
3783
3784
3785void V8::SetCounterFunction(CounterLookupCallback callback) {
3786 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
3787 i::StatsTable::SetCounterFunction(callback);
3788}
3789
3790void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
3791 if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
3792 i::StatsTable::SetCreateHistogramFunction(callback);
3793}
3794
3795void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
3796 if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
3797 i::StatsTable::SetAddHistogramSampleFunction(callback);
3798}
3799
3800void V8::EnableSlidingStateWindow() {
3801 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
3802 i::Logger::EnableSlidingStateWindow();
3803}
3804
3805
3806void V8::SetFailedAccessCheckCallbackFunction(
3807 FailedAccessCheckCallback callback) {
3808 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
3809 i::Top::SetFailedAccessCheckCallback(callback);
3810}
3811
3812
3813void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
3814 if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
3815 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
3816 i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
3817}
3818
3819
3820int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
3821 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
3822 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
3823}
3824
3825
3826void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
3827 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
3828 i::Heap::SetGlobalGCPrologueCallback(callback);
3829}
3830
3831
3832void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
3833 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
3834 i::Heap::SetGlobalGCEpilogueCallback(callback);
3835}
3836
3837
Steve Block6ded16b2010-05-10 14:33:55 +01003838void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
3839 if (IsDeadCheck("v8::V8::AddGCPrologueCallback()")) return;
3840 i::Heap::AddGCPrologueCallback(callback, gc_type);
3841}
3842
3843
3844void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
3845 if (IsDeadCheck("v8::V8::RemoveGCPrologueCallback()")) return;
3846 i::Heap::RemoveGCPrologueCallback(callback);
3847}
3848
3849
3850void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
3851 if (IsDeadCheck("v8::V8::AddGCEpilogueCallback()")) return;
3852 i::Heap::AddGCEpilogueCallback(callback, gc_type);
3853}
3854
3855
3856void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
3857 if (IsDeadCheck("v8::V8::RemoveGCEpilogueCallback()")) return;
3858 i::Heap::RemoveGCEpilogueCallback(callback);
3859}
3860
3861
Steve Blocka7e24c12009-10-30 11:49:00 +00003862void V8::PauseProfiler() {
3863#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003864 PauseProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003865#endif
3866}
3867
3868
3869void V8::ResumeProfiler() {
3870#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003871 ResumeProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003872#endif
3873}
3874
3875
3876bool V8::IsProfilerPaused() {
3877#ifdef ENABLE_LOGGING_AND_PROFILING
3878 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
3879#else
3880 return true;
3881#endif
3882}
3883
3884
Andrei Popescu402d9372010-02-26 13:31:12 +00003885void V8::ResumeProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003886#ifdef ENABLE_LOGGING_AND_PROFILING
3887 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
3888 // Snapshot mode: resume modules, perform GC, then pause only
3889 // those modules which haven't been started prior to making a
3890 // snapshot.
3891
Steve Block6ded16b2010-05-10 14:33:55 +01003892 // Make a GC prior to taking a snapshot.
3893 i::Heap::CollectAllGarbage(false);
Steve Blocka7e24c12009-10-30 11:49:00 +00003894 // Reset snapshot flag and CPU module flags.
3895 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
3896 const int current_flags = i::Logger::GetActiveProfilerModules();
Andrei Popescu402d9372010-02-26 13:31:12 +00003897 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003898 i::Heap::CollectAllGarbage(false);
Andrei Popescu402d9372010-02-26 13:31:12 +00003899 i::Logger::PauseProfiler(~current_flags & flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003900 } else {
Andrei Popescu402d9372010-02-26 13:31:12 +00003901 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003902 }
3903#endif
3904}
3905
3906
Andrei Popescu402d9372010-02-26 13:31:12 +00003907void V8::PauseProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003908#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003909 i::Logger::PauseProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003910#endif
3911}
3912
3913
3914int V8::GetActiveProfilerModules() {
3915#ifdef ENABLE_LOGGING_AND_PROFILING
3916 return i::Logger::GetActiveProfilerModules();
3917#else
3918 return PROFILER_MODULE_NONE;
3919#endif
3920}
3921
3922
3923int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
3924#ifdef ENABLE_LOGGING_AND_PROFILING
Steve Block6ded16b2010-05-10 14:33:55 +01003925 ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
Steve Blocka7e24c12009-10-30 11:49:00 +00003926 return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
3927#endif
3928 return 0;
3929}
3930
3931
3932int V8::GetCurrentThreadId() {
3933 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3934 EnsureInitialized("V8::GetCurrentThreadId()");
3935 return i::Top::thread_id();
3936}
3937
3938
3939void V8::TerminateExecution(int thread_id) {
3940 if (!i::V8::IsRunning()) return;
3941 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3942 // If the thread_id identifies the current thread just terminate
3943 // execution right away. Otherwise, ask the thread manager to
3944 // terminate the thread with the given id if any.
3945 if (thread_id == i::Top::thread_id()) {
3946 i::StackGuard::TerminateExecution();
3947 } else {
3948 i::ThreadManager::TerminateExecution(thread_id);
3949 }
3950}
3951
3952
3953void V8::TerminateExecution() {
3954 if (!i::V8::IsRunning()) return;
3955 i::StackGuard::TerminateExecution();
3956}
3957
3958
Steve Block6ded16b2010-05-10 14:33:55 +01003959bool V8::IsExecutionTerminating() {
3960 if (!i::V8::IsRunning()) return false;
3961 if (i::Top::has_scheduled_exception()) {
3962 return i::Top::scheduled_exception() == i::Heap::termination_exception();
3963 }
3964 return false;
3965}
3966
3967
Steve Blocka7e24c12009-10-30 11:49:00 +00003968String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
3969 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
3970 if (obj.IsEmpty()) {
3971 str_ = NULL;
3972 length_ = 0;
3973 return;
3974 }
3975 ENTER_V8;
3976 HandleScope scope;
3977 TryCatch try_catch;
3978 Handle<String> str = obj->ToString();
3979 if (str.IsEmpty()) {
3980 str_ = NULL;
3981 length_ = 0;
3982 } else {
3983 length_ = str->Utf8Length();
3984 str_ = i::NewArray<char>(length_ + 1);
3985 str->WriteUtf8(str_);
3986 }
3987}
3988
3989
3990String::Utf8Value::~Utf8Value() {
3991 i::DeleteArray(str_);
3992}
3993
3994
3995String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
3996 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
3997 if (obj.IsEmpty()) {
3998 str_ = NULL;
3999 length_ = 0;
4000 return;
4001 }
4002 ENTER_V8;
4003 HandleScope scope;
4004 TryCatch try_catch;
4005 Handle<String> str = obj->ToString();
4006 if (str.IsEmpty()) {
4007 str_ = NULL;
4008 length_ = 0;
4009 } else {
4010 length_ = str->Length();
4011 str_ = i::NewArray<char>(length_ + 1);
4012 str->WriteAscii(str_);
4013 }
4014}
4015
4016
4017String::AsciiValue::~AsciiValue() {
4018 i::DeleteArray(str_);
4019}
4020
4021
4022String::Value::Value(v8::Handle<v8::Value> obj) {
4023 EnsureInitialized("v8::String::Value::Value()");
4024 if (obj.IsEmpty()) {
4025 str_ = NULL;
4026 length_ = 0;
4027 return;
4028 }
4029 ENTER_V8;
4030 HandleScope scope;
4031 TryCatch try_catch;
4032 Handle<String> str = obj->ToString();
4033 if (str.IsEmpty()) {
4034 str_ = NULL;
4035 length_ = 0;
4036 } else {
4037 length_ = str->Length();
4038 str_ = i::NewArray<uint16_t>(length_ + 1);
4039 str->Write(str_);
4040 }
4041}
4042
4043
4044String::Value::~Value() {
4045 i::DeleteArray(str_);
4046}
4047
4048Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
4049 LOG_API("RangeError");
4050 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
4051 ENTER_V8;
4052 i::Object* error;
4053 {
4054 HandleScope scope;
4055 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4056 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
4057 error = *result;
4058 }
4059 i::Handle<i::Object> result(error);
4060 return Utils::ToLocal(result);
4061}
4062
4063Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
4064 LOG_API("ReferenceError");
4065 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
4066 ENTER_V8;
4067 i::Object* error;
4068 {
4069 HandleScope scope;
4070 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4071 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
4072 error = *result;
4073 }
4074 i::Handle<i::Object> result(error);
4075 return Utils::ToLocal(result);
4076}
4077
4078Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
4079 LOG_API("SyntaxError");
4080 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
4081 ENTER_V8;
4082 i::Object* error;
4083 {
4084 HandleScope scope;
4085 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4086 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
4087 error = *result;
4088 }
4089 i::Handle<i::Object> result(error);
4090 return Utils::ToLocal(result);
4091}
4092
4093Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
4094 LOG_API("TypeError");
4095 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
4096 ENTER_V8;
4097 i::Object* error;
4098 {
4099 HandleScope scope;
4100 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4101 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
4102 error = *result;
4103 }
4104 i::Handle<i::Object> result(error);
4105 return Utils::ToLocal(result);
4106}
4107
4108Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
4109 LOG_API("Error");
4110 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
4111 ENTER_V8;
4112 i::Object* error;
4113 {
4114 HandleScope scope;
4115 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4116 i::Handle<i::Object> result = i::Factory::NewError(message);
4117 error = *result;
4118 }
4119 i::Handle<i::Object> result(error);
4120 return Utils::ToLocal(result);
4121}
4122
4123
4124// --- D e b u g S u p p o r t ---
4125
4126#ifdef ENABLE_DEBUGGER_SUPPORT
Leon Clarkef7060e22010-06-03 12:02:55 +01004127
4128static v8::Debug::EventCallback event_callback = NULL;
4129
4130static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) {
4131 if (event_callback) {
4132 event_callback(event_details.GetEvent(),
4133 event_details.GetExecutionState(),
4134 event_details.GetEventData(),
4135 event_details.GetCallbackData());
4136 }
4137}
4138
4139
Steve Blocka7e24c12009-10-30 11:49:00 +00004140bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
4141 EnsureInitialized("v8::Debug::SetDebugEventListener()");
4142 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4143 ENTER_V8;
Leon Clarkef7060e22010-06-03 12:02:55 +01004144
4145 event_callback = that;
4146
4147 HandleScope scope;
4148 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4149 if (that != NULL) {
4150 proxy = i::Factory::NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
4151 }
4152 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4153 return true;
4154}
4155
4156
4157bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
4158 EnsureInitialized("v8::Debug::SetDebugEventListener2()");
4159 ON_BAILOUT("v8::Debug::SetDebugEventListener2()", return false);
4160 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004161 HandleScope scope;
4162 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4163 if (that != NULL) {
4164 proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
4165 }
4166 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4167 return true;
4168}
4169
4170
4171bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
4172 Handle<Value> data) {
4173 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4174 ENTER_V8;
4175 i::Debugger::SetEventListener(Utils::OpenHandle(*that),
4176 Utils::OpenHandle(*data));
4177 return true;
4178}
4179
4180
4181void Debug::DebugBreak() {
4182 if (!i::V8::IsRunning()) return;
4183 i::StackGuard::DebugBreak();
4184}
4185
4186
4187static v8::Debug::MessageHandler message_handler = NULL;
4188
4189static void MessageHandlerWrapper(const v8::Debug::Message& message) {
4190 if (message_handler) {
4191 v8::String::Value json(message.GetJSON());
4192 message_handler(*json, json.length(), message.GetClientData());
4193 }
4194}
4195
4196
4197void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
4198 bool message_handler_thread) {
4199 EnsureInitialized("v8::Debug::SetMessageHandler");
4200 ENTER_V8;
4201 // Message handler thread not supported any more. Parameter temporally left in
4202 // the API for client compatability reasons.
4203 CHECK(!message_handler_thread);
4204
4205 // TODO(sgjesse) support the old message handler API through a simple wrapper.
4206 message_handler = handler;
4207 if (message_handler != NULL) {
4208 i::Debugger::SetMessageHandler(MessageHandlerWrapper);
4209 } else {
4210 i::Debugger::SetMessageHandler(NULL);
4211 }
4212}
4213
4214
4215void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
4216 EnsureInitialized("v8::Debug::SetMessageHandler");
4217 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004218 i::Debugger::SetMessageHandler(handler);
4219}
4220
4221
4222void Debug::SendCommand(const uint16_t* command, int length,
4223 ClientData* client_data) {
4224 if (!i::V8::IsRunning()) return;
4225 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
4226 client_data);
4227}
4228
4229
4230void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
4231 int period) {
4232 EnsureInitialized("v8::Debug::SetHostDispatchHandler");
4233 ENTER_V8;
4234 i::Debugger::SetHostDispatchHandler(handler, period);
4235}
4236
4237
Steve Blockd0582a62009-12-15 09:54:21 +00004238void Debug::SetDebugMessageDispatchHandler(
Leon Clarkee46be812010-01-19 14:06:41 +00004239 DebugMessageDispatchHandler handler, bool provide_locker) {
Steve Blockd0582a62009-12-15 09:54:21 +00004240 EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
4241 ENTER_V8;
Leon Clarkee46be812010-01-19 14:06:41 +00004242 i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
Steve Blockd0582a62009-12-15 09:54:21 +00004243}
4244
4245
Steve Blocka7e24c12009-10-30 11:49:00 +00004246Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
4247 v8::Handle<v8::Value> data) {
4248 if (!i::V8::IsRunning()) return Local<Value>();
4249 ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
4250 ENTER_V8;
4251 i::Handle<i::Object> result;
4252 EXCEPTION_PREAMBLE();
4253 if (data.IsEmpty()) {
4254 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4255 i::Factory::undefined_value(),
4256 &has_pending_exception);
4257 } else {
4258 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4259 Utils::OpenHandle(*data),
4260 &has_pending_exception);
4261 }
4262 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4263 return Utils::ToLocal(result);
4264}
4265
4266
4267Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
4268 if (!i::V8::IsRunning()) return Local<Value>();
4269 ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
4270 ENTER_V8;
4271 v8::HandleScope scope;
4272 i::Debug::Load();
4273 i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
4274 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
4275 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
4276 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
4277 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
4278 const int kArgc = 1;
4279 v8::Handle<v8::Value> argv[kArgc] = { obj };
4280 EXCEPTION_PREAMBLE();
4281 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
4282 kArgc,
4283 argv);
4284 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4285 return scope.Close(result);
4286}
4287
4288
Leon Clarkee46be812010-01-19 14:06:41 +00004289bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
4290 return i::Debugger::StartAgent(name, port, wait_for_connection);
Steve Blocka7e24c12009-10-30 11:49:00 +00004291}
Leon Clarkee46be812010-01-19 14:06:41 +00004292
4293void Debug::ProcessDebugMessages() {
4294 i::Execution::ProcessDebugMesssages(true);
4295}
4296
Steve Block6ded16b2010-05-10 14:33:55 +01004297Local<Context> Debug::GetDebugContext() {
4298 EnsureInitialized("v8::Debug::GetDebugContext()");
4299 ENTER_V8;
4300 return Utils::ToLocal(i::Debugger::GetDebugContext());
4301}
4302
Steve Blocka7e24c12009-10-30 11:49:00 +00004303#endif // ENABLE_DEBUGGER_SUPPORT
4304
Steve Block6ded16b2010-05-10 14:33:55 +01004305
4306#ifdef ENABLE_LOGGING_AND_PROFILING
4307
4308Handle<String> CpuProfileNode::GetFunctionName() const {
4309 IsDeadCheck("v8::CpuProfileNode::GetFunctionName");
4310 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4311 const i::CodeEntry* entry = node->entry();
4312 if (!entry->has_name_prefix()) {
4313 return Handle<String>(ToApi<String>(
4314 i::Factory::LookupAsciiSymbol(entry->name())));
4315 } else {
4316 return Handle<String>(ToApi<String>(i::Factory::NewConsString(
4317 i::Factory::LookupAsciiSymbol(entry->name_prefix()),
4318 i::Factory::LookupAsciiSymbol(entry->name()))));
4319 }
4320}
4321
4322
4323Handle<String> CpuProfileNode::GetScriptResourceName() const {
4324 IsDeadCheck("v8::CpuProfileNode::GetScriptResourceName");
4325 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4326 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4327 node->entry()->resource_name())));
4328}
4329
4330
4331int CpuProfileNode::GetLineNumber() const {
4332 IsDeadCheck("v8::CpuProfileNode::GetLineNumber");
4333 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
4334}
4335
4336
4337double CpuProfileNode::GetTotalTime() const {
4338 IsDeadCheck("v8::CpuProfileNode::GetTotalTime");
4339 return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis();
4340}
4341
4342
4343double CpuProfileNode::GetSelfTime() const {
4344 IsDeadCheck("v8::CpuProfileNode::GetSelfTime");
4345 return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis();
4346}
4347
4348
4349double CpuProfileNode::GetTotalSamplesCount() const {
4350 IsDeadCheck("v8::CpuProfileNode::GetTotalSamplesCount");
4351 return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
4352}
4353
4354
4355double CpuProfileNode::GetSelfSamplesCount() const {
4356 IsDeadCheck("v8::CpuProfileNode::GetSelfSamplesCount");
4357 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
4358}
4359
4360
4361unsigned CpuProfileNode::GetCallUid() const {
4362 IsDeadCheck("v8::CpuProfileNode::GetCallUid");
4363 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->call_uid();
4364}
4365
4366
4367int CpuProfileNode::GetChildrenCount() const {
4368 IsDeadCheck("v8::CpuProfileNode::GetChildrenCount");
4369 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
4370}
4371
4372
4373const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
4374 IsDeadCheck("v8::CpuProfileNode::GetChild");
4375 const i::ProfileNode* child =
4376 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
4377 return reinterpret_cast<const CpuProfileNode*>(child);
4378}
4379
4380
4381unsigned CpuProfile::GetUid() const {
4382 IsDeadCheck("v8::CpuProfile::GetUid");
4383 return reinterpret_cast<const i::CpuProfile*>(this)->uid();
4384}
4385
4386
4387Handle<String> CpuProfile::GetTitle() const {
4388 IsDeadCheck("v8::CpuProfile::GetTitle");
4389 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4390 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4391 profile->title())));
4392}
4393
4394
4395const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
4396 IsDeadCheck("v8::CpuProfile::GetBottomUpRoot");
4397 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4398 return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
4399}
4400
4401
4402const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
4403 IsDeadCheck("v8::CpuProfile::GetTopDownRoot");
4404 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4405 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
4406}
4407
4408
4409int CpuProfiler::GetProfilesCount() {
4410 IsDeadCheck("v8::CpuProfiler::GetProfilesCount");
4411 return i::CpuProfiler::GetProfilesCount();
4412}
4413
4414
Leon Clarkef7060e22010-06-03 12:02:55 +01004415const CpuProfile* CpuProfiler::GetProfile(int index,
4416 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004417 IsDeadCheck("v8::CpuProfiler::GetProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004418 return reinterpret_cast<const CpuProfile*>(
4419 i::CpuProfiler::GetProfile(
4420 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4421 index));
Steve Block6ded16b2010-05-10 14:33:55 +01004422}
4423
4424
Leon Clarkef7060e22010-06-03 12:02:55 +01004425const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
4426 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004427 IsDeadCheck("v8::CpuProfiler::FindProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004428 return reinterpret_cast<const CpuProfile*>(
4429 i::CpuProfiler::FindProfile(
4430 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4431 uid));
Steve Block6ded16b2010-05-10 14:33:55 +01004432}
4433
4434
4435void CpuProfiler::StartProfiling(Handle<String> title) {
4436 IsDeadCheck("v8::CpuProfiler::StartProfiling");
4437 i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
4438}
4439
4440
Leon Clarkef7060e22010-06-03 12:02:55 +01004441const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
4442 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004443 IsDeadCheck("v8::CpuProfiler::StopProfiling");
4444 return reinterpret_cast<const CpuProfile*>(
Leon Clarkef7060e22010-06-03 12:02:55 +01004445 i::CpuProfiler::StopProfiling(
4446 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4447 *Utils::OpenHandle(*title)));
Steve Block6ded16b2010-05-10 14:33:55 +01004448}
4449
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004450
4451HeapGraphEdge::Type HeapGraphEdge::GetType() const {
4452 IsDeadCheck("v8::HeapGraphEdge::GetType");
4453 return static_cast<HeapGraphEdge::Type>(
4454 reinterpret_cast<const i::HeapGraphEdge*>(this)->type());
4455}
4456
4457
4458Handle<Value> HeapGraphEdge::GetName() const {
4459 IsDeadCheck("v8::HeapGraphEdge::GetName");
4460 const i::HeapGraphEdge* edge =
4461 reinterpret_cast<const i::HeapGraphEdge*>(this);
4462 switch (edge->type()) {
4463 case i::HeapGraphEdge::CONTEXT_VARIABLE:
4464 case i::HeapGraphEdge::INTERNAL:
4465 case i::HeapGraphEdge::PROPERTY:
4466 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4467 edge->name())));
4468 case i::HeapGraphEdge::ELEMENT:
4469 return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt(
4470 edge->index())));
4471 default: UNREACHABLE();
4472 }
4473 return ImplementationUtilities::Undefined();
4474}
4475
4476
4477const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
4478 IsDeadCheck("v8::HeapGraphEdge::GetFromNode");
4479 const i::HeapEntry* from =
4480 reinterpret_cast<const i::HeapGraphEdge*>(this)->from();
4481 return reinterpret_cast<const HeapGraphNode*>(from);
4482}
4483
4484
4485const HeapGraphNode* HeapGraphEdge::GetToNode() const {
4486 IsDeadCheck("v8::HeapGraphEdge::GetToNode");
4487 const i::HeapEntry* to =
4488 reinterpret_cast<const i::HeapGraphEdge*>(this)->to();
4489 return reinterpret_cast<const HeapGraphNode*>(to);
4490}
4491
4492
4493int HeapGraphPath::GetEdgesCount() const {
4494 return reinterpret_cast<const i::HeapGraphPath*>(this)->path()->length();
4495}
4496
4497
4498const HeapGraphEdge* HeapGraphPath::GetEdge(int index) const {
4499 return reinterpret_cast<const HeapGraphEdge*>(
4500 reinterpret_cast<const i::HeapGraphPath*>(this)->path()->at(index));
4501}
4502
4503
4504const HeapGraphNode* HeapGraphPath::GetFromNode() const {
4505 return GetEdgesCount() > 0 ? GetEdge(0)->GetFromNode() : NULL;
4506}
4507
4508
4509const HeapGraphNode* HeapGraphPath::GetToNode() const {
4510 const int count = GetEdgesCount();
4511 return count > 0 ? GetEdge(count - 1)->GetToNode() : NULL;
4512}
4513
4514
4515HeapGraphNode::Type HeapGraphNode::GetType() const {
4516 IsDeadCheck("v8::HeapGraphNode::GetType");
4517 return static_cast<HeapGraphNode::Type>(
4518 reinterpret_cast<const i::HeapEntry*>(this)->type());
4519}
4520
4521
4522Handle<String> HeapGraphNode::GetName() const {
4523 IsDeadCheck("v8::HeapGraphNode::GetName");
4524 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4525 reinterpret_cast<const i::HeapEntry*>(this)->name())));
4526}
4527
4528
4529int HeapGraphNode::GetSelfSize() const {
4530 IsDeadCheck("v8::HeapGraphNode::GetSelfSize");
4531 return reinterpret_cast<const i::HeapEntry*>(this)->self_size();
4532}
4533
4534
4535int HeapGraphNode::GetTotalSize() const {
4536 IsDeadCheck("v8::HeapSnapshot::GetHead");
4537 return const_cast<i::HeapEntry*>(
4538 reinterpret_cast<const i::HeapEntry*>(this))->TotalSize();
4539}
4540
4541
4542int HeapGraphNode::GetPrivateSize() const {
4543 IsDeadCheck("v8::HeapSnapshot::GetPrivateSize");
4544 return const_cast<i::HeapEntry*>(
4545 reinterpret_cast<const i::HeapEntry*>(this))->NonSharedTotalSize();
4546}
4547
4548
4549int HeapGraphNode::GetChildrenCount() const {
4550 IsDeadCheck("v8::HeapSnapshot::GetChildrenCount");
4551 return reinterpret_cast<const i::HeapEntry*>(this)->children()->length();
4552}
4553
4554
4555const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
4556 IsDeadCheck("v8::HeapSnapshot::GetChild");
4557 return reinterpret_cast<const HeapGraphEdge*>(
4558 reinterpret_cast<const i::HeapEntry*>(this)->children()->at(index));
4559}
4560
4561
4562int HeapGraphNode::GetRetainersCount() const {
4563 IsDeadCheck("v8::HeapSnapshot::GetRetainersCount");
4564 return reinterpret_cast<const i::HeapEntry*>(this)->retainers()->length();
4565}
4566
4567
4568const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const {
4569 IsDeadCheck("v8::HeapSnapshot::GetRetainer");
4570 return reinterpret_cast<const HeapGraphEdge*>(
4571 reinterpret_cast<const i::HeapEntry*>(this)->retainers()->at(index));
4572}
4573
4574
4575int HeapGraphNode::GetRetainingPathsCount() const {
4576 IsDeadCheck("v8::HeapSnapshot::GetRetainingPathsCount");
4577 return const_cast<i::HeapEntry*>(
4578 reinterpret_cast<const i::HeapEntry*>(
4579 this))->GetRetainingPaths()->length();
4580}
4581
4582
4583const HeapGraphPath* HeapGraphNode::GetRetainingPath(int index) const {
4584 IsDeadCheck("v8::HeapSnapshot::GetRetainingPath");
4585 return reinterpret_cast<const HeapGraphPath*>(
4586 const_cast<i::HeapEntry*>(
4587 reinterpret_cast<const i::HeapEntry*>(
4588 this))->GetRetainingPaths()->at(index));
4589}
4590
4591
4592unsigned HeapSnapshot::GetUid() const {
4593 IsDeadCheck("v8::HeapSnapshot::GetUid");
4594 return reinterpret_cast<const i::HeapSnapshot*>(this)->uid();
4595}
4596
4597
4598Handle<String> HeapSnapshot::GetTitle() const {
4599 IsDeadCheck("v8::HeapSnapshot::GetTitle");
4600 const i::HeapSnapshot* snapshot =
4601 reinterpret_cast<const i::HeapSnapshot*>(this);
4602 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4603 snapshot->title())));
4604}
4605
4606
4607const HeapGraphNode* HeapSnapshot::GetHead() const {
4608 IsDeadCheck("v8::HeapSnapshot::GetHead");
4609 const i::HeapSnapshot* snapshot =
4610 reinterpret_cast<const i::HeapSnapshot*>(this);
4611 return reinterpret_cast<const HeapGraphNode*>(snapshot->const_root());
4612}
4613
4614
4615int HeapProfiler::GetSnapshotsCount() {
4616 IsDeadCheck("v8::HeapProfiler::GetSnapshotsCount");
4617 return i::HeapProfiler::GetSnapshotsCount();
4618}
4619
4620
4621const HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
4622 IsDeadCheck("v8::HeapProfiler::GetSnapshot");
4623 return reinterpret_cast<const HeapSnapshot*>(
4624 i::HeapProfiler::GetSnapshot(index));
4625}
4626
4627
4628const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
4629 IsDeadCheck("v8::HeapProfiler::FindSnapshot");
4630 return reinterpret_cast<const HeapSnapshot*>(
4631 i::HeapProfiler::FindSnapshot(uid));
4632}
4633
4634
4635const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title) {
4636 IsDeadCheck("v8::HeapProfiler::TakeSnapshot");
4637 return reinterpret_cast<const HeapSnapshot*>(
4638 i::HeapProfiler::TakeSnapshot(*Utils::OpenHandle(*title)));
4639}
4640
Steve Block6ded16b2010-05-10 14:33:55 +01004641#endif // ENABLE_LOGGING_AND_PROFILING
4642
4643
Steve Blocka7e24c12009-10-30 11:49:00 +00004644namespace internal {
4645
4646
4647HandleScopeImplementer* HandleScopeImplementer::instance() {
4648 return &thread_local;
4649}
4650
4651
4652void HandleScopeImplementer::FreeThreadResources() {
4653 thread_local.Free();
4654}
4655
4656
4657char* HandleScopeImplementer::ArchiveThread(char* storage) {
4658 return thread_local.ArchiveThreadHelper(storage);
4659}
4660
4661
4662char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
4663 v8::ImplementationUtilities::HandleScopeData* current =
4664 v8::ImplementationUtilities::CurrentHandleScope();
4665 handle_scope_data_ = *current;
4666 memcpy(storage, this, sizeof(*this));
4667
4668 ResetAfterArchive();
4669 current->Initialize();
4670
4671 return storage + ArchiveSpacePerThread();
4672}
4673
4674
4675int HandleScopeImplementer::ArchiveSpacePerThread() {
4676 return sizeof(thread_local);
4677}
4678
4679
4680char* HandleScopeImplementer::RestoreThread(char* storage) {
4681 return thread_local.RestoreThreadHelper(storage);
4682}
4683
4684
4685char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
4686 memcpy(this, storage, sizeof(*this));
4687 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
4688 return storage + ArchiveSpacePerThread();
4689}
4690
4691
4692void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
4693 // Iterate over all handles in the blocks except for the last.
4694 for (int i = blocks()->length() - 2; i >= 0; --i) {
4695 Object** block = blocks()->at(i);
4696 v->VisitPointers(block, &block[kHandleBlockSize]);
4697 }
4698
4699 // Iterate over live handles in the last block (if any).
4700 if (!blocks()->is_empty()) {
4701 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
4702 }
4703
4704 if (!saved_contexts_.is_empty()) {
4705 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
4706 v->VisitPointers(start, start + saved_contexts_.length());
4707 }
4708}
4709
4710
4711void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
4712 v8::ImplementationUtilities::HandleScopeData* current =
4713 v8::ImplementationUtilities::CurrentHandleScope();
4714 thread_local.handle_scope_data_ = *current;
4715 thread_local.IterateThis(v);
4716}
4717
4718
4719char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
4720 HandleScopeImplementer* thread_local =
4721 reinterpret_cast<HandleScopeImplementer*>(storage);
4722 thread_local->IterateThis(v);
4723 return storage + ArchiveSpacePerThread();
4724}
4725
4726} } // namespace v8::internal