blob: 0d01fcc75e2a9e14c506acb82533027e956b1534 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2009 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "api.h"
31#include "arguments.h"
32#include "bootstrapper.h"
33#include "compiler.h"
34#include "debug.h"
35#include "execution.h"
36#include "global-handles.h"
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010037#include "heap-profiler.h"
Steve Block6ded16b2010-05-10 14:33:55 +010038#include "messages.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000039#include "platform.h"
Steve Block6ded16b2010-05-10 14:33:55 +010040#include "profile-generator-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000041#include "serialize.h"
42#include "snapshot.h"
Steve Block6ded16b2010-05-10 14:33:55 +010043#include "top.h"
Steve Blockd0582a62009-12-15 09:54:21 +000044#include "utils.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000045#include "v8threads.h"
46#include "version.h"
47
Steve Block6ded16b2010-05-10 14:33:55 +010048#include "../include/v8-profiler.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000049
50#define LOG_API(expr) LOG(ApiEntryCall(expr))
51
Leon Clarkef7060e22010-06-03 12:02:55 +010052#ifdef ENABLE_VMSTATE_TRACKING
Steve Blocka7e24c12009-10-30 11:49:00 +000053#define ENTER_V8 i::VMState __state__(i::OTHER)
54#define LEAVE_V8 i::VMState __state__(i::EXTERNAL)
55#else
56#define ENTER_V8 ((void) 0)
57#define LEAVE_V8 ((void) 0)
58#endif
59
60namespace v8 {
61
Leon Clarkef7060e22010-06-03 12:02:55 +010062#define ON_BAILOUT(location, code) \
63 if (IsDeadCheck(location) || v8::V8::IsExecutionTerminating()) { \
64 code; \
65 UNREACHABLE(); \
Steve Blocka7e24c12009-10-30 11:49:00 +000066 }
67
68
69#define EXCEPTION_PREAMBLE() \
70 thread_local.IncrementCallDepth(); \
71 ASSERT(!i::Top::external_caught_exception()); \
72 bool has_pending_exception = false
73
74
75#define EXCEPTION_BAILOUT_CHECK(value) \
76 do { \
77 thread_local.DecrementCallDepth(); \
78 if (has_pending_exception) { \
79 if (thread_local.CallDepthIsZero() && i::Top::is_out_of_memory()) { \
80 if (!thread_local.ignore_out_of_memory()) \
81 i::V8::FatalProcessOutOfMemory(NULL); \
82 } \
83 bool call_depth_is_zero = thread_local.CallDepthIsZero(); \
84 i::Top::OptionalRescheduleException(call_depth_is_zero); \
85 return value; \
86 } \
87 } while (false)
88
89
90#define API_ENTRY_CHECK(msg) \
91 do { \
92 if (v8::Locker::IsActive()) { \
93 ApiCheck(i::ThreadManager::IsLockedByCurrentThread(), \
94 msg, \
95 "Entering the V8 API without proper locking in place"); \
96 } \
97 } while (false)
98
99// --- D a t a t h a t i s s p e c i f i c t o a t h r e a d ---
100
101
102static i::HandleScopeImplementer thread_local;
103
104
105// --- E x c e p t i o n B e h a v i o r ---
106
107
108static FatalErrorCallback exception_behavior = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000109
110static void DefaultFatalErrorHandler(const char* location,
111 const char* message) {
112 ENTER_V8;
113 API_Fatal(location, message);
114}
115
116
117
118static FatalErrorCallback& GetFatalErrorHandler() {
119 if (exception_behavior == NULL) {
120 exception_behavior = DefaultFatalErrorHandler;
121 }
122 return exception_behavior;
123}
124
125
126
127// When V8 cannot allocated memory FatalProcessOutOfMemory is called.
128// The default fatal error handler is called and execution is stopped.
Ben Murdochbb769b22010-08-11 14:56:33 +0100129void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
Steve Blockd0582a62009-12-15 09:54:21 +0000130 i::HeapStats heap_stats;
131 int start_marker;
132 heap_stats.start_marker = &start_marker;
133 int new_space_size;
134 heap_stats.new_space_size = &new_space_size;
135 int new_space_capacity;
136 heap_stats.new_space_capacity = &new_space_capacity;
137 int old_pointer_space_size;
138 heap_stats.old_pointer_space_size = &old_pointer_space_size;
139 int old_pointer_space_capacity;
140 heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
141 int old_data_space_size;
142 heap_stats.old_data_space_size = &old_data_space_size;
143 int old_data_space_capacity;
144 heap_stats.old_data_space_capacity = &old_data_space_capacity;
145 int code_space_size;
146 heap_stats.code_space_size = &code_space_size;
147 int code_space_capacity;
148 heap_stats.code_space_capacity = &code_space_capacity;
149 int map_space_size;
150 heap_stats.map_space_size = &map_space_size;
151 int map_space_capacity;
152 heap_stats.map_space_capacity = &map_space_capacity;
153 int cell_space_size;
154 heap_stats.cell_space_size = &cell_space_size;
155 int cell_space_capacity;
156 heap_stats.cell_space_capacity = &cell_space_capacity;
157 int lo_space_size;
158 heap_stats.lo_space_size = &lo_space_size;
159 int global_handle_count;
160 heap_stats.global_handle_count = &global_handle_count;
161 int weak_global_handle_count;
162 heap_stats.weak_global_handle_count = &weak_global_handle_count;
163 int pending_global_handle_count;
164 heap_stats.pending_global_handle_count = &pending_global_handle_count;
165 int near_death_global_handle_count;
166 heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
167 int destroyed_global_handle_count;
168 heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count;
Ben Murdochbb769b22010-08-11 14:56:33 +0100169 int memory_allocator_size;
170 heap_stats.memory_allocator_size = &memory_allocator_size;
171 int memory_allocator_capacity;
172 heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
173 int objects_per_type[LAST_TYPE + 1] = {0};
174 heap_stats.objects_per_type = objects_per_type;
175 int size_per_type[LAST_TYPE + 1] = {0};
176 heap_stats.size_per_type = size_per_type;
Iain Merrick75681382010-08-19 15:07:18 +0100177 int os_error;
178 heap_stats.os_error = &os_error;
Steve Blockd0582a62009-12-15 09:54:21 +0000179 int end_marker;
180 heap_stats.end_marker = &end_marker;
Ben Murdochbb769b22010-08-11 14:56:33 +0100181 i::Heap::RecordStats(&heap_stats, take_snapshot);
Steve Blocka7e24c12009-10-30 11:49:00 +0000182 i::V8::SetFatalError();
183 FatalErrorCallback callback = GetFatalErrorHandler();
184 {
185 LEAVE_V8;
186 callback(location, "Allocation failed - process out of memory");
187 }
188 // If the callback returns, we stop execution.
189 UNREACHABLE();
190}
191
192
193void V8::SetFatalErrorHandler(FatalErrorCallback that) {
194 exception_behavior = that;
195}
196
197
198bool Utils::ReportApiFailure(const char* location, const char* message) {
199 FatalErrorCallback callback = GetFatalErrorHandler();
200 callback(location, message);
201 i::V8::SetFatalError();
202 return false;
203}
204
205
206bool V8::IsDead() {
207 return i::V8::IsDead();
208}
209
210
211static inline bool ApiCheck(bool condition,
212 const char* location,
213 const char* message) {
214 return condition ? true : Utils::ReportApiFailure(location, message);
215}
216
217
218static bool ReportV8Dead(const char* location) {
219 FatalErrorCallback callback = GetFatalErrorHandler();
220 callback(location, "V8 is no longer usable");
221 return true;
222}
223
224
225static bool ReportEmptyHandle(const char* location) {
226 FatalErrorCallback callback = GetFatalErrorHandler();
227 callback(location, "Reading from empty handle");
228 return true;
229}
230
231
232/**
233 * IsDeadCheck checks that the vm is usable. If, for instance, the vm has been
234 * out of memory at some point this check will fail. It should be called on
235 * entry to all methods that touch anything in the heap, except destructors
236 * which you sometimes can't avoid calling after the vm has crashed. Functions
237 * that call EnsureInitialized or ON_BAILOUT don't have to also call
238 * IsDeadCheck. ON_BAILOUT has the advantage over EnsureInitialized that you
239 * can arrange to return if the VM is dead. This is needed to ensure that no VM
240 * heap allocations are attempted on a dead VM. EnsureInitialized has the
241 * advantage over ON_BAILOUT that it actually initializes the VM if this has not
242 * yet been done.
243 */
244static inline bool IsDeadCheck(const char* location) {
245 return !i::V8::IsRunning()
246 && i::V8::IsDead() ? ReportV8Dead(location) : false;
247}
248
249
250static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
251 return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
252}
253
254
255static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
256 return (obj == 0) ? ReportEmptyHandle(location) : false;
257}
258
259// --- S t a t i c s ---
260
261
262static i::StringInputBuffer write_input_buffer;
263
264
265static inline bool EnsureInitialized(const char* location) {
266 if (i::V8::IsRunning()) {
267 return true;
268 }
269 if (IsDeadCheck(location)) {
270 return false;
271 }
272 return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
273}
274
275
276ImplementationUtilities::HandleScopeData*
277 ImplementationUtilities::CurrentHandleScope() {
278 return &i::HandleScope::current_;
279}
280
281
282#ifdef DEBUG
283void ImplementationUtilities::ZapHandleRange(i::Object** begin,
284 i::Object** end) {
285 i::HandleScope::ZapRange(begin, end);
286}
287#endif
288
289
290v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
291 if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
292 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
293}
294
295
296v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
297 if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
298 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
299}
300
301
302v8::Handle<v8::Boolean> ImplementationUtilities::True() {
303 if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
304 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
305}
306
307
308v8::Handle<v8::Boolean> ImplementationUtilities::False() {
309 if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
310 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
311}
312
313
314void V8::SetFlagsFromString(const char* str, int length) {
315 i::FlagList::SetFlagsFromString(str, length);
316}
317
318
319void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
320 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
321}
322
323
324v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
325 if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
326 ENTER_V8;
327 // If we're passed an empty handle, we throw an undefined exception
328 // to deal more gracefully with out of memory situations.
329 if (value.IsEmpty()) {
330 i::Top::ScheduleThrow(i::Heap::undefined_value());
331 } else {
332 i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
333 }
334 return v8::Undefined();
335}
336
337
338RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
339
340
341RegisteredExtension::RegisteredExtension(Extension* extension)
342 : extension_(extension), state_(UNVISITED) { }
343
344
345void RegisteredExtension::Register(RegisteredExtension* that) {
346 that->next_ = RegisteredExtension::first_extension_;
347 RegisteredExtension::first_extension_ = that;
348}
349
350
351void RegisterExtension(Extension* that) {
352 RegisteredExtension* extension = new RegisteredExtension(that);
353 RegisteredExtension::Register(extension);
354}
355
356
357Extension::Extension(const char* name,
358 const char* source,
359 int dep_count,
360 const char** deps)
361 : name_(name),
362 source_(source),
363 dep_count_(dep_count),
364 deps_(deps),
365 auto_enable_(false) { }
366
367
368v8::Handle<Primitive> Undefined() {
369 LOG_API("Undefined");
370 return ImplementationUtilities::Undefined();
371}
372
373
374v8::Handle<Primitive> Null() {
375 LOG_API("Null");
376 return ImplementationUtilities::Null();
377}
378
379
380v8::Handle<Boolean> True() {
381 LOG_API("True");
382 return ImplementationUtilities::True();
383}
384
385
386v8::Handle<Boolean> False() {
387 LOG_API("False");
388 return ImplementationUtilities::False();
389}
390
391
392ResourceConstraints::ResourceConstraints()
393 : max_young_space_size_(0),
394 max_old_space_size_(0),
395 stack_limit_(NULL) { }
396
397
398bool SetResourceConstraints(ResourceConstraints* constraints) {
Steve Block3ce2e202009-11-05 08:53:23 +0000399 int young_space_size = constraints->max_young_space_size();
Steve Blocka7e24c12009-10-30 11:49:00 +0000400 int old_gen_size = constraints->max_old_space_size();
Steve Block3ce2e202009-11-05 08:53:23 +0000401 if (young_space_size != 0 || old_gen_size != 0) {
402 bool result = i::Heap::ConfigureHeap(young_space_size / 2, old_gen_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000403 if (!result) return false;
404 }
405 if (constraints->stack_limit() != NULL) {
406 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
407 i::StackGuard::SetStackLimit(limit);
408 }
409 return true;
410}
411
412
413i::Object** V8::GlobalizeReference(i::Object** obj) {
414 if (IsDeadCheck("V8::Persistent::New")) return NULL;
415 LOG_API("Persistent::New");
416 i::Handle<i::Object> result =
417 i::GlobalHandles::Create(*obj);
418 return result.location();
419}
420
421
422void V8::MakeWeak(i::Object** object, void* parameters,
423 WeakReferenceCallback callback) {
424 LOG_API("MakeWeak");
425 i::GlobalHandles::MakeWeak(object, parameters, callback);
426}
427
428
429void V8::ClearWeak(i::Object** obj) {
430 LOG_API("ClearWeak");
431 i::GlobalHandles::ClearWeakness(obj);
432}
433
434
435bool V8::IsGlobalNearDeath(i::Object** obj) {
436 LOG_API("IsGlobalNearDeath");
437 if (!i::V8::IsRunning()) return false;
438 return i::GlobalHandles::IsNearDeath(obj);
439}
440
441
442bool V8::IsGlobalWeak(i::Object** obj) {
443 LOG_API("IsGlobalWeak");
444 if (!i::V8::IsRunning()) return false;
445 return i::GlobalHandles::IsWeak(obj);
446}
447
448
449void V8::DisposeGlobal(i::Object** obj) {
450 LOG_API("DisposeGlobal");
451 if (!i::V8::IsRunning()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000452 i::GlobalHandles::Destroy(obj);
453}
454
455// --- H a n d l e s ---
456
457
458HandleScope::HandleScope() : is_closed_(false) {
459 API_ENTRY_CHECK("HandleScope::HandleScope");
460 i::HandleScope::Enter(&previous_);
461}
462
463
464HandleScope::~HandleScope() {
465 if (!is_closed_) {
466 i::HandleScope::Leave(&previous_);
467 }
468}
469
470
471int HandleScope::NumberOfHandles() {
472 return i::HandleScope::NumberOfHandles();
473}
474
475
476i::Object** v8::HandleScope::CreateHandle(i::Object* value) {
477 return i::HandleScope::CreateHandle(value);
478}
479
480
481void Context::Enter() {
482 if (IsDeadCheck("v8::Context::Enter()")) return;
483 ENTER_V8;
484 i::Handle<i::Context> env = Utils::OpenHandle(this);
485 thread_local.EnterContext(env);
486
487 thread_local.SaveContext(i::Top::context());
488 i::Top::set_context(*env);
489}
490
491
492void Context::Exit() {
493 if (!i::V8::IsRunning()) return;
494 if (!ApiCheck(thread_local.LeaveLastContext(),
495 "v8::Context::Exit()",
496 "Cannot exit non-entered context")) {
497 return;
498 }
499
500 // Content of 'last_context' could be NULL.
501 i::Context* last_context = thread_local.RestoreContext();
502 i::Top::set_context(last_context);
503}
504
505
Steve Blockd0582a62009-12-15 09:54:21 +0000506void Context::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000507 if (IsDeadCheck("v8::Context::SetData()")) return;
508 ENTER_V8;
509 {
510 HandleScope scope;
511 i::Handle<i::Context> env = Utils::OpenHandle(this);
512 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
513 ASSERT(env->IsGlobalContext());
514 if (env->IsGlobalContext()) {
515 env->set_data(*raw_data);
516 }
517 }
518}
519
520
521v8::Local<v8::Value> Context::GetData() {
522 if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
523 ENTER_V8;
524 i::Object* raw_result = NULL;
525 {
526 HandleScope scope;
527 i::Handle<i::Context> env = Utils::OpenHandle(this);
528 ASSERT(env->IsGlobalContext());
529 if (env->IsGlobalContext()) {
530 raw_result = env->data();
531 } else {
532 return Local<Value>();
533 }
534 }
535 i::Handle<i::Object> result(raw_result);
536 return Utils::ToLocal(result);
537}
538
539
540i::Object** v8::HandleScope::RawClose(i::Object** value) {
541 if (!ApiCheck(!is_closed_,
542 "v8::HandleScope::Close()",
543 "Local scope has already been closed")) {
544 return 0;
545 }
546 LOG_API("CloseHandleScope");
547
548 // Read the result before popping the handle block.
Steve Block6ded16b2010-05-10 14:33:55 +0100549 i::Object* result = NULL;
550 if (value != NULL) {
551 result = *value;
552 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000553 is_closed_ = true;
554 i::HandleScope::Leave(&previous_);
555
Steve Block6ded16b2010-05-10 14:33:55 +0100556 if (value == NULL) {
557 return NULL;
558 }
559
Steve Blocka7e24c12009-10-30 11:49:00 +0000560 // Allocate a new handle on the previous handle block.
561 i::Handle<i::Object> handle(result);
562 return handle.location();
563}
564
565
566// --- N e a n d e r ---
567
568
569// A constructor cannot easily return an error value, therefore it is necessary
570// to check for a dead VM with ON_BAILOUT before constructing any Neander
571// objects. To remind you about this there is no HandleScope in the
572// NeanderObject constructor. When you add one to the site calling the
573// constructor you should check that you ensured the VM was not dead first.
574NeanderObject::NeanderObject(int size) {
575 EnsureInitialized("v8::Nowhere");
576 ENTER_V8;
577 value_ = i::Factory::NewNeanderObject();
578 i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
579 value_->set_elements(*elements);
580}
581
582
583int NeanderObject::size() {
584 return i::FixedArray::cast(value_->elements())->length();
585}
586
587
588NeanderArray::NeanderArray() : obj_(2) {
589 obj_.set(0, i::Smi::FromInt(0));
590}
591
592
593int NeanderArray::length() {
594 return i::Smi::cast(obj_.get(0))->value();
595}
596
597
598i::Object* NeanderArray::get(int offset) {
599 ASSERT(0 <= offset);
600 ASSERT(offset < length());
601 return obj_.get(offset + 1);
602}
603
604
605// This method cannot easily return an error value, therefore it is necessary
606// to check for a dead VM with ON_BAILOUT before calling it. To remind you
607// about this there is no HandleScope in this method. When you add one to the
608// site calling this method you should check that you ensured the VM was not
609// dead first.
610void NeanderArray::add(i::Handle<i::Object> value) {
611 int length = this->length();
612 int size = obj_.size();
613 if (length == size - 1) {
614 i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
615 for (int i = 0; i < length; i++)
616 new_elms->set(i + 1, get(i));
617 obj_.value()->set_elements(*new_elms);
618 }
619 obj_.set(length + 1, *value);
620 obj_.set(0, i::Smi::FromInt(length + 1));
621}
622
623
624void NeanderArray::set(int index, i::Object* value) {
625 if (index < 0 || index >= this->length()) return;
626 obj_.set(index + 1, value);
627}
628
629
630// --- T e m p l a t e ---
631
632
633static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
634 that->set_tag(i::Smi::FromInt(type));
635}
636
637
638void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
639 v8::PropertyAttribute attribute) {
640 if (IsDeadCheck("v8::Template::SetProperty()")) return;
641 ENTER_V8;
642 HandleScope scope;
643 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
644 if (list->IsUndefined()) {
645 list = NeanderArray().value();
646 Utils::OpenHandle(this)->set_property_list(*list);
647 }
648 NeanderArray array(list);
649 array.add(Utils::OpenHandle(*name));
650 array.add(Utils::OpenHandle(*value));
651 array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
652}
653
654
655// --- F u n c t i o n T e m p l a t e ---
656static void InitializeFunctionTemplate(
657 i::Handle<i::FunctionTemplateInfo> info) {
658 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
659 info->set_flag(0);
660}
661
662
663Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
664 if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
665 return Local<ObjectTemplate>();
666 }
667 ENTER_V8;
668 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
669 if (result->IsUndefined()) {
670 result = Utils::OpenHandle(*ObjectTemplate::New());
671 Utils::OpenHandle(this)->set_prototype_template(*result);
672 }
673 return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
674}
675
676
677void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
678 if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
679 ENTER_V8;
680 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
681}
682
683
684// To distinguish the function templates, so that we can find them in the
685// function cache of the global context.
686static int next_serial_number = 0;
687
688
689Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
690 v8::Handle<Value> data, v8::Handle<Signature> signature) {
691 EnsureInitialized("v8::FunctionTemplate::New()");
692 LOG_API("FunctionTemplate::New");
693 ENTER_V8;
694 i::Handle<i::Struct> struct_obj =
695 i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
696 i::Handle<i::FunctionTemplateInfo> obj =
697 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
698 InitializeFunctionTemplate(obj);
699 obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
700 if (callback != 0) {
701 if (data.IsEmpty()) data = v8::Undefined();
702 Utils::ToLocal(obj)->SetCallHandler(callback, data);
703 }
704 obj->set_undetectable(false);
705 obj->set_needs_access_check(false);
706
707 if (!signature.IsEmpty())
708 obj->set_signature(*Utils::OpenHandle(*signature));
709 return Utils::ToLocal(obj);
710}
711
712
713Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
714 int argc, Handle<FunctionTemplate> argv[]) {
715 EnsureInitialized("v8::Signature::New()");
716 LOG_API("Signature::New");
717 ENTER_V8;
718 i::Handle<i::Struct> struct_obj =
719 i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
720 i::Handle<i::SignatureInfo> obj =
721 i::Handle<i::SignatureInfo>::cast(struct_obj);
722 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
723 if (argc > 0) {
724 i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
725 for (int i = 0; i < argc; i++) {
726 if (!argv[i].IsEmpty())
727 args->set(i, *Utils::OpenHandle(*argv[i]));
728 }
729 obj->set_args(*args);
730 }
731 return Utils::ToLocal(obj);
732}
733
734
735Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
736 Handle<FunctionTemplate> types[1] = { type };
737 return TypeSwitch::New(1, types);
738}
739
740
741Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
742 EnsureInitialized("v8::TypeSwitch::New()");
743 LOG_API("TypeSwitch::New");
744 ENTER_V8;
745 i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
746 for (int i = 0; i < argc; i++)
747 vector->set(i, *Utils::OpenHandle(*types[i]));
748 i::Handle<i::Struct> struct_obj =
749 i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
750 i::Handle<i::TypeSwitchInfo> obj =
751 i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
752 obj->set_types(*vector);
753 return Utils::ToLocal(obj);
754}
755
756
757int TypeSwitch::match(v8::Handle<Value> value) {
758 LOG_API("TypeSwitch::match");
759 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
760 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
761 i::FixedArray* types = i::FixedArray::cast(info->types());
762 for (int i = 0; i < types->length(); i++) {
763 if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
764 return i + 1;
765 }
766 return 0;
767}
768
769
770void FunctionTemplate::SetCallHandler(InvocationCallback callback,
771 v8::Handle<Value> data) {
772 if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
773 ENTER_V8;
774 HandleScope scope;
775 i::Handle<i::Struct> struct_obj =
776 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
777 i::Handle<i::CallHandlerInfo> obj =
778 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
779 obj->set_callback(*FromCData(callback));
780 if (data.IsEmpty()) data = v8::Undefined();
781 obj->set_data(*Utils::OpenHandle(*data));
782 Utils::OpenHandle(this)->set_call_code(*obj);
783}
784
785
Leon Clarkef7060e22010-06-03 12:02:55 +0100786static i::Handle<i::AccessorInfo> MakeAccessorInfo(
787 v8::Handle<String> name,
788 AccessorGetter getter,
789 AccessorSetter setter,
790 v8::Handle<Value> data,
791 v8::AccessControl settings,
792 v8::PropertyAttribute attributes) {
793 i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
794 ASSERT(getter != NULL);
795 obj->set_getter(*FromCData(getter));
796 obj->set_setter(*FromCData(setter));
797 if (data.IsEmpty()) data = v8::Undefined();
798 obj->set_data(*Utils::OpenHandle(*data));
799 obj->set_name(*Utils::OpenHandle(*name));
800 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
801 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
802 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
803 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
804 return obj;
805}
806
807
Steve Blocka7e24c12009-10-30 11:49:00 +0000808void FunctionTemplate::AddInstancePropertyAccessor(
809 v8::Handle<String> name,
810 AccessorGetter getter,
811 AccessorSetter setter,
812 v8::Handle<Value> data,
813 v8::AccessControl settings,
814 v8::PropertyAttribute attributes) {
815 if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
816 return;
817 }
818 ENTER_V8;
819 HandleScope scope;
Steve Blocka7e24c12009-10-30 11:49:00 +0000820
Leon Clarkef7060e22010-06-03 12:02:55 +0100821 i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name,
822 getter, setter, data,
823 settings, attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000824 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
825 if (list->IsUndefined()) {
826 list = NeanderArray().value();
827 Utils::OpenHandle(this)->set_property_accessors(*list);
828 }
829 NeanderArray array(list);
830 array.add(obj);
831}
832
833
834Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
835 if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
836 || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
837 return Local<ObjectTemplate>();
838 ENTER_V8;
839 if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
840 Local<ObjectTemplate> templ =
841 ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
842 Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
843 }
844 i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
845 Utils::OpenHandle(this)->instance_template()));
846 return Utils::ToLocal(result);
847}
848
849
850void FunctionTemplate::SetClassName(Handle<String> name) {
851 if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
852 ENTER_V8;
853 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
854}
855
856
857void FunctionTemplate::SetHiddenPrototype(bool value) {
858 if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
859 ENTER_V8;
860 Utils::OpenHandle(this)->set_hidden_prototype(value);
861}
862
863
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100864void FunctionTemplate::SetNamedInstancePropertyHandler(
Steve Blocka7e24c12009-10-30 11:49:00 +0000865 NamedPropertyGetter getter,
866 NamedPropertySetter setter,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100867 NamedPropertyQuery query,
Steve Blocka7e24c12009-10-30 11:49:00 +0000868 NamedPropertyDeleter remover,
869 NamedPropertyEnumerator enumerator,
870 Handle<Value> data) {
871 if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
872 return;
873 }
874 ENTER_V8;
875 HandleScope scope;
876 i::Handle<i::Struct> struct_obj =
877 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
878 i::Handle<i::InterceptorInfo> obj =
879 i::Handle<i::InterceptorInfo>::cast(struct_obj);
880 if (getter != 0) obj->set_getter(*FromCData(getter));
881 if (setter != 0) obj->set_setter(*FromCData(setter));
882 if (query != 0) obj->set_query(*FromCData(query));
883 if (remover != 0) obj->set_deleter(*FromCData(remover));
884 if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
885 if (data.IsEmpty()) data = v8::Undefined();
886 obj->set_data(*Utils::OpenHandle(*data));
887 Utils::OpenHandle(this)->set_named_property_handler(*obj);
888}
889
890
891void FunctionTemplate::SetIndexedInstancePropertyHandler(
892 IndexedPropertyGetter getter,
893 IndexedPropertySetter setter,
894 IndexedPropertyQuery query,
895 IndexedPropertyDeleter remover,
896 IndexedPropertyEnumerator enumerator,
897 Handle<Value> data) {
898 if (IsDeadCheck(
899 "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
900 return;
901 }
902 ENTER_V8;
903 HandleScope scope;
904 i::Handle<i::Struct> struct_obj =
905 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
906 i::Handle<i::InterceptorInfo> obj =
907 i::Handle<i::InterceptorInfo>::cast(struct_obj);
908 if (getter != 0) obj->set_getter(*FromCData(getter));
909 if (setter != 0) obj->set_setter(*FromCData(setter));
910 if (query != 0) obj->set_query(*FromCData(query));
911 if (remover != 0) obj->set_deleter(*FromCData(remover));
912 if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
913 if (data.IsEmpty()) data = v8::Undefined();
914 obj->set_data(*Utils::OpenHandle(*data));
915 Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
916}
917
918
919void FunctionTemplate::SetInstanceCallAsFunctionHandler(
920 InvocationCallback callback,
921 Handle<Value> data) {
922 if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
923 return;
924 }
925 ENTER_V8;
926 HandleScope scope;
927 i::Handle<i::Struct> struct_obj =
928 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
929 i::Handle<i::CallHandlerInfo> obj =
930 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
931 obj->set_callback(*FromCData(callback));
932 if (data.IsEmpty()) data = v8::Undefined();
933 obj->set_data(*Utils::OpenHandle(*data));
934 Utils::OpenHandle(this)->set_instance_call_handler(*obj);
935}
936
937
938// --- O b j e c t T e m p l a t e ---
939
940
941Local<ObjectTemplate> ObjectTemplate::New() {
942 return New(Local<FunctionTemplate>());
943}
944
945
946Local<ObjectTemplate> ObjectTemplate::New(
947 v8::Handle<FunctionTemplate> constructor) {
948 if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
949 EnsureInitialized("v8::ObjectTemplate::New()");
950 LOG_API("ObjectTemplate::New");
951 ENTER_V8;
952 i::Handle<i::Struct> struct_obj =
953 i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
954 i::Handle<i::ObjectTemplateInfo> obj =
955 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
956 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
957 if (!constructor.IsEmpty())
958 obj->set_constructor(*Utils::OpenHandle(*constructor));
959 obj->set_internal_field_count(i::Smi::FromInt(0));
960 return Utils::ToLocal(obj);
961}
962
963
964// Ensure that the object template has a constructor. If no
965// constructor is available we create one.
966static void EnsureConstructor(ObjectTemplate* object_template) {
967 if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
968 Local<FunctionTemplate> templ = FunctionTemplate::New();
969 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
970 constructor->set_instance_template(*Utils::OpenHandle(object_template));
971 Utils::OpenHandle(object_template)->set_constructor(*constructor);
972 }
973}
974
975
976void ObjectTemplate::SetAccessor(v8::Handle<String> name,
977 AccessorGetter getter,
978 AccessorSetter setter,
979 v8::Handle<Value> data,
980 AccessControl settings,
981 PropertyAttribute attribute) {
982 if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
983 ENTER_V8;
984 HandleScope scope;
985 EnsureConstructor(this);
986 i::FunctionTemplateInfo* constructor =
987 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
988 i::Handle<i::FunctionTemplateInfo> cons(constructor);
989 Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
990 getter,
991 setter,
992 data,
993 settings,
994 attribute);
995}
996
997
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100998void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
999 NamedPropertySetter setter,
1000 NamedPropertyQuery query,
1001 NamedPropertyDeleter remover,
1002 NamedPropertyEnumerator enumerator,
1003 Handle<Value> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001004 if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
1005 ENTER_V8;
1006 HandleScope scope;
1007 EnsureConstructor(this);
1008 i::FunctionTemplateInfo* constructor =
1009 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1010 i::Handle<i::FunctionTemplateInfo> cons(constructor);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001011 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
1012 setter,
1013 query,
1014 remover,
1015 enumerator,
1016 data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001017}
1018
1019
1020void ObjectTemplate::MarkAsUndetectable() {
1021 if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
1022 ENTER_V8;
1023 HandleScope scope;
1024 EnsureConstructor(this);
1025 i::FunctionTemplateInfo* constructor =
1026 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1027 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1028 cons->set_undetectable(true);
1029}
1030
1031
1032void ObjectTemplate::SetAccessCheckCallbacks(
1033 NamedSecurityCallback named_callback,
1034 IndexedSecurityCallback indexed_callback,
1035 Handle<Value> data,
1036 bool turned_on_by_default) {
1037 if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
1038 ENTER_V8;
1039 HandleScope scope;
1040 EnsureConstructor(this);
1041
1042 i::Handle<i::Struct> struct_info =
1043 i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1044 i::Handle<i::AccessCheckInfo> info =
1045 i::Handle<i::AccessCheckInfo>::cast(struct_info);
1046 info->set_named_callback(*FromCData(named_callback));
1047 info->set_indexed_callback(*FromCData(indexed_callback));
1048 if (data.IsEmpty()) data = v8::Undefined();
1049 info->set_data(*Utils::OpenHandle(*data));
1050
1051 i::FunctionTemplateInfo* constructor =
1052 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1053 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1054 cons->set_access_check_info(*info);
1055 cons->set_needs_access_check(turned_on_by_default);
1056}
1057
1058
1059void ObjectTemplate::SetIndexedPropertyHandler(
1060 IndexedPropertyGetter getter,
1061 IndexedPropertySetter setter,
1062 IndexedPropertyQuery query,
1063 IndexedPropertyDeleter remover,
1064 IndexedPropertyEnumerator enumerator,
1065 Handle<Value> data) {
1066 if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
1067 ENTER_V8;
1068 HandleScope scope;
1069 EnsureConstructor(this);
1070 i::FunctionTemplateInfo* constructor =
1071 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1072 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1073 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
1074 setter,
1075 query,
1076 remover,
1077 enumerator,
1078 data);
1079}
1080
1081
1082void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1083 Handle<Value> data) {
1084 if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
1085 ENTER_V8;
1086 HandleScope scope;
1087 EnsureConstructor(this);
1088 i::FunctionTemplateInfo* constructor =
1089 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1090 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1091 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1092}
1093
1094
1095int ObjectTemplate::InternalFieldCount() {
1096 if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
1097 return 0;
1098 }
1099 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1100}
1101
1102
1103void ObjectTemplate::SetInternalFieldCount(int value) {
1104 if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
1105 if (!ApiCheck(i::Smi::IsValid(value),
1106 "v8::ObjectTemplate::SetInternalFieldCount()",
1107 "Invalid internal field count")) {
1108 return;
1109 }
1110 ENTER_V8;
1111 if (value > 0) {
1112 // The internal field count is set by the constructor function's
1113 // construct code, so we ensure that there is a constructor
1114 // function to do the setting.
1115 EnsureConstructor(this);
1116 }
1117 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1118}
1119
1120
1121// --- S c r i p t D a t a ---
1122
1123
1124ScriptData* ScriptData::PreCompile(const char* input, int length) {
1125 unibrow::Utf8InputBuffer<> buf(input, length);
1126 return i::PreParse(i::Handle<i::String>(), &buf, NULL);
1127}
1128
1129
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001130ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
1131 i::Handle<i::String> str = Utils::OpenHandle(*source);
1132 return i::PreParse(str, NULL, NULL);
1133}
1134
1135
Leon Clarkef7060e22010-06-03 12:02:55 +01001136ScriptData* ScriptData::New(const char* data, int length) {
1137 // Return an empty ScriptData if the length is obviously invalid.
1138 if (length % sizeof(unsigned) != 0) {
Iain Merrick9ac36c92010-09-13 15:29:50 +01001139 return new i::ScriptDataImpl();
Leon Clarkef7060e22010-06-03 12:02:55 +01001140 }
1141
1142 // Copy the data to ensure it is properly aligned.
1143 int deserialized_data_length = length / sizeof(unsigned);
Iain Merrick9ac36c92010-09-13 15:29:50 +01001144 // If aligned, don't create a copy of the data.
1145 if (reinterpret_cast<intptr_t>(data) % sizeof(unsigned) == 0) {
1146 return new i::ScriptDataImpl(data, length);
1147 }
1148 // Copy the data to align it.
Leon Clarkef7060e22010-06-03 12:02:55 +01001149 unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
Iain Merrick9ac36c92010-09-13 15:29:50 +01001150 i::MemCopy(deserialized_data, data, length);
Leon Clarkef7060e22010-06-03 12:02:55 +01001151
1152 return new i::ScriptDataImpl(
1153 i::Vector<unsigned>(deserialized_data, deserialized_data_length));
Steve Blocka7e24c12009-10-30 11:49:00 +00001154}
1155
1156
1157// --- S c r i p t ---
1158
1159
1160Local<Script> Script::New(v8::Handle<String> source,
1161 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001162 v8::ScriptData* pre_data,
1163 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001164 ON_BAILOUT("v8::Script::New()", return Local<Script>());
1165 LOG_API("Script::New");
1166 ENTER_V8;
1167 i::Handle<i::String> str = Utils::OpenHandle(*source);
1168 i::Handle<i::Object> name_obj;
1169 int line_offset = 0;
1170 int column_offset = 0;
1171 if (origin != NULL) {
1172 if (!origin->ResourceName().IsEmpty()) {
1173 name_obj = Utils::OpenHandle(*origin->ResourceName());
1174 }
1175 if (!origin->ResourceLineOffset().IsEmpty()) {
1176 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1177 }
1178 if (!origin->ResourceColumnOffset().IsEmpty()) {
1179 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1180 }
1181 }
1182 EXCEPTION_PREAMBLE();
Andrei Popescu402d9372010-02-26 13:31:12 +00001183 i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001184 // We assert that the pre-data is sane, even though we can actually
1185 // handle it if it turns out not to be in release mode.
Andrei Popescu402d9372010-02-26 13:31:12 +00001186 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
Steve Blocka7e24c12009-10-30 11:49:00 +00001187 // If the pre-data isn't sane we simply ignore it
Andrei Popescu402d9372010-02-26 13:31:12 +00001188 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
1189 pre_data_impl = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001190 }
Steve Block6ded16b2010-05-10 14:33:55 +01001191 i::Handle<i::SharedFunctionInfo> result =
Andrei Popescu31002712010-02-23 13:46:05 +00001192 i::Compiler::Compile(str,
1193 name_obj,
1194 line_offset,
1195 column_offset,
1196 NULL,
Andrei Popescu402d9372010-02-26 13:31:12 +00001197 pre_data_impl,
1198 Utils::OpenHandle(*script_data),
Andrei Popescu31002712010-02-23 13:46:05 +00001199 i::NOT_NATIVES_CODE);
Steve Block6ded16b2010-05-10 14:33:55 +01001200 has_pending_exception = result.is_null();
Steve Blocka7e24c12009-10-30 11:49:00 +00001201 EXCEPTION_BAILOUT_CHECK(Local<Script>());
Steve Block6ded16b2010-05-10 14:33:55 +01001202 return Local<Script>(ToApi<Script>(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00001203}
1204
1205
1206Local<Script> Script::New(v8::Handle<String> source,
1207 v8::Handle<Value> file_name) {
1208 ScriptOrigin origin(file_name);
1209 return New(source, &origin);
1210}
1211
1212
1213Local<Script> Script::Compile(v8::Handle<String> source,
1214 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001215 v8::ScriptData* pre_data,
1216 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001217 ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1218 LOG_API("Script::Compile");
1219 ENTER_V8;
Andrei Popescu402d9372010-02-26 13:31:12 +00001220 Local<Script> generic = New(source, origin, pre_data, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001221 if (generic.IsEmpty())
1222 return generic;
Steve Block6ded16b2010-05-10 14:33:55 +01001223 i::Handle<i::Object> obj = Utils::OpenHandle(*generic);
1224 i::Handle<i::SharedFunctionInfo> function =
1225 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001226 i::Handle<i::JSFunction> result =
Steve Block6ded16b2010-05-10 14:33:55 +01001227 i::Factory::NewFunctionFromSharedFunctionInfo(function,
1228 i::Top::global_context());
Steve Blocka7e24c12009-10-30 11:49:00 +00001229 return Local<Script>(ToApi<Script>(result));
1230}
1231
1232
1233Local<Script> Script::Compile(v8::Handle<String> source,
Andrei Popescu402d9372010-02-26 13:31:12 +00001234 v8::Handle<Value> file_name,
1235 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001236 ScriptOrigin origin(file_name);
Andrei Popescu402d9372010-02-26 13:31:12 +00001237 return Compile(source, &origin, 0, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001238}
1239
1240
1241Local<Value> Script::Run() {
1242 ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1243 LOG_API("Script::Run");
1244 ENTER_V8;
1245 i::Object* raw_result = NULL;
1246 {
1247 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001248 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1249 i::Handle<i::JSFunction> fun;
1250 if (obj->IsSharedFunctionInfo()) {
1251 i::Handle<i::SharedFunctionInfo>
1252 function_info(i::SharedFunctionInfo::cast(*obj));
1253 fun = i::Factory::NewFunctionFromSharedFunctionInfo(
1254 function_info, i::Top::global_context());
1255 } else {
1256 fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001257 }
1258 EXCEPTION_PREAMBLE();
1259 i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
1260 i::Handle<i::Object> result =
1261 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
1262 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1263 raw_result = *result;
1264 }
1265 i::Handle<i::Object> result(raw_result);
1266 return Utils::ToLocal(result);
1267}
1268
1269
Steve Block6ded16b2010-05-10 14:33:55 +01001270static i::Handle<i::SharedFunctionInfo> OpenScript(Script* script) {
1271 i::Handle<i::Object> obj = Utils::OpenHandle(script);
1272 i::Handle<i::SharedFunctionInfo> result;
1273 if (obj->IsSharedFunctionInfo()) {
1274 result =
1275 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
1276 } else {
1277 result =
1278 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared());
1279 }
1280 return result;
1281}
1282
1283
Steve Blocka7e24c12009-10-30 11:49:00 +00001284Local<Value> Script::Id() {
1285 ON_BAILOUT("v8::Script::Id()", return Local<Value>());
1286 LOG_API("Script::Id");
1287 i::Object* raw_id = NULL;
1288 {
1289 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001290 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1291 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001292 i::Handle<i::Object> id(script->id());
1293 raw_id = *id;
1294 }
1295 i::Handle<i::Object> id(raw_id);
1296 return Utils::ToLocal(id);
1297}
1298
1299
Steve Blockd0582a62009-12-15 09:54:21 +00001300void Script::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001301 ON_BAILOUT("v8::Script::SetData()", return);
1302 LOG_API("Script::SetData");
1303 {
1304 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001305 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001306 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
Steve Block6ded16b2010-05-10 14:33:55 +01001307 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001308 script->set_data(*raw_data);
1309 }
1310}
1311
1312
1313// --- E x c e p t i o n s ---
1314
1315
1316v8::TryCatch::TryCatch()
Steve Blockd0582a62009-12-15 09:54:21 +00001317 : next_(i::Top::try_catch_handler_address()),
Steve Blocka7e24c12009-10-30 11:49:00 +00001318 exception_(i::Heap::the_hole_value()),
1319 message_(i::Smi::FromInt(0)),
1320 is_verbose_(false),
1321 can_continue_(true),
1322 capture_message_(true),
Steve Blockd0582a62009-12-15 09:54:21 +00001323 rethrow_(false) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001324 i::Top::RegisterTryCatchHandler(this);
1325}
1326
1327
1328v8::TryCatch::~TryCatch() {
Steve Blockd0582a62009-12-15 09:54:21 +00001329 if (rethrow_) {
1330 v8::HandleScope scope;
1331 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
1332 i::Top::UnregisterTryCatchHandler(this);
1333 v8::ThrowException(exc);
1334 } else {
1335 i::Top::UnregisterTryCatchHandler(this);
1336 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001337}
1338
1339
1340bool v8::TryCatch::HasCaught() const {
1341 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1342}
1343
1344
1345bool v8::TryCatch::CanContinue() const {
1346 return can_continue_;
1347}
1348
1349
Steve Blockd0582a62009-12-15 09:54:21 +00001350v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1351 if (!HasCaught()) return v8::Local<v8::Value>();
1352 rethrow_ = true;
1353 return v8::Undefined();
1354}
1355
1356
Steve Blocka7e24c12009-10-30 11:49:00 +00001357v8::Local<Value> v8::TryCatch::Exception() const {
1358 if (HasCaught()) {
1359 // Check for out of memory exception.
1360 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1361 return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1362 } else {
1363 return v8::Local<Value>();
1364 }
1365}
1366
1367
1368v8::Local<Value> v8::TryCatch::StackTrace() const {
1369 if (HasCaught()) {
1370 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1371 if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1372 v8::HandleScope scope;
1373 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
1374 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
1375 if (!obj->HasProperty(*name))
1376 return v8::Local<Value>();
1377 return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
1378 } else {
1379 return v8::Local<Value>();
1380 }
1381}
1382
1383
1384v8::Local<v8::Message> v8::TryCatch::Message() const {
1385 if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1386 i::Object* message = reinterpret_cast<i::Object*>(message_);
1387 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1388 } else {
1389 return v8::Local<v8::Message>();
1390 }
1391}
1392
1393
1394void v8::TryCatch::Reset() {
1395 exception_ = i::Heap::the_hole_value();
1396 message_ = i::Smi::FromInt(0);
1397}
1398
1399
1400void v8::TryCatch::SetVerbose(bool value) {
1401 is_verbose_ = value;
1402}
1403
1404
1405void v8::TryCatch::SetCaptureMessage(bool value) {
1406 capture_message_ = value;
1407}
1408
1409
1410// --- M e s s a g e ---
1411
1412
1413Local<String> Message::Get() const {
1414 ON_BAILOUT("v8::Message::Get()", return Local<String>());
1415 ENTER_V8;
1416 HandleScope scope;
1417 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1418 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1419 Local<String> result = Utils::ToLocal(raw_result);
1420 return scope.Close(result);
1421}
1422
1423
1424v8::Handle<Value> Message::GetScriptResourceName() const {
1425 if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1426 return Local<String>();
1427 }
1428 ENTER_V8;
1429 HandleScope scope;
1430 i::Handle<i::JSObject> obj =
1431 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1432 // Return this.script.name.
1433 i::Handle<i::JSValue> script =
1434 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1435 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
1436 return scope.Close(Utils::ToLocal(resource_name));
1437}
1438
1439
1440v8::Handle<Value> Message::GetScriptData() const {
1441 if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
1442 return Local<Value>();
1443 }
1444 ENTER_V8;
1445 HandleScope scope;
1446 i::Handle<i::JSObject> obj =
1447 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1448 // Return this.script.data.
1449 i::Handle<i::JSValue> script =
1450 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1451 i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1452 return scope.Close(Utils::ToLocal(data));
1453}
1454
1455
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001456v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
1457 if (IsDeadCheck("v8::Message::GetStackTrace()")) {
1458 return Local<v8::StackTrace>();
1459 }
1460 ENTER_V8;
1461 HandleScope scope;
1462 i::Handle<i::JSObject> obj =
1463 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1464 i::Handle<i::Object> stackFramesObj = GetProperty(obj, "stackFrames");
1465 if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
1466 i::Handle<i::JSArray> stackTrace =
1467 i::Handle<i::JSArray>::cast(stackFramesObj);
1468 return scope.Close(Utils::StackTraceToLocal(stackTrace));
1469}
1470
1471
Steve Blocka7e24c12009-10-30 11:49:00 +00001472static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1473 i::Handle<i::Object> recv,
1474 int argc,
1475 i::Object** argv[],
1476 bool* has_pending_exception) {
1477 i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
1478 i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
1479 i::Handle<i::JSFunction> fun =
1480 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1481 i::Handle<i::Object> value =
1482 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1483 return value;
1484}
1485
1486
1487static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1488 i::Handle<i::Object> data,
1489 bool* has_pending_exception) {
1490 i::Object** argv[1] = { data.location() };
1491 return CallV8HeapFunction(name,
1492 i::Top::builtins(),
1493 1,
1494 argv,
1495 has_pending_exception);
1496}
1497
1498
1499int Message::GetLineNumber() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001500 ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001501 ENTER_V8;
1502 HandleScope scope;
1503 EXCEPTION_PREAMBLE();
1504 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1505 Utils::OpenHandle(this),
1506 &has_pending_exception);
1507 EXCEPTION_BAILOUT_CHECK(0);
1508 return static_cast<int>(result->Number());
1509}
1510
1511
1512int Message::GetStartPosition() const {
1513 if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1514 ENTER_V8;
1515 HandleScope scope;
1516
1517 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1518 return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1519}
1520
1521
1522int Message::GetEndPosition() const {
1523 if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1524 ENTER_V8;
1525 HandleScope scope;
1526 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1527 return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1528}
1529
1530
1531int Message::GetStartColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001532 if (IsDeadCheck("v8::Message::GetStartColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001533 ENTER_V8;
1534 HandleScope scope;
1535 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1536 EXCEPTION_PREAMBLE();
1537 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1538 "GetPositionInLine",
1539 data_obj,
1540 &has_pending_exception);
1541 EXCEPTION_BAILOUT_CHECK(0);
1542 return static_cast<int>(start_col_obj->Number());
1543}
1544
1545
1546int Message::GetEndColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001547 if (IsDeadCheck("v8::Message::GetEndColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001548 ENTER_V8;
1549 HandleScope scope;
1550 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1551 EXCEPTION_PREAMBLE();
1552 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1553 "GetPositionInLine",
1554 data_obj,
1555 &has_pending_exception);
1556 EXCEPTION_BAILOUT_CHECK(0);
1557 int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1558 int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1559 return static_cast<int>(start_col_obj->Number()) + (end - start);
1560}
1561
1562
1563Local<String> Message::GetSourceLine() const {
1564 ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
1565 ENTER_V8;
1566 HandleScope scope;
1567 EXCEPTION_PREAMBLE();
1568 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1569 Utils::OpenHandle(this),
1570 &has_pending_exception);
1571 EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1572 if (result->IsString()) {
1573 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1574 } else {
1575 return Local<String>();
1576 }
1577}
1578
1579
1580void Message::PrintCurrentStackTrace(FILE* out) {
1581 if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1582 ENTER_V8;
1583 i::Top::PrintCurrentStackTrace(out);
1584}
1585
1586
Kristian Monsen25f61362010-05-21 11:50:48 +01001587// --- S t a c k T r a c e ---
1588
1589Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
1590 if (IsDeadCheck("v8::StackTrace::GetFrame()")) return Local<StackFrame>();
1591 ENTER_V8;
1592 HandleScope scope;
1593 i::Handle<i::JSArray> self = Utils::OpenHandle(this);
1594 i::Handle<i::JSObject> obj(i::JSObject::cast(self->GetElement(index)));
1595 return scope.Close(Utils::StackFrameToLocal(obj));
1596}
1597
1598
1599int StackTrace::GetFrameCount() const {
1600 if (IsDeadCheck("v8::StackTrace::GetFrameCount()")) return -1;
1601 ENTER_V8;
1602 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
1603}
1604
1605
1606Local<Array> StackTrace::AsArray() {
1607 if (IsDeadCheck("v8::StackTrace::AsArray()")) Local<Array>();
1608 ENTER_V8;
1609 return Utils::ToLocal(Utils::OpenHandle(this));
1610}
1611
1612
1613Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
1614 StackTraceOptions options) {
1615 if (IsDeadCheck("v8::StackTrace::CurrentStackTrace()")) Local<StackTrace>();
1616 ENTER_V8;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001617 i::Handle<i::JSArray> stackTrace =
1618 i::Top::CaptureCurrentStackTrace(frame_limit, options);
1619 return Utils::StackTraceToLocal(stackTrace);
Kristian Monsen25f61362010-05-21 11:50:48 +01001620}
1621
1622
1623// --- S t a c k F r a m e ---
1624
1625int StackFrame::GetLineNumber() const {
1626 if (IsDeadCheck("v8::StackFrame::GetLineNumber()")) {
1627 return Message::kNoLineNumberInfo;
1628 }
1629 ENTER_V8;
1630 i::HandleScope scope;
1631 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1632 i::Handle<i::Object> line = GetProperty(self, "lineNumber");
1633 if (!line->IsSmi()) {
1634 return Message::kNoLineNumberInfo;
1635 }
1636 return i::Smi::cast(*line)->value();
1637}
1638
1639
1640int StackFrame::GetColumn() const {
1641 if (IsDeadCheck("v8::StackFrame::GetColumn()")) {
1642 return Message::kNoColumnInfo;
1643 }
1644 ENTER_V8;
1645 i::HandleScope scope;
1646 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1647 i::Handle<i::Object> column = GetProperty(self, "column");
1648 if (!column->IsSmi()) {
1649 return Message::kNoColumnInfo;
1650 }
1651 return i::Smi::cast(*column)->value();
1652}
1653
1654
1655Local<String> StackFrame::GetScriptName() const {
1656 if (IsDeadCheck("v8::StackFrame::GetScriptName()")) return Local<String>();
1657 ENTER_V8;
1658 HandleScope scope;
1659 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1660 i::Handle<i::Object> name = GetProperty(self, "scriptName");
1661 if (!name->IsString()) {
1662 return Local<String>();
1663 }
1664 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1665}
1666
1667
1668Local<String> StackFrame::GetFunctionName() const {
1669 if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
1670 ENTER_V8;
1671 HandleScope scope;
1672 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1673 i::Handle<i::Object> name = GetProperty(self, "functionName");
1674 if (!name->IsString()) {
1675 return Local<String>();
1676 }
1677 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1678}
1679
1680
1681bool StackFrame::IsEval() const {
1682 if (IsDeadCheck("v8::StackFrame::IsEval()")) return false;
1683 ENTER_V8;
1684 i::HandleScope scope;
1685 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1686 i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
1687 return is_eval->IsTrue();
1688}
1689
1690
1691bool StackFrame::IsConstructor() const {
1692 if (IsDeadCheck("v8::StackFrame::IsConstructor()")) return false;
1693 ENTER_V8;
1694 i::HandleScope scope;
1695 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1696 i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
1697 return is_constructor->IsTrue();
1698}
1699
1700
Steve Blocka7e24c12009-10-30 11:49:00 +00001701// --- D a t a ---
1702
1703bool Value::IsUndefined() const {
1704 if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1705 return Utils::OpenHandle(this)->IsUndefined();
1706}
1707
1708
1709bool Value::IsNull() const {
1710 if (IsDeadCheck("v8::Value::IsNull()")) return false;
1711 return Utils::OpenHandle(this)->IsNull();
1712}
1713
1714
1715bool Value::IsTrue() const {
1716 if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1717 return Utils::OpenHandle(this)->IsTrue();
1718}
1719
1720
1721bool Value::IsFalse() const {
1722 if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1723 return Utils::OpenHandle(this)->IsFalse();
1724}
1725
1726
1727bool Value::IsFunction() const {
1728 if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1729 return Utils::OpenHandle(this)->IsJSFunction();
1730}
1731
1732
1733bool Value::FullIsString() const {
1734 if (IsDeadCheck("v8::Value::IsString()")) return false;
1735 bool result = Utils::OpenHandle(this)->IsString();
1736 ASSERT_EQ(result, QuickIsString());
1737 return result;
1738}
1739
1740
1741bool Value::IsArray() const {
1742 if (IsDeadCheck("v8::Value::IsArray()")) return false;
1743 return Utils::OpenHandle(this)->IsJSArray();
1744}
1745
1746
1747bool Value::IsObject() const {
1748 if (IsDeadCheck("v8::Value::IsObject()")) return false;
1749 return Utils::OpenHandle(this)->IsJSObject();
1750}
1751
1752
1753bool Value::IsNumber() const {
1754 if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1755 return Utils::OpenHandle(this)->IsNumber();
1756}
1757
1758
1759bool Value::IsBoolean() const {
1760 if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1761 return Utils::OpenHandle(this)->IsBoolean();
1762}
1763
1764
1765bool Value::IsExternal() const {
1766 if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1767 return Utils::OpenHandle(this)->IsProxy();
1768}
1769
1770
1771bool Value::IsInt32() const {
1772 if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1773 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1774 if (obj->IsSmi()) return true;
1775 if (obj->IsNumber()) {
1776 double value = obj->Number();
1777 return i::FastI2D(i::FastD2I(value)) == value;
1778 }
1779 return false;
1780}
1781
1782
Steve Block6ded16b2010-05-10 14:33:55 +01001783bool Value::IsUint32() const {
1784 if (IsDeadCheck("v8::Value::IsUint32()")) return false;
1785 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1786 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
1787 if (obj->IsNumber()) {
1788 double value = obj->Number();
1789 return i::FastUI2D(i::FastD2UI(value)) == value;
1790 }
1791 return false;
1792}
1793
1794
Steve Blocka7e24c12009-10-30 11:49:00 +00001795bool Value::IsDate() const {
1796 if (IsDeadCheck("v8::Value::IsDate()")) return false;
1797 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1798 return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1799}
1800
1801
Iain Merrick75681382010-08-19 15:07:18 +01001802bool Value::IsRegExp() const {
1803 if (IsDeadCheck("v8::Value::IsRegExp()")) return false;
1804 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1805 return obj->IsJSRegExp();
1806}
1807
1808
Steve Blocka7e24c12009-10-30 11:49:00 +00001809Local<String> Value::ToString() const {
1810 if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1811 LOG_API("ToString");
1812 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1813 i::Handle<i::Object> str;
1814 if (obj->IsString()) {
1815 str = obj;
1816 } else {
1817 ENTER_V8;
1818 EXCEPTION_PREAMBLE();
1819 str = i::Execution::ToString(obj, &has_pending_exception);
1820 EXCEPTION_BAILOUT_CHECK(Local<String>());
1821 }
1822 return Local<String>(ToApi<String>(str));
1823}
1824
1825
1826Local<String> Value::ToDetailString() const {
1827 if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1828 LOG_API("ToDetailString");
1829 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1830 i::Handle<i::Object> str;
1831 if (obj->IsString()) {
1832 str = obj;
1833 } else {
1834 ENTER_V8;
1835 EXCEPTION_PREAMBLE();
1836 str = i::Execution::ToDetailString(obj, &has_pending_exception);
1837 EXCEPTION_BAILOUT_CHECK(Local<String>());
1838 }
1839 return Local<String>(ToApi<String>(str));
1840}
1841
1842
1843Local<v8::Object> Value::ToObject() const {
1844 if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1845 LOG_API("ToObject");
1846 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1847 i::Handle<i::Object> val;
1848 if (obj->IsJSObject()) {
1849 val = obj;
1850 } else {
1851 ENTER_V8;
1852 EXCEPTION_PREAMBLE();
1853 val = i::Execution::ToObject(obj, &has_pending_exception);
1854 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1855 }
1856 return Local<v8::Object>(ToApi<Object>(val));
1857}
1858
1859
1860Local<Boolean> Value::ToBoolean() const {
1861 if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1862 LOG_API("ToBoolean");
1863 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1864 if (obj->IsBoolean()) {
1865 return Local<Boolean>(ToApi<Boolean>(obj));
1866 } else {
1867 ENTER_V8;
1868 i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1869 return Local<Boolean>(ToApi<Boolean>(val));
1870 }
1871}
1872
1873
1874Local<Number> Value::ToNumber() const {
1875 if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1876 LOG_API("ToNumber");
1877 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1878 i::Handle<i::Object> num;
1879 if (obj->IsNumber()) {
1880 num = obj;
1881 } else {
1882 ENTER_V8;
1883 EXCEPTION_PREAMBLE();
1884 num = i::Execution::ToNumber(obj, &has_pending_exception);
1885 EXCEPTION_BAILOUT_CHECK(Local<Number>());
1886 }
1887 return Local<Number>(ToApi<Number>(num));
1888}
1889
1890
1891Local<Integer> Value::ToInteger() const {
1892 if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1893 LOG_API("ToInteger");
1894 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1895 i::Handle<i::Object> num;
1896 if (obj->IsSmi()) {
1897 num = obj;
1898 } else {
1899 ENTER_V8;
1900 EXCEPTION_PREAMBLE();
1901 num = i::Execution::ToInteger(obj, &has_pending_exception);
1902 EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1903 }
1904 return Local<Integer>(ToApi<Integer>(num));
1905}
1906
1907
1908void External::CheckCast(v8::Value* that) {
1909 if (IsDeadCheck("v8::External::Cast()")) return;
1910 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1911 ApiCheck(obj->IsProxy(),
1912 "v8::External::Cast()",
1913 "Could not convert to external");
1914}
1915
1916
1917void v8::Object::CheckCast(Value* that) {
1918 if (IsDeadCheck("v8::Object::Cast()")) return;
1919 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1920 ApiCheck(obj->IsJSObject(),
1921 "v8::Object::Cast()",
1922 "Could not convert to object");
1923}
1924
1925
1926void v8::Function::CheckCast(Value* that) {
1927 if (IsDeadCheck("v8::Function::Cast()")) return;
1928 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1929 ApiCheck(obj->IsJSFunction(),
1930 "v8::Function::Cast()",
1931 "Could not convert to function");
1932}
1933
1934
1935void v8::String::CheckCast(v8::Value* that) {
1936 if (IsDeadCheck("v8::String::Cast()")) return;
1937 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1938 ApiCheck(obj->IsString(),
1939 "v8::String::Cast()",
1940 "Could not convert to string");
1941}
1942
1943
1944void v8::Number::CheckCast(v8::Value* that) {
1945 if (IsDeadCheck("v8::Number::Cast()")) return;
1946 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1947 ApiCheck(obj->IsNumber(),
1948 "v8::Number::Cast()",
1949 "Could not convert to number");
1950}
1951
1952
1953void v8::Integer::CheckCast(v8::Value* that) {
1954 if (IsDeadCheck("v8::Integer::Cast()")) return;
1955 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1956 ApiCheck(obj->IsNumber(),
1957 "v8::Integer::Cast()",
1958 "Could not convert to number");
1959}
1960
1961
1962void v8::Array::CheckCast(Value* that) {
1963 if (IsDeadCheck("v8::Array::Cast()")) return;
1964 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1965 ApiCheck(obj->IsJSArray(),
1966 "v8::Array::Cast()",
1967 "Could not convert to array");
1968}
1969
1970
1971void v8::Date::CheckCast(v8::Value* that) {
1972 if (IsDeadCheck("v8::Date::Cast()")) return;
1973 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1974 ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
1975 "v8::Date::Cast()",
1976 "Could not convert to date");
1977}
1978
1979
1980bool Value::BooleanValue() const {
1981 if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
1982 LOG_API("BooleanValue");
1983 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1984 if (obj->IsBoolean()) {
1985 return obj->IsTrue();
1986 } else {
1987 ENTER_V8;
1988 i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
1989 return value->IsTrue();
1990 }
1991}
1992
1993
1994double Value::NumberValue() const {
1995 if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
1996 LOG_API("NumberValue");
1997 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1998 i::Handle<i::Object> num;
1999 if (obj->IsNumber()) {
2000 num = obj;
2001 } else {
2002 ENTER_V8;
2003 EXCEPTION_PREAMBLE();
2004 num = i::Execution::ToNumber(obj, &has_pending_exception);
2005 EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
2006 }
2007 return num->Number();
2008}
2009
2010
2011int64_t Value::IntegerValue() const {
2012 if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
2013 LOG_API("IntegerValue");
2014 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2015 i::Handle<i::Object> num;
2016 if (obj->IsNumber()) {
2017 num = obj;
2018 } else {
2019 ENTER_V8;
2020 EXCEPTION_PREAMBLE();
2021 num = i::Execution::ToInteger(obj, &has_pending_exception);
2022 EXCEPTION_BAILOUT_CHECK(0);
2023 }
2024 if (num->IsSmi()) {
2025 return i::Smi::cast(*num)->value();
2026 } else {
2027 return static_cast<int64_t>(num->Number());
2028 }
2029}
2030
2031
2032Local<Int32> Value::ToInt32() const {
2033 if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
2034 LOG_API("ToInt32");
2035 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2036 i::Handle<i::Object> num;
2037 if (obj->IsSmi()) {
2038 num = obj;
2039 } else {
2040 ENTER_V8;
2041 EXCEPTION_PREAMBLE();
2042 num = i::Execution::ToInt32(obj, &has_pending_exception);
2043 EXCEPTION_BAILOUT_CHECK(Local<Int32>());
2044 }
2045 return Local<Int32>(ToApi<Int32>(num));
2046}
2047
2048
2049Local<Uint32> Value::ToUint32() const {
2050 if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
2051 LOG_API("ToUInt32");
2052 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2053 i::Handle<i::Object> num;
2054 if (obj->IsSmi()) {
2055 num = obj;
2056 } else {
2057 ENTER_V8;
2058 EXCEPTION_PREAMBLE();
2059 num = i::Execution::ToUint32(obj, &has_pending_exception);
2060 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2061 }
2062 return Local<Uint32>(ToApi<Uint32>(num));
2063}
2064
2065
2066Local<Uint32> Value::ToArrayIndex() const {
2067 if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
2068 LOG_API("ToArrayIndex");
2069 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2070 if (obj->IsSmi()) {
2071 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2072 return Local<Uint32>();
2073 }
2074 ENTER_V8;
2075 EXCEPTION_PREAMBLE();
2076 i::Handle<i::Object> string_obj =
2077 i::Execution::ToString(obj, &has_pending_exception);
2078 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2079 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2080 uint32_t index;
2081 if (str->AsArrayIndex(&index)) {
2082 i::Handle<i::Object> value;
2083 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2084 value = i::Handle<i::Object>(i::Smi::FromInt(index));
2085 } else {
2086 value = i::Factory::NewNumber(index);
2087 }
2088 return Utils::Uint32ToLocal(value);
2089 }
2090 return Local<Uint32>();
2091}
2092
2093
2094int32_t Value::Int32Value() const {
2095 if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
2096 LOG_API("Int32Value");
2097 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2098 if (obj->IsSmi()) {
2099 return i::Smi::cast(*obj)->value();
2100 } else {
2101 LOG_API("Int32Value (slow)");
2102 ENTER_V8;
2103 EXCEPTION_PREAMBLE();
2104 i::Handle<i::Object> num =
2105 i::Execution::ToInt32(obj, &has_pending_exception);
2106 EXCEPTION_BAILOUT_CHECK(0);
2107 if (num->IsSmi()) {
2108 return i::Smi::cast(*num)->value();
2109 } else {
2110 return static_cast<int32_t>(num->Number());
2111 }
2112 }
2113}
2114
2115
2116bool Value::Equals(Handle<Value> that) const {
2117 if (IsDeadCheck("v8::Value::Equals()")
2118 || EmptyCheck("v8::Value::Equals()", this)
2119 || EmptyCheck("v8::Value::Equals()", that)) {
2120 return false;
2121 }
2122 LOG_API("Equals");
2123 ENTER_V8;
2124 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2125 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2126 i::Object** args[1] = { other.location() };
2127 EXCEPTION_PREAMBLE();
2128 i::Handle<i::Object> result =
2129 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
2130 EXCEPTION_BAILOUT_CHECK(false);
2131 return *result == i::Smi::FromInt(i::EQUAL);
2132}
2133
2134
2135bool Value::StrictEquals(Handle<Value> that) const {
2136 if (IsDeadCheck("v8::Value::StrictEquals()")
2137 || EmptyCheck("v8::Value::StrictEquals()", this)
2138 || EmptyCheck("v8::Value::StrictEquals()", that)) {
2139 return false;
2140 }
2141 LOG_API("StrictEquals");
2142 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2143 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2144 // Must check HeapNumber first, since NaN !== NaN.
2145 if (obj->IsHeapNumber()) {
2146 if (!other->IsNumber()) return false;
2147 double x = obj->Number();
2148 double y = other->Number();
2149 // Must check explicitly for NaN:s on Windows, but -0 works fine.
2150 return x == y && !isnan(x) && !isnan(y);
2151 } else if (*obj == *other) { // Also covers Booleans.
2152 return true;
2153 } else if (obj->IsSmi()) {
2154 return other->IsNumber() && obj->Number() == other->Number();
2155 } else if (obj->IsString()) {
2156 return other->IsString() &&
2157 i::String::cast(*obj)->Equals(i::String::cast(*other));
2158 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2159 return other->IsUndefined() || other->IsUndetectableObject();
2160 } else {
2161 return false;
2162 }
2163}
2164
2165
2166uint32_t Value::Uint32Value() const {
2167 if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
2168 LOG_API("Uint32Value");
2169 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2170 if (obj->IsSmi()) {
2171 return i::Smi::cast(*obj)->value();
2172 } else {
2173 ENTER_V8;
2174 EXCEPTION_PREAMBLE();
2175 i::Handle<i::Object> num =
2176 i::Execution::ToUint32(obj, &has_pending_exception);
2177 EXCEPTION_BAILOUT_CHECK(0);
2178 if (num->IsSmi()) {
2179 return i::Smi::cast(*num)->value();
2180 } else {
2181 return static_cast<uint32_t>(num->Number());
2182 }
2183 }
2184}
2185
2186
2187bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
2188 v8::PropertyAttribute attribs) {
2189 ON_BAILOUT("v8::Object::Set()", return false);
2190 ENTER_V8;
2191 HandleScope scope;
2192 i::Handle<i::Object> self = Utils::OpenHandle(this);
2193 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2194 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2195 EXCEPTION_PREAMBLE();
2196 i::Handle<i::Object> obj = i::SetProperty(
2197 self,
2198 key_obj,
2199 value_obj,
2200 static_cast<PropertyAttributes>(attribs));
2201 has_pending_exception = obj.is_null();
2202 EXCEPTION_BAILOUT_CHECK(false);
2203 return true;
2204}
2205
2206
Steve Block6ded16b2010-05-10 14:33:55 +01002207bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
2208 ON_BAILOUT("v8::Object::Set()", return false);
2209 ENTER_V8;
2210 HandleScope scope;
2211 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2212 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2213 EXCEPTION_PREAMBLE();
2214 i::Handle<i::Object> obj = i::SetElement(
2215 self,
2216 index,
2217 value_obj);
2218 has_pending_exception = obj.is_null();
2219 EXCEPTION_BAILOUT_CHECK(false);
2220 return true;
2221}
2222
2223
Steve Blocka7e24c12009-10-30 11:49:00 +00002224bool v8::Object::ForceSet(v8::Handle<Value> key,
2225 v8::Handle<Value> value,
2226 v8::PropertyAttribute attribs) {
2227 ON_BAILOUT("v8::Object::ForceSet()", return false);
2228 ENTER_V8;
2229 HandleScope scope;
2230 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2231 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2232 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2233 EXCEPTION_PREAMBLE();
2234 i::Handle<i::Object> obj = i::ForceSetProperty(
2235 self,
2236 key_obj,
2237 value_obj,
2238 static_cast<PropertyAttributes>(attribs));
2239 has_pending_exception = obj.is_null();
2240 EXCEPTION_BAILOUT_CHECK(false);
2241 return true;
2242}
2243
2244
2245bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2246 ON_BAILOUT("v8::Object::ForceDelete()", return false);
2247 ENTER_V8;
2248 HandleScope scope;
2249 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2250 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2251 EXCEPTION_PREAMBLE();
2252 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2253 has_pending_exception = obj.is_null();
2254 EXCEPTION_BAILOUT_CHECK(false);
2255 return obj->IsTrue();
2256}
2257
2258
2259Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2260 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2261 ENTER_V8;
2262 i::Handle<i::Object> self = Utils::OpenHandle(this);
2263 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2264 EXCEPTION_PREAMBLE();
2265 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2266 has_pending_exception = result.is_null();
2267 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2268 return Utils::ToLocal(result);
2269}
2270
2271
Steve Block6ded16b2010-05-10 14:33:55 +01002272Local<Value> v8::Object::Get(uint32_t index) {
2273 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2274 ENTER_V8;
2275 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2276 EXCEPTION_PREAMBLE();
2277 i::Handle<i::Object> result = i::GetElement(self, index);
2278 has_pending_exception = result.is_null();
2279 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2280 return Utils::ToLocal(result);
2281}
2282
2283
Steve Blocka7e24c12009-10-30 11:49:00 +00002284Local<Value> v8::Object::GetPrototype() {
2285 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
2286 ENTER_V8;
2287 i::Handle<i::Object> self = Utils::OpenHandle(this);
2288 i::Handle<i::Object> result = i::GetPrototype(self);
2289 return Utils::ToLocal(result);
2290}
2291
2292
Andrei Popescu402d9372010-02-26 13:31:12 +00002293bool v8::Object::SetPrototype(Handle<Value> value) {
2294 ON_BAILOUT("v8::Object::SetPrototype()", return false);
2295 ENTER_V8;
2296 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2297 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2298 EXCEPTION_PREAMBLE();
2299 i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2300 has_pending_exception = result.is_null();
2301 EXCEPTION_BAILOUT_CHECK(false);
2302 return true;
2303}
2304
2305
Steve Blocka7e24c12009-10-30 11:49:00 +00002306Local<Object> v8::Object::FindInstanceInPrototypeChain(
2307 v8::Handle<FunctionTemplate> tmpl) {
2308 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
2309 return Local<v8::Object>());
2310 ENTER_V8;
2311 i::JSObject* object = *Utils::OpenHandle(this);
2312 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2313 while (!object->IsInstanceOf(tmpl_info)) {
2314 i::Object* prototype = object->GetPrototype();
2315 if (!prototype->IsJSObject()) return Local<Object>();
2316 object = i::JSObject::cast(prototype);
2317 }
2318 return Utils::ToLocal(i::Handle<i::JSObject>(object));
2319}
2320
2321
2322Local<Array> v8::Object::GetPropertyNames() {
2323 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
2324 ENTER_V8;
2325 v8::HandleScope scope;
2326 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2327 i::Handle<i::FixedArray> value =
2328 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2329 // Because we use caching to speed up enumeration it is important
2330 // to never change the result of the basic enumeration function so
2331 // we clone the result.
2332 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
2333 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
2334 return scope.Close(Utils::ToLocal(result));
2335}
2336
2337
2338Local<String> v8::Object::ObjectProtoToString() {
2339 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2340 ENTER_V8;
2341 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2342
2343 i::Handle<i::Object> name(self->class_name());
2344
2345 // Native implementation of Object.prototype.toString (v8natives.js):
2346 // var c = %ClassOf(this);
2347 // if (c === 'Arguments') c = 'Object';
2348 // return "[object " + c + "]";
2349
2350 if (!name->IsString()) {
2351 return v8::String::New("[object ]");
2352
2353 } else {
2354 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2355 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2356 return v8::String::New("[object Object]");
2357
2358 } else {
2359 const char* prefix = "[object ";
2360 Local<String> str = Utils::ToLocal(class_name);
2361 const char* postfix = "]";
2362
Steve Blockd0582a62009-12-15 09:54:21 +00002363 int prefix_len = i::StrLength(prefix);
2364 int str_len = str->Length();
2365 int postfix_len = i::StrLength(postfix);
Steve Blocka7e24c12009-10-30 11:49:00 +00002366
Steve Blockd0582a62009-12-15 09:54:21 +00002367 int buf_len = prefix_len + str_len + postfix_len;
Kristian Monsen25f61362010-05-21 11:50:48 +01002368 i::ScopedVector<char> buf(buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002369
2370 // Write prefix.
Kristian Monsen25f61362010-05-21 11:50:48 +01002371 char* ptr = buf.start();
Steve Blocka7e24c12009-10-30 11:49:00 +00002372 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2373 ptr += prefix_len;
2374
2375 // Write real content.
2376 str->WriteAscii(ptr, 0, str_len);
2377 ptr += str_len;
2378
2379 // Write postfix.
2380 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2381
2382 // Copy the buffer into a heap-allocated string and return it.
Kristian Monsen25f61362010-05-21 11:50:48 +01002383 Local<String> result = v8::String::New(buf.start(), buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002384 return result;
2385 }
2386 }
2387}
2388
2389
2390bool v8::Object::Delete(v8::Handle<String> key) {
2391 ON_BAILOUT("v8::Object::Delete()", return false);
2392 ENTER_V8;
2393 HandleScope scope;
2394 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2395 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2396 return i::DeleteProperty(self, key_obj)->IsTrue();
2397}
2398
2399
2400bool v8::Object::Has(v8::Handle<String> key) {
2401 ON_BAILOUT("v8::Object::Has()", return false);
2402 ENTER_V8;
2403 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2404 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2405 return self->HasProperty(*key_obj);
2406}
2407
2408
2409bool v8::Object::Delete(uint32_t index) {
2410 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2411 ENTER_V8;
2412 HandleScope scope;
2413 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2414 return i::DeleteElement(self, index)->IsTrue();
2415}
2416
2417
2418bool v8::Object::Has(uint32_t index) {
2419 ON_BAILOUT("v8::Object::HasProperty()", return false);
2420 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2421 return self->HasElement(index);
2422}
2423
2424
Leon Clarkef7060e22010-06-03 12:02:55 +01002425bool Object::SetAccessor(Handle<String> name,
2426 AccessorGetter getter,
2427 AccessorSetter setter,
2428 v8::Handle<Value> data,
2429 AccessControl settings,
2430 PropertyAttribute attributes) {
2431 ON_BAILOUT("v8::Object::SetAccessor()", return false);
2432 ENTER_V8;
2433 HandleScope scope;
2434 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name,
2435 getter, setter, data,
2436 settings, attributes);
2437 i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info);
2438 return !result.is_null() && !result->IsUndefined();
2439}
2440
2441
Steve Blocka7e24c12009-10-30 11:49:00 +00002442bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2443 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2444 return Utils::OpenHandle(this)->HasRealNamedProperty(
2445 *Utils::OpenHandle(*key));
2446}
2447
2448
2449bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2450 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2451 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2452}
2453
2454
2455bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2456 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2457 ENTER_V8;
2458 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2459 *Utils::OpenHandle(*key));
2460}
2461
2462
2463bool v8::Object::HasNamedLookupInterceptor() {
2464 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2465 return Utils::OpenHandle(this)->HasNamedInterceptor();
2466}
2467
2468
2469bool v8::Object::HasIndexedLookupInterceptor() {
2470 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2471 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2472}
2473
2474
2475Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2476 Handle<String> key) {
2477 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2478 return Local<Value>());
2479 ENTER_V8;
2480 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2481 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2482 i::LookupResult lookup;
2483 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002484 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002485 PropertyAttributes attributes;
2486 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2487 &lookup,
2488 *key_obj,
2489 &attributes));
2490 return Utils::ToLocal(result);
2491 }
2492 return Local<Value>(); // No real property was found in prototype chain.
2493}
2494
2495
2496Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2497 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
2498 ENTER_V8;
2499 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2500 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2501 i::LookupResult lookup;
2502 self_obj->LookupRealNamedProperty(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002503 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002504 PropertyAttributes attributes;
2505 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2506 &lookup,
2507 *key_obj,
2508 &attributes));
2509 return Utils::ToLocal(result);
2510 }
2511 return Local<Value>(); // No real property was found in prototype chain.
2512}
2513
2514
2515// Turns on access checks by copying the map and setting the check flag.
2516// Because the object gets a new map, existing inline cache caching
2517// the old map of this object will fail.
2518void v8::Object::TurnOnAccessCheck() {
2519 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2520 ENTER_V8;
2521 HandleScope scope;
2522 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2523
2524 i::Handle<i::Map> new_map =
2525 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2526 new_map->set_is_access_check_needed(true);
2527 obj->set_map(*new_map);
2528}
2529
2530
2531bool v8::Object::IsDirty() {
2532 return Utils::OpenHandle(this)->IsDirty();
2533}
2534
2535
2536Local<v8::Object> v8::Object::Clone() {
2537 ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2538 ENTER_V8;
2539 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2540 EXCEPTION_PREAMBLE();
2541 i::Handle<i::JSObject> result = i::Copy(self);
2542 has_pending_exception = result.is_null();
2543 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2544 return Utils::ToLocal(result);
2545}
2546
2547
2548int v8::Object::GetIdentityHash() {
2549 ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2550 ENTER_V8;
2551 HandleScope scope;
2552 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2553 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2554 i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
2555 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2556 int hash_value;
2557 if (hash->IsSmi()) {
2558 hash_value = i::Smi::cast(*hash)->value();
2559 } else {
2560 int attempts = 0;
2561 do {
2562 // Generate a random 32-bit hash value but limit range to fit
2563 // within a smi.
2564 hash_value = i::V8::Random() & i::Smi::kMaxValue;
2565 attempts++;
2566 } while (hash_value == 0 && attempts < 30);
2567 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
2568 i::SetProperty(hidden_props,
2569 hash_symbol,
2570 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2571 static_cast<PropertyAttributes>(None));
2572 }
2573 return hash_value;
2574}
2575
2576
2577bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2578 v8::Handle<v8::Value> value) {
2579 ON_BAILOUT("v8::Object::SetHiddenValue()", 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, true));
2584 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2585 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2586 EXCEPTION_PREAMBLE();
2587 i::Handle<i::Object> obj = i::SetProperty(
2588 hidden_props,
2589 key_obj,
2590 value_obj,
2591 static_cast<PropertyAttributes>(None));
2592 has_pending_exception = obj.is_null();
2593 EXCEPTION_BAILOUT_CHECK(false);
2594 return true;
2595}
2596
2597
2598v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2599 ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2600 ENTER_V8;
2601 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2602 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2603 if (hidden_props->IsUndefined()) {
2604 return v8::Local<v8::Value>();
2605 }
2606 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2607 EXCEPTION_PREAMBLE();
2608 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2609 has_pending_exception = result.is_null();
2610 EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2611 if (result->IsUndefined()) {
2612 return v8::Local<v8::Value>();
2613 }
2614 return Utils::ToLocal(result);
2615}
2616
2617
2618bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2619 ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2620 ENTER_V8;
2621 HandleScope scope;
2622 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2623 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2624 if (hidden_props->IsUndefined()) {
2625 return true;
2626 }
2627 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2628 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2629 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2630}
2631
2632
2633void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2634 ON_BAILOUT("v8::SetElementsToPixelData()", return);
2635 ENTER_V8;
2636 HandleScope scope;
Steve Block3ce2e202009-11-05 08:53:23 +00002637 if (!ApiCheck(length <= i::PixelArray::kMaxLength,
Steve Blocka7e24c12009-10-30 11:49:00 +00002638 "v8::Object::SetIndexedPropertiesToPixelData()",
2639 "length exceeds max acceptable value")) {
2640 return;
2641 }
2642 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2643 if (!ApiCheck(!self->IsJSArray(),
2644 "v8::Object::SetIndexedPropertiesToPixelData()",
2645 "JSArray is not supported")) {
2646 return;
2647 }
2648 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
Steve Block8defd9f2010-07-08 12:39:36 +01002649 self->set_map(
2650 *i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map())));
Steve Blocka7e24c12009-10-30 11:49:00 +00002651 self->set_elements(*pixels);
2652}
2653
2654
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002655bool v8::Object::HasIndexedPropertiesInPixelData() {
2656 ON_BAILOUT("v8::HasIndexedPropertiesInPixelData()", return false);
2657 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2658 return self->HasPixelElements();
2659}
2660
2661
2662uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
2663 ON_BAILOUT("v8::GetIndexedPropertiesPixelData()", return NULL);
2664 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2665 if (self->HasPixelElements()) {
2666 return i::PixelArray::cast(self->elements())->external_pointer();
2667 } else {
2668 return NULL;
2669 }
2670}
2671
2672
2673int v8::Object::GetIndexedPropertiesPixelDataLength() {
2674 ON_BAILOUT("v8::GetIndexedPropertiesPixelDataLength()", return -1);
2675 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2676 if (self->HasPixelElements()) {
2677 return i::PixelArray::cast(self->elements())->length();
2678 } else {
2679 return -1;
2680 }
2681}
2682
2683
Steve Block3ce2e202009-11-05 08:53:23 +00002684void v8::Object::SetIndexedPropertiesToExternalArrayData(
2685 void* data,
2686 ExternalArrayType array_type,
2687 int length) {
2688 ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
2689 ENTER_V8;
2690 HandleScope scope;
2691 if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
2692 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2693 "length exceeds max acceptable value")) {
2694 return;
2695 }
2696 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2697 if (!ApiCheck(!self->IsJSArray(),
2698 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2699 "JSArray is not supported")) {
2700 return;
2701 }
2702 i::Handle<i::ExternalArray> array =
2703 i::Factory::NewExternalArray(length, array_type, data);
Steve Block8defd9f2010-07-08 12:39:36 +01002704 self->set_map(
2705 *i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map())));
Steve Block3ce2e202009-11-05 08:53:23 +00002706 self->set_elements(*array);
2707}
2708
2709
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002710bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
2711 ON_BAILOUT("v8::HasIndexedPropertiesInExternalArrayData()", return false);
2712 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2713 return self->HasExternalArrayElements();
2714}
2715
2716
2717void* v8::Object::GetIndexedPropertiesExternalArrayData() {
2718 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayData()", return NULL);
2719 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2720 if (self->HasExternalArrayElements()) {
2721 return i::ExternalArray::cast(self->elements())->external_pointer();
2722 } else {
2723 return NULL;
2724 }
2725}
2726
2727
2728ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
2729 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataType()",
2730 return static_cast<ExternalArrayType>(-1));
2731 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2732 switch (self->elements()->map()->instance_type()) {
2733 case i::EXTERNAL_BYTE_ARRAY_TYPE:
2734 return kExternalByteArray;
2735 case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2736 return kExternalUnsignedByteArray;
2737 case i::EXTERNAL_SHORT_ARRAY_TYPE:
2738 return kExternalShortArray;
2739 case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2740 return kExternalUnsignedShortArray;
2741 case i::EXTERNAL_INT_ARRAY_TYPE:
2742 return kExternalIntArray;
2743 case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2744 return kExternalUnsignedIntArray;
2745 case i::EXTERNAL_FLOAT_ARRAY_TYPE:
2746 return kExternalFloatArray;
2747 default:
2748 return static_cast<ExternalArrayType>(-1);
2749 }
2750}
2751
2752
2753int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
2754 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataLength()", return 0);
2755 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2756 if (self->HasExternalArrayElements()) {
2757 return i::ExternalArray::cast(self->elements())->length();
2758 } else {
2759 return -1;
2760 }
2761}
2762
2763
Steve Blocka7e24c12009-10-30 11:49:00 +00002764Local<v8::Object> Function::NewInstance() const {
2765 return NewInstance(0, NULL);
2766}
2767
2768
2769Local<v8::Object> Function::NewInstance(int argc,
2770 v8::Handle<v8::Value> argv[]) const {
2771 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2772 LOG_API("Function::NewInstance");
2773 ENTER_V8;
2774 HandleScope scope;
2775 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2776 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2777 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2778 EXCEPTION_PREAMBLE();
2779 i::Handle<i::Object> returned =
2780 i::Execution::New(function, argc, args, &has_pending_exception);
2781 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2782 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2783}
2784
2785
2786Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2787 v8::Handle<v8::Value> argv[]) {
2788 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2789 LOG_API("Function::Call");
2790 ENTER_V8;
2791 i::Object* raw_result = NULL;
2792 {
2793 HandleScope scope;
2794 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2795 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2796 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2797 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2798 EXCEPTION_PREAMBLE();
2799 i::Handle<i::Object> returned =
2800 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2801 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2802 raw_result = *returned;
2803 }
2804 i::Handle<i::Object> result(raw_result);
2805 return Utils::ToLocal(result);
2806}
2807
2808
2809void Function::SetName(v8::Handle<v8::String> name) {
2810 ENTER_V8;
2811 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2812 func->shared()->set_name(*Utils::OpenHandle(*name));
2813}
2814
2815
2816Handle<Value> Function::GetName() const {
2817 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2818 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2819}
2820
2821
Andrei Popescu402d9372010-02-26 13:31:12 +00002822ScriptOrigin Function::GetScriptOrigin() const {
2823 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2824 if (func->shared()->script()->IsScript()) {
2825 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2826 v8::ScriptOrigin origin(
2827 Utils::ToLocal(i::Handle<i::Object>(script->name())),
2828 v8::Integer::New(script->line_offset()->value()),
2829 v8::Integer::New(script->column_offset()->value()));
2830 return origin;
2831 }
2832 return v8::ScriptOrigin(Handle<Value>());
2833}
2834
2835
2836const int Function::kLineOffsetNotFound = -1;
2837
2838
2839int Function::GetScriptLineNumber() const {
2840 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2841 if (func->shared()->script()->IsScript()) {
2842 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2843 return i::GetScriptLineNumber(script, func->shared()->start_position());
2844 }
2845 return kLineOffsetNotFound;
2846}
2847
2848
2849namespace {
2850
2851// Tracks string usage to help make better decisions when
2852// externalizing strings.
2853//
2854// Implementation note: internally this class only tracks fresh
2855// strings and keeps a single use counter for them.
2856class StringTracker {
2857 public:
2858 // Records that the given string's characters were copied to some
2859 // external buffer. If this happens often we should honor
2860 // externalization requests for the string.
2861 static void RecordWrite(i::Handle<i::String> string) {
2862 i::Address address = reinterpret_cast<i::Address>(*string);
2863 i::Address top = i::Heap::NewSpaceTop();
2864 if (IsFreshString(address, top)) {
2865 IncrementUseCount(top);
2866 }
2867 }
2868
2869 // Estimates freshness and use frequency of the given string based
2870 // on how close it is to the new space top and the recorded usage
2871 // history.
2872 static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
2873 i::Address address = reinterpret_cast<i::Address>(*string);
2874 i::Address top = i::Heap::NewSpaceTop();
2875 return IsFreshString(address, top) && IsUseCountLow(top);
2876 }
2877
2878 private:
2879 static inline bool IsFreshString(i::Address string, i::Address top) {
2880 return top - kFreshnessLimit <= string && string <= top;
2881 }
2882
2883 static inline bool IsUseCountLow(i::Address top) {
2884 if (last_top_ != top) return true;
2885 return use_count_ < kUseLimit;
2886 }
2887
2888 static inline void IncrementUseCount(i::Address top) {
2889 if (last_top_ != top) {
2890 use_count_ = 0;
2891 last_top_ = top;
2892 }
2893 ++use_count_;
2894 }
2895
2896 // How close to the new space top a fresh string has to be.
2897 static const int kFreshnessLimit = 1024;
2898
2899 // The number of uses required to consider a string useful.
2900 static const int kUseLimit = 32;
2901
2902 // Single use counter shared by all fresh strings.
2903 static int use_count_;
2904
2905 // Last new space top when the use count above was valid.
2906 static i::Address last_top_;
2907};
2908
2909int StringTracker::use_count_ = 0;
2910i::Address StringTracker::last_top_ = NULL;
2911
2912} // namespace
2913
2914
Steve Blocka7e24c12009-10-30 11:49:00 +00002915int String::Length() const {
2916 if (IsDeadCheck("v8::String::Length()")) return 0;
2917 return Utils::OpenHandle(this)->length();
2918}
2919
2920
2921int String::Utf8Length() const {
2922 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
2923 return Utils::OpenHandle(this)->Utf8Length();
2924}
2925
2926
Steve Block6ded16b2010-05-10 14:33:55 +01002927int String::WriteUtf8(char* buffer,
2928 int capacity,
2929 int* nchars_ref,
2930 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002931 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
2932 LOG_API("String::WriteUtf8");
2933 ENTER_V8;
2934 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002935 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002936 if (hints & HINT_MANY_WRITES_EXPECTED) {
2937 // Flatten the string for efficiency. This applies whether we are
2938 // using StringInputBuffer or Get(i) to access the characters.
2939 str->TryFlatten();
2940 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002941 write_input_buffer.Reset(0, *str);
2942 int len = str->length();
2943 // Encode the first K - 3 bytes directly into the buffer since we
2944 // know there's room for them. If no capacity is given we copy all
2945 // of them here.
2946 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
2947 int i;
2948 int pos = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01002949 int nchars = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002950 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
2951 i::uc32 c = write_input_buffer.GetNext();
2952 int written = unibrow::Utf8::Encode(buffer + pos, c);
2953 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002954 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002955 }
2956 if (i < len) {
2957 // For the last characters we need to check the length for each one
2958 // because they may be longer than the remaining space in the
2959 // buffer.
2960 char intermediate[unibrow::Utf8::kMaxEncodedSize];
2961 for (; i < len && pos < capacity; i++) {
2962 i::uc32 c = write_input_buffer.GetNext();
2963 int written = unibrow::Utf8::Encode(intermediate, c);
2964 if (pos + written <= capacity) {
2965 for (int j = 0; j < written; j++)
2966 buffer[pos + j] = intermediate[j];
2967 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002968 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002969 } else {
2970 // We've reached the end of the buffer
2971 break;
2972 }
2973 }
2974 }
Steve Block6ded16b2010-05-10 14:33:55 +01002975 if (nchars_ref != NULL) *nchars_ref = nchars;
Steve Blocka7e24c12009-10-30 11:49:00 +00002976 if (i == len && (capacity == -1 || pos < capacity))
2977 buffer[pos++] = '\0';
2978 return pos;
2979}
2980
2981
Steve Block6ded16b2010-05-10 14:33:55 +01002982int String::WriteAscii(char* buffer,
2983 int start,
2984 int length,
2985 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002986 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
2987 LOG_API("String::WriteAscii");
2988 ENTER_V8;
2989 ASSERT(start >= 0 && length >= -1);
2990 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002991 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002992 if (hints & HINT_MANY_WRITES_EXPECTED) {
2993 // Flatten the string for efficiency. This applies whether we are
2994 // using StringInputBuffer or Get(i) to access the characters.
2995 str->TryFlatten();
2996 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002997 int end = length;
2998 if ( (length == -1) || (length > str->length() - start) )
2999 end = str->length() - start;
3000 if (end < 0) return 0;
3001 write_input_buffer.Reset(start, *str);
3002 int i;
3003 for (i = 0; i < end; i++) {
3004 char c = static_cast<char>(write_input_buffer.GetNext());
3005 if (c == '\0') c = ' ';
3006 buffer[i] = c;
3007 }
3008 if (length == -1 || i < length)
3009 buffer[i] = '\0';
3010 return i;
3011}
3012
3013
Steve Block6ded16b2010-05-10 14:33:55 +01003014int String::Write(uint16_t* buffer,
3015 int start,
3016 int length,
3017 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003018 if (IsDeadCheck("v8::String::Write()")) return 0;
3019 LOG_API("String::Write");
3020 ENTER_V8;
3021 ASSERT(start >= 0 && length >= -1);
3022 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003023 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003024 if (hints & HINT_MANY_WRITES_EXPECTED) {
3025 // Flatten the string for efficiency. This applies whether we are
3026 // using StringInputBuffer or Get(i) to access the characters.
3027 str->TryFlatten();
3028 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003029 int end = length;
3030 if ( (length == -1) || (length > str->length() - start) )
3031 end = str->length() - start;
3032 if (end < 0) return 0;
3033 i::String::WriteToFlat(*str, buffer, start, end);
3034 if (length == -1 || end < length)
3035 buffer[end] = '\0';
3036 return end;
3037}
3038
3039
3040bool v8::String::IsExternal() const {
3041 EnsureInitialized("v8::String::IsExternal()");
3042 i::Handle<i::String> str = Utils::OpenHandle(this);
3043 return i::StringShape(*str).IsExternalTwoByte();
3044}
3045
3046
3047bool v8::String::IsExternalAscii() const {
3048 EnsureInitialized("v8::String::IsExternalAscii()");
3049 i::Handle<i::String> str = Utils::OpenHandle(this);
3050 return i::StringShape(*str).IsExternalAscii();
3051}
3052
3053
3054void v8::String::VerifyExternalStringResource(
3055 v8::String::ExternalStringResource* value) const {
3056 i::Handle<i::String> str = Utils::OpenHandle(this);
3057 v8::String::ExternalStringResource* expected;
3058 if (i::StringShape(*str).IsExternalTwoByte()) {
3059 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
3060 expected = reinterpret_cast<ExternalStringResource*>(resource);
3061 } else {
3062 expected = NULL;
3063 }
3064 CHECK_EQ(expected, value);
3065}
3066
3067
3068v8::String::ExternalAsciiStringResource*
3069 v8::String::GetExternalAsciiStringResource() const {
3070 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
3071 i::Handle<i::String> str = Utils::OpenHandle(this);
3072 if (i::StringShape(*str).IsExternalAscii()) {
3073 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
3074 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
3075 } else {
3076 return NULL;
3077 }
3078}
3079
3080
3081double Number::Value() const {
3082 if (IsDeadCheck("v8::Number::Value()")) return 0;
3083 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3084 return obj->Number();
3085}
3086
3087
3088bool Boolean::Value() const {
3089 if (IsDeadCheck("v8::Boolean::Value()")) return false;
3090 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3091 return obj->IsTrue();
3092}
3093
3094
3095int64_t Integer::Value() const {
3096 if (IsDeadCheck("v8::Integer::Value()")) return 0;
3097 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3098 if (obj->IsSmi()) {
3099 return i::Smi::cast(*obj)->value();
3100 } else {
3101 return static_cast<int64_t>(obj->Number());
3102 }
3103}
3104
3105
3106int32_t Int32::Value() const {
3107 if (IsDeadCheck("v8::Int32::Value()")) return 0;
3108 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3109 if (obj->IsSmi()) {
3110 return i::Smi::cast(*obj)->value();
3111 } else {
3112 return static_cast<int32_t>(obj->Number());
3113 }
3114}
3115
3116
Steve Block6ded16b2010-05-10 14:33:55 +01003117uint32_t Uint32::Value() const {
3118 if (IsDeadCheck("v8::Uint32::Value()")) return 0;
3119 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3120 if (obj->IsSmi()) {
3121 return i::Smi::cast(*obj)->value();
3122 } else {
3123 return static_cast<uint32_t>(obj->Number());
3124 }
3125}
3126
3127
Steve Blocka7e24c12009-10-30 11:49:00 +00003128int v8::Object::InternalFieldCount() {
3129 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
3130 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3131 return obj->GetInternalFieldCount();
3132}
3133
3134
3135Local<Value> v8::Object::CheckedGetInternalField(int index) {
3136 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
3137 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3138 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3139 "v8::Object::GetInternalField()",
3140 "Reading internal field out of bounds")) {
3141 return Local<Value>();
3142 }
3143 i::Handle<i::Object> value(obj->GetInternalField(index));
3144 Local<Value> result = Utils::ToLocal(value);
3145#ifdef DEBUG
3146 Local<Value> unchecked = UncheckedGetInternalField(index);
3147 ASSERT(unchecked.IsEmpty() || (unchecked == result));
3148#endif
3149 return result;
3150}
3151
3152
3153void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
3154 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
3155 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3156 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3157 "v8::Object::SetInternalField()",
3158 "Writing internal field out of bounds")) {
3159 return;
3160 }
3161 ENTER_V8;
3162 i::Handle<i::Object> val = Utils::OpenHandle(*value);
3163 obj->SetInternalField(index, *val);
3164}
3165
3166
3167void v8::Object::SetPointerInInternalField(int index, void* value) {
Steve Block6ded16b2010-05-10 14:33:55 +01003168 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003169 i::Object* as_object = reinterpret_cast<i::Object*>(value);
3170 if (as_object->IsSmi()) {
3171 Utils::OpenHandle(this)->SetInternalField(index, as_object);
3172 return;
3173 }
3174 HandleScope scope;
3175 i::Handle<i::Proxy> proxy =
3176 i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
3177 if (!proxy.is_null())
3178 Utils::OpenHandle(this)->SetInternalField(index, *proxy);
Steve Blocka7e24c12009-10-30 11:49:00 +00003179}
3180
3181
3182// --- E n v i r o n m e n t ---
3183
3184bool v8::V8::Initialize() {
3185 if (i::V8::IsRunning()) return true;
3186 ENTER_V8;
3187 HandleScope scope;
Steve Blockd0582a62009-12-15 09:54:21 +00003188 if (i::Snapshot::Initialize()) return true;
3189 return i::V8::Initialize(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00003190}
3191
3192
3193bool v8::V8::Dispose() {
3194 i::V8::TearDown();
3195 return true;
3196}
3197
3198
Steve Block3ce2e202009-11-05 08:53:23 +00003199HeapStatistics::HeapStatistics(): total_heap_size_(0), used_heap_size_(0) { }
3200
3201
3202void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
3203 heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
3204 heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
3205}
3206
3207
3208bool v8::V8::IdleNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003209 // Returning true tells the caller that it need not
3210 // continue to call IdleNotification.
3211 if (!i::V8::IsRunning()) return true;
Steve Block3ce2e202009-11-05 08:53:23 +00003212 return i::V8::IdleNotification();
Steve Blocka7e24c12009-10-30 11:49:00 +00003213}
3214
3215
3216void v8::V8::LowMemoryNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003217 if (!i::V8::IsRunning()) return;
3218 i::Heap::CollectAllGarbage(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00003219}
3220
3221
Steve Block6ded16b2010-05-10 14:33:55 +01003222int v8::V8::ContextDisposedNotification() {
3223 if (!i::V8::IsRunning()) return 0;
3224 return i::Heap::NotifyContextDisposed();
3225}
3226
3227
Steve Blocka7e24c12009-10-30 11:49:00 +00003228const char* v8::V8::GetVersion() {
3229 static v8::internal::EmbeddedVector<char, 128> buffer;
3230 v8::internal::Version::GetString(buffer);
3231 return buffer.start();
3232}
3233
3234
3235static i::Handle<i::FunctionTemplateInfo>
3236 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
3237 if (templ->constructor()->IsUndefined()) {
3238 Local<FunctionTemplate> constructor = FunctionTemplate::New();
3239 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
3240 templ->set_constructor(*Utils::OpenHandle(*constructor));
3241 }
3242 return i::Handle<i::FunctionTemplateInfo>(
3243 i::FunctionTemplateInfo::cast(templ->constructor()));
3244}
3245
3246
3247Persistent<Context> v8::Context::New(
3248 v8::ExtensionConfiguration* extensions,
3249 v8::Handle<ObjectTemplate> global_template,
3250 v8::Handle<Value> global_object) {
3251 EnsureInitialized("v8::Context::New()");
3252 LOG_API("Context::New");
3253 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
3254
3255 // Enter V8 via an ENTER_V8 scope.
3256 i::Handle<i::Context> env;
3257 {
3258 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003259 v8::Handle<ObjectTemplate> proxy_template = global_template;
3260 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
3261 i::Handle<i::FunctionTemplateInfo> global_constructor;
3262
3263 if (!global_template.IsEmpty()) {
3264 // Make sure that the global_template has a constructor.
3265 global_constructor =
3266 EnsureConstructor(Utils::OpenHandle(*global_template));
3267
3268 // Create a fresh template for the global proxy object.
3269 proxy_template = ObjectTemplate::New();
3270 proxy_constructor =
3271 EnsureConstructor(Utils::OpenHandle(*proxy_template));
3272
3273 // Set the global template to be the prototype template of
3274 // global proxy template.
3275 proxy_constructor->set_prototype_template(
3276 *Utils::OpenHandle(*global_template));
3277
3278 // Migrate security handlers from global_template to
3279 // proxy_template. Temporarily removing access check
3280 // information from the global template.
3281 if (!global_constructor->access_check_info()->IsUndefined()) {
3282 proxy_constructor->set_access_check_info(
3283 global_constructor->access_check_info());
3284 proxy_constructor->set_needs_access_check(
3285 global_constructor->needs_access_check());
3286 global_constructor->set_needs_access_check(false);
3287 global_constructor->set_access_check_info(i::Heap::undefined_value());
3288 }
3289 }
3290
3291 // Create the environment.
3292 env = i::Bootstrapper::CreateEnvironment(
3293 Utils::OpenHandle(*global_object),
3294 proxy_template,
3295 extensions);
3296
3297 // Restore the access check info on the global template.
3298 if (!global_template.IsEmpty()) {
3299 ASSERT(!global_constructor.is_null());
3300 ASSERT(!proxy_constructor.is_null());
3301 global_constructor->set_access_check_info(
3302 proxy_constructor->access_check_info());
3303 global_constructor->set_needs_access_check(
3304 proxy_constructor->needs_access_check());
3305 }
3306 }
3307 // Leave V8.
3308
3309 if (env.is_null())
3310 return Persistent<Context>();
3311 return Persistent<Context>(Utils::ToLocal(env));
3312}
3313
3314
3315void v8::Context::SetSecurityToken(Handle<Value> token) {
3316 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
3317 ENTER_V8;
3318 i::Handle<i::Context> env = Utils::OpenHandle(this);
3319 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
3320 env->set_security_token(*token_handle);
3321}
3322
3323
3324void v8::Context::UseDefaultSecurityToken() {
3325 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
3326 ENTER_V8;
3327 i::Handle<i::Context> env = Utils::OpenHandle(this);
3328 env->set_security_token(env->global());
3329}
3330
3331
3332Handle<Value> v8::Context::GetSecurityToken() {
3333 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
3334 i::Handle<i::Context> env = Utils::OpenHandle(this);
3335 i::Object* security_token = env->security_token();
3336 i::Handle<i::Object> token_handle(security_token);
3337 return Utils::ToLocal(token_handle);
3338}
3339
3340
3341bool Context::HasOutOfMemoryException() {
3342 i::Handle<i::Context> env = Utils::OpenHandle(this);
3343 return env->has_out_of_memory();
3344}
3345
3346
3347bool Context::InContext() {
3348 return i::Top::context() != NULL;
3349}
3350
3351
3352v8::Local<v8::Context> Context::GetEntered() {
3353 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
3354 i::Handle<i::Object> last = thread_local.LastEnteredContext();
3355 if (last.is_null()) return Local<Context>();
3356 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
3357 return Utils::ToLocal(context);
3358}
3359
3360
3361v8::Local<v8::Context> Context::GetCurrent() {
3362 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
Steve Block3ce2e202009-11-05 08:53:23 +00003363 i::Handle<i::Object> current = i::Top::global_context();
3364 if (current.is_null()) return Local<Context>();
3365 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
Steve Blocka7e24c12009-10-30 11:49:00 +00003366 return Utils::ToLocal(context);
3367}
3368
3369
3370v8::Local<v8::Context> Context::GetCalling() {
3371 if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
3372 i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
3373 if (calling.is_null()) return Local<Context>();
3374 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
3375 return Utils::ToLocal(context);
3376}
3377
3378
3379v8::Local<v8::Object> Context::Global() {
3380 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
3381 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3382 i::Handle<i::Context> context =
3383 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3384 i::Handle<i::Object> global(context->global_proxy());
3385 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
3386}
3387
3388
3389void Context::DetachGlobal() {
3390 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
3391 ENTER_V8;
3392 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3393 i::Handle<i::Context> context =
3394 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3395 i::Bootstrapper::DetachGlobal(context);
3396}
3397
3398
Andrei Popescu74b3c142010-03-29 12:03:09 +01003399void Context::ReattachGlobal(Handle<Object> global_object) {
3400 if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
3401 ENTER_V8;
3402 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3403 i::Handle<i::Context> context =
3404 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3405 i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
3406}
3407
3408
Steve Blocka7e24c12009-10-30 11:49:00 +00003409Local<v8::Object> ObjectTemplate::NewInstance() {
3410 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
3411 LOG_API("ObjectTemplate::NewInstance");
3412 ENTER_V8;
3413 EXCEPTION_PREAMBLE();
3414 i::Handle<i::Object> obj =
3415 i::Execution::InstantiateObject(Utils::OpenHandle(this),
3416 &has_pending_exception);
3417 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
3418 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3419}
3420
3421
3422Local<v8::Function> FunctionTemplate::GetFunction() {
3423 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
3424 return Local<v8::Function>());
3425 LOG_API("FunctionTemplate::GetFunction");
3426 ENTER_V8;
3427 EXCEPTION_PREAMBLE();
3428 i::Handle<i::Object> obj =
3429 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3430 &has_pending_exception);
3431 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
3432 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3433}
3434
3435
3436bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3437 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
3438 i::Object* obj = *Utils::OpenHandle(*value);
3439 return obj->IsInstanceOf(*Utils::OpenHandle(this));
3440}
3441
3442
3443static Local<External> ExternalNewImpl(void* data) {
3444 return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
3445}
3446
3447static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3448 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3449}
3450
3451
Steve Blocka7e24c12009-10-30 11:49:00 +00003452Local<Value> v8::External::Wrap(void* data) {
3453 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3454 LOG_API("External::Wrap");
3455 EnsureInitialized("v8::External::Wrap()");
3456 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003457 i::Object* as_object = reinterpret_cast<i::Object*>(data);
3458 if (as_object->IsSmi()) {
3459 return Utils::ToLocal(i::Handle<i::Object>(as_object));
Steve Blocka7e24c12009-10-30 11:49:00 +00003460 }
3461 return ExternalNewImpl(data);
3462}
3463
3464
Steve Block3ce2e202009-11-05 08:53:23 +00003465void* v8::Object::SlowGetPointerFromInternalField(int index) {
3466 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3467 i::Object* value = obj->GetInternalField(index);
3468 if (value->IsSmi()) {
3469 return value;
3470 } else if (value->IsProxy()) {
3471 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3472 } else {
3473 return NULL;
3474 }
3475}
3476
3477
Steve Blocka7e24c12009-10-30 11:49:00 +00003478void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3479 if (IsDeadCheck("v8::External::Unwrap()")) return 0;
3480 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3481 void* result;
3482 if (obj->IsSmi()) {
3483 // The external value was an aligned pointer.
Steve Block3ce2e202009-11-05 08:53:23 +00003484 result = *obj;
Steve Blocka7e24c12009-10-30 11:49:00 +00003485 } else if (obj->IsProxy()) {
3486 result = ExternalValueImpl(obj);
3487 } else {
3488 result = NULL;
3489 }
3490 ASSERT_EQ(result, QuickUnwrap(wrapper));
3491 return result;
3492}
3493
3494
3495Local<External> v8::External::New(void* data) {
3496 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3497 LOG_API("External::New");
3498 EnsureInitialized("v8::External::New()");
3499 ENTER_V8;
3500 return ExternalNewImpl(data);
3501}
3502
3503
3504void* External::Value() const {
3505 if (IsDeadCheck("v8::External::Value()")) return 0;
3506 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3507 return ExternalValueImpl(obj);
3508}
3509
3510
3511Local<String> v8::String::Empty() {
3512 EnsureInitialized("v8::String::Empty()");
3513 LOG_API("String::Empty()");
3514 return Utils::ToLocal(i::Factory::empty_symbol());
3515}
3516
3517
3518Local<String> v8::String::New(const char* data, int length) {
3519 EnsureInitialized("v8::String::New()");
3520 LOG_API("String::New(char)");
3521 if (length == 0) return Empty();
3522 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003523 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003524 i::Handle<i::String> result =
3525 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3526 return Utils::ToLocal(result);
3527}
3528
3529
Steve Block3ce2e202009-11-05 08:53:23 +00003530Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3531 EnsureInitialized("v8::String::New()");
3532 LOG_API("String::New(char)");
3533 ENTER_V8;
3534 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3535 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3536 i::Handle<i::String> result = i::Factory::NewConsString(left_string,
3537 right_string);
3538 return Utils::ToLocal(result);
3539}
3540
3541
Steve Blocka7e24c12009-10-30 11:49:00 +00003542Local<String> v8::String::NewUndetectable(const char* data, int length) {
3543 EnsureInitialized("v8::String::NewUndetectable()");
3544 LOG_API("String::NewUndetectable(char)");
3545 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003546 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003547 i::Handle<i::String> result =
3548 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3549 result->MarkAsUndetectable();
3550 return Utils::ToLocal(result);
3551}
3552
3553
3554static int TwoByteStringLength(const uint16_t* data) {
3555 int length = 0;
3556 while (data[length] != '\0') length++;
3557 return length;
3558}
3559
3560
3561Local<String> v8::String::New(const uint16_t* data, int length) {
3562 EnsureInitialized("v8::String::New()");
3563 LOG_API("String::New(uint16_)");
3564 if (length == 0) return Empty();
3565 ENTER_V8;
3566 if (length == -1) length = TwoByteStringLength(data);
3567 i::Handle<i::String> result =
3568 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3569 return Utils::ToLocal(result);
3570}
3571
3572
3573Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
3574 EnsureInitialized("v8::String::NewUndetectable()");
3575 LOG_API("String::NewUndetectable(uint16_)");
3576 ENTER_V8;
3577 if (length == -1) length = TwoByteStringLength(data);
3578 i::Handle<i::String> result =
3579 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3580 result->MarkAsUndetectable();
3581 return Utils::ToLocal(result);
3582}
3583
3584
3585i::Handle<i::String> NewExternalStringHandle(
3586 v8::String::ExternalStringResource* resource) {
3587 i::Handle<i::String> result =
3588 i::Factory::NewExternalStringFromTwoByte(resource);
3589 return result;
3590}
3591
3592
3593i::Handle<i::String> NewExternalAsciiStringHandle(
3594 v8::String::ExternalAsciiStringResource* resource) {
3595 i::Handle<i::String> result =
3596 i::Factory::NewExternalStringFromAscii(resource);
3597 return result;
3598}
3599
3600
Steve Blocka7e24c12009-10-30 11:49:00 +00003601Local<String> v8::String::NewExternal(
3602 v8::String::ExternalStringResource* resource) {
3603 EnsureInitialized("v8::String::NewExternal()");
3604 LOG_API("String::NewExternal");
3605 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003606 i::Handle<i::String> result = NewExternalStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003607 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003608 return Utils::ToLocal(result);
3609}
3610
3611
3612bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3613 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3614 if (this->IsExternal()) return false; // Already an external string.
3615 ENTER_V8;
3616 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003617 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003618 bool result = obj->MakeExternal(resource);
3619 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003620 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003621 }
3622 return result;
3623}
3624
3625
3626Local<String> v8::String::NewExternal(
3627 v8::String::ExternalAsciiStringResource* resource) {
3628 EnsureInitialized("v8::String::NewExternal()");
3629 LOG_API("String::NewExternal");
3630 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003631 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003632 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003633 return Utils::ToLocal(result);
3634}
3635
3636
3637bool v8::String::MakeExternal(
3638 v8::String::ExternalAsciiStringResource* resource) {
3639 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3640 if (this->IsExternal()) return false; // Already an external string.
3641 ENTER_V8;
3642 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003643 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003644 bool result = obj->MakeExternal(resource);
3645 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003646 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003647 }
3648 return result;
3649}
3650
3651
3652bool v8::String::CanMakeExternal() {
3653 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3654 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003655 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003656 int size = obj->Size(); // Byte size of the original string.
3657 if (size < i::ExternalString::kSize)
3658 return false;
3659 i::StringShape shape(*obj);
3660 return !shape.IsExternal();
3661}
3662
3663
3664Local<v8::Object> v8::Object::New() {
3665 EnsureInitialized("v8::Object::New()");
3666 LOG_API("Object::New");
3667 ENTER_V8;
3668 i::Handle<i::JSObject> obj =
3669 i::Factory::NewJSObject(i::Top::object_function());
3670 return Utils::ToLocal(obj);
3671}
3672
3673
3674Local<v8::Value> v8::Date::New(double time) {
3675 EnsureInitialized("v8::Date::New()");
3676 LOG_API("Date::New");
Steve Blockd0582a62009-12-15 09:54:21 +00003677 if (isnan(time)) {
3678 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3679 time = i::OS::nan_value();
3680 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003681 ENTER_V8;
3682 EXCEPTION_PREAMBLE();
3683 i::Handle<i::Object> obj =
3684 i::Execution::NewDate(time, &has_pending_exception);
3685 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3686 return Utils::ToLocal(obj);
3687}
3688
3689
3690double v8::Date::NumberValue() const {
3691 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3692 LOG_API("Date::NumberValue");
3693 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3694 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3695 return jsvalue->value()->Number();
3696}
3697
3698
3699Local<v8::Array> v8::Array::New(int length) {
3700 EnsureInitialized("v8::Array::New()");
3701 LOG_API("Array::New");
3702 ENTER_V8;
3703 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3704 return Utils::ToLocal(obj);
3705}
3706
3707
3708uint32_t v8::Array::Length() const {
3709 if (IsDeadCheck("v8::Array::Length()")) return 0;
3710 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3711 i::Object* length = obj->length();
3712 if (length->IsSmi()) {
3713 return i::Smi::cast(length)->value();
3714 } else {
3715 return static_cast<uint32_t>(length->Number());
3716 }
3717}
3718
3719
3720Local<Object> Array::CloneElementAt(uint32_t index) {
3721 ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3722 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3723 if (!self->HasFastElements()) {
3724 return Local<Object>();
3725 }
3726 i::FixedArray* elms = i::FixedArray::cast(self->elements());
3727 i::Object* paragon = elms->get(index);
3728 if (!paragon->IsJSObject()) {
3729 return Local<Object>();
3730 }
3731 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3732 EXCEPTION_PREAMBLE();
Steve Block6ded16b2010-05-10 14:33:55 +01003733 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003734 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3735 has_pending_exception = result.is_null();
3736 EXCEPTION_BAILOUT_CHECK(Local<Object>());
3737 return Utils::ToLocal(result);
3738}
3739
3740
3741Local<String> v8::String::NewSymbol(const char* data, int length) {
3742 EnsureInitialized("v8::String::NewSymbol()");
3743 LOG_API("String::NewSymbol(char)");
3744 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003745 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003746 i::Handle<i::String> result =
3747 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3748 return Utils::ToLocal(result);
3749}
3750
3751
3752Local<Number> v8::Number::New(double value) {
3753 EnsureInitialized("v8::Number::New()");
Steve Blockd0582a62009-12-15 09:54:21 +00003754 if (isnan(value)) {
3755 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3756 value = i::OS::nan_value();
3757 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003758 ENTER_V8;
3759 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3760 return Utils::NumberToLocal(result);
3761}
3762
3763
3764Local<Integer> v8::Integer::New(int32_t value) {
3765 EnsureInitialized("v8::Integer::New()");
3766 if (i::Smi::IsValid(value)) {
3767 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3768 }
3769 ENTER_V8;
3770 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3771 return Utils::IntegerToLocal(result);
3772}
3773
3774
Steve Block3ce2e202009-11-05 08:53:23 +00003775Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
3776 bool fits_into_int32_t = (value & (1 << 31)) == 0;
3777 if (fits_into_int32_t) {
3778 return Integer::New(static_cast<int32_t>(value));
3779 }
3780 ENTER_V8;
3781 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3782 return Utils::IntegerToLocal(result);
3783}
3784
3785
Steve Blocka7e24c12009-10-30 11:49:00 +00003786void V8::IgnoreOutOfMemoryException() {
3787 thread_local.set_ignore_out_of_memory(true);
3788}
3789
3790
3791bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
3792 EnsureInitialized("v8::V8::AddMessageListener()");
3793 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
3794 ENTER_V8;
3795 HandleScope scope;
3796 NeanderArray listeners(i::Factory::message_listeners());
3797 NeanderObject obj(2);
3798 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
3799 obj.set(1, data.IsEmpty() ?
3800 i::Heap::undefined_value() :
3801 *Utils::OpenHandle(*data));
3802 listeners.add(obj.value());
3803 return true;
3804}
3805
3806
3807void V8::RemoveMessageListeners(MessageCallback that) {
3808 EnsureInitialized("v8::V8::RemoveMessageListener()");
3809 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
3810 ENTER_V8;
3811 HandleScope scope;
3812 NeanderArray listeners(i::Factory::message_listeners());
3813 for (int i = 0; i < listeners.length(); i++) {
3814 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
3815
3816 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
3817 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
3818 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
3819 listeners.set(i, i::Heap::undefined_value());
3820 }
3821 }
3822}
3823
3824
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003825void V8::SetCaptureStackTraceForUncaughtExceptions(
3826 bool capture,
3827 int frame_limit,
3828 StackTrace::StackTraceOptions options) {
3829 i::Top::SetCaptureStackTraceForUncaughtExceptions(
3830 capture,
3831 frame_limit,
3832 options);
3833}
3834
3835
Steve Blocka7e24c12009-10-30 11:49:00 +00003836void V8::SetCounterFunction(CounterLookupCallback callback) {
3837 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
3838 i::StatsTable::SetCounterFunction(callback);
3839}
3840
3841void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
3842 if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
3843 i::StatsTable::SetCreateHistogramFunction(callback);
3844}
3845
3846void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
3847 if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
3848 i::StatsTable::SetAddHistogramSampleFunction(callback);
3849}
3850
3851void V8::EnableSlidingStateWindow() {
3852 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
3853 i::Logger::EnableSlidingStateWindow();
3854}
3855
3856
3857void V8::SetFailedAccessCheckCallbackFunction(
3858 FailedAccessCheckCallback callback) {
3859 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
3860 i::Top::SetFailedAccessCheckCallback(callback);
3861}
3862
3863
3864void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
3865 if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
3866 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
3867 i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
3868}
3869
3870
3871int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
3872 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
3873 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
3874}
3875
3876
3877void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
3878 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
3879 i::Heap::SetGlobalGCPrologueCallback(callback);
3880}
3881
3882
3883void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
3884 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
3885 i::Heap::SetGlobalGCEpilogueCallback(callback);
3886}
3887
3888
Steve Block6ded16b2010-05-10 14:33:55 +01003889void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
3890 if (IsDeadCheck("v8::V8::AddGCPrologueCallback()")) return;
3891 i::Heap::AddGCPrologueCallback(callback, gc_type);
3892}
3893
3894
3895void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
3896 if (IsDeadCheck("v8::V8::RemoveGCPrologueCallback()")) return;
3897 i::Heap::RemoveGCPrologueCallback(callback);
3898}
3899
3900
3901void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
3902 if (IsDeadCheck("v8::V8::AddGCEpilogueCallback()")) return;
3903 i::Heap::AddGCEpilogueCallback(callback, gc_type);
3904}
3905
3906
3907void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
3908 if (IsDeadCheck("v8::V8::RemoveGCEpilogueCallback()")) return;
3909 i::Heap::RemoveGCEpilogueCallback(callback);
3910}
3911
3912
Iain Merrick9ac36c92010-09-13 15:29:50 +01003913void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
3914 ObjectSpace space,
3915 AllocationAction action) {
3916 if (IsDeadCheck("v8::V8::AddMemoryAllocationCallback()")) return;
3917 i::MemoryAllocator::AddMemoryAllocationCallback(callback,
3918 space,
3919 action);
3920}
3921
3922
3923void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
3924 if (IsDeadCheck("v8::V8::RemoveMemoryAllocationCallback()")) return;
3925 i::MemoryAllocator::RemoveMemoryAllocationCallback(callback);
3926}
3927
3928
Steve Blocka7e24c12009-10-30 11:49:00 +00003929void V8::PauseProfiler() {
3930#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003931 PauseProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003932#endif
3933}
3934
3935
3936void V8::ResumeProfiler() {
3937#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003938 ResumeProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003939#endif
3940}
3941
3942
3943bool V8::IsProfilerPaused() {
3944#ifdef ENABLE_LOGGING_AND_PROFILING
3945 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
3946#else
3947 return true;
3948#endif
3949}
3950
3951
Andrei Popescu402d9372010-02-26 13:31:12 +00003952void V8::ResumeProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003953#ifdef ENABLE_LOGGING_AND_PROFILING
3954 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
3955 // Snapshot mode: resume modules, perform GC, then pause only
3956 // those modules which haven't been started prior to making a
3957 // snapshot.
3958
Steve Block6ded16b2010-05-10 14:33:55 +01003959 // Make a GC prior to taking a snapshot.
3960 i::Heap::CollectAllGarbage(false);
Steve Blocka7e24c12009-10-30 11:49:00 +00003961 // Reset snapshot flag and CPU module flags.
3962 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
3963 const int current_flags = i::Logger::GetActiveProfilerModules();
Andrei Popescu402d9372010-02-26 13:31:12 +00003964 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003965 i::Heap::CollectAllGarbage(false);
Andrei Popescu402d9372010-02-26 13:31:12 +00003966 i::Logger::PauseProfiler(~current_flags & flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003967 } else {
Andrei Popescu402d9372010-02-26 13:31:12 +00003968 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003969 }
3970#endif
3971}
3972
3973
Andrei Popescu402d9372010-02-26 13:31:12 +00003974void V8::PauseProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003975#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003976 i::Logger::PauseProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003977#endif
3978}
3979
3980
3981int V8::GetActiveProfilerModules() {
3982#ifdef ENABLE_LOGGING_AND_PROFILING
3983 return i::Logger::GetActiveProfilerModules();
3984#else
3985 return PROFILER_MODULE_NONE;
3986#endif
3987}
3988
3989
3990int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
3991#ifdef ENABLE_LOGGING_AND_PROFILING
Steve Block6ded16b2010-05-10 14:33:55 +01003992 ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
Steve Blocka7e24c12009-10-30 11:49:00 +00003993 return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
3994#endif
3995 return 0;
3996}
3997
3998
3999int V8::GetCurrentThreadId() {
4000 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
4001 EnsureInitialized("V8::GetCurrentThreadId()");
4002 return i::Top::thread_id();
4003}
4004
4005
4006void V8::TerminateExecution(int thread_id) {
4007 if (!i::V8::IsRunning()) return;
4008 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
4009 // If the thread_id identifies the current thread just terminate
4010 // execution right away. Otherwise, ask the thread manager to
4011 // terminate the thread with the given id if any.
4012 if (thread_id == i::Top::thread_id()) {
4013 i::StackGuard::TerminateExecution();
4014 } else {
4015 i::ThreadManager::TerminateExecution(thread_id);
4016 }
4017}
4018
4019
4020void V8::TerminateExecution() {
4021 if (!i::V8::IsRunning()) return;
4022 i::StackGuard::TerminateExecution();
4023}
4024
4025
Steve Block6ded16b2010-05-10 14:33:55 +01004026bool V8::IsExecutionTerminating() {
4027 if (!i::V8::IsRunning()) return false;
4028 if (i::Top::has_scheduled_exception()) {
4029 return i::Top::scheduled_exception() == i::Heap::termination_exception();
4030 }
4031 return false;
4032}
4033
4034
Steve Blocka7e24c12009-10-30 11:49:00 +00004035String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
4036 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
4037 if (obj.IsEmpty()) {
4038 str_ = NULL;
4039 length_ = 0;
4040 return;
4041 }
4042 ENTER_V8;
4043 HandleScope scope;
4044 TryCatch try_catch;
4045 Handle<String> str = obj->ToString();
4046 if (str.IsEmpty()) {
4047 str_ = NULL;
4048 length_ = 0;
4049 } else {
4050 length_ = str->Utf8Length();
4051 str_ = i::NewArray<char>(length_ + 1);
4052 str->WriteUtf8(str_);
4053 }
4054}
4055
4056
4057String::Utf8Value::~Utf8Value() {
4058 i::DeleteArray(str_);
4059}
4060
4061
4062String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
4063 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
4064 if (obj.IsEmpty()) {
4065 str_ = NULL;
4066 length_ = 0;
4067 return;
4068 }
4069 ENTER_V8;
4070 HandleScope scope;
4071 TryCatch try_catch;
4072 Handle<String> str = obj->ToString();
4073 if (str.IsEmpty()) {
4074 str_ = NULL;
4075 length_ = 0;
4076 } else {
4077 length_ = str->Length();
4078 str_ = i::NewArray<char>(length_ + 1);
4079 str->WriteAscii(str_);
4080 }
4081}
4082
4083
4084String::AsciiValue::~AsciiValue() {
4085 i::DeleteArray(str_);
4086}
4087
4088
4089String::Value::Value(v8::Handle<v8::Value> obj) {
4090 EnsureInitialized("v8::String::Value::Value()");
4091 if (obj.IsEmpty()) {
4092 str_ = NULL;
4093 length_ = 0;
4094 return;
4095 }
4096 ENTER_V8;
4097 HandleScope scope;
4098 TryCatch try_catch;
4099 Handle<String> str = obj->ToString();
4100 if (str.IsEmpty()) {
4101 str_ = NULL;
4102 length_ = 0;
4103 } else {
4104 length_ = str->Length();
4105 str_ = i::NewArray<uint16_t>(length_ + 1);
4106 str->Write(str_);
4107 }
4108}
4109
4110
4111String::Value::~Value() {
4112 i::DeleteArray(str_);
4113}
4114
4115Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
4116 LOG_API("RangeError");
4117 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
4118 ENTER_V8;
4119 i::Object* error;
4120 {
4121 HandleScope scope;
4122 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4123 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
4124 error = *result;
4125 }
4126 i::Handle<i::Object> result(error);
4127 return Utils::ToLocal(result);
4128}
4129
4130Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
4131 LOG_API("ReferenceError");
4132 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
4133 ENTER_V8;
4134 i::Object* error;
4135 {
4136 HandleScope scope;
4137 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4138 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
4139 error = *result;
4140 }
4141 i::Handle<i::Object> result(error);
4142 return Utils::ToLocal(result);
4143}
4144
4145Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
4146 LOG_API("SyntaxError");
4147 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
4148 ENTER_V8;
4149 i::Object* error;
4150 {
4151 HandleScope scope;
4152 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4153 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
4154 error = *result;
4155 }
4156 i::Handle<i::Object> result(error);
4157 return Utils::ToLocal(result);
4158}
4159
4160Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
4161 LOG_API("TypeError");
4162 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
4163 ENTER_V8;
4164 i::Object* error;
4165 {
4166 HandleScope scope;
4167 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4168 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
4169 error = *result;
4170 }
4171 i::Handle<i::Object> result(error);
4172 return Utils::ToLocal(result);
4173}
4174
4175Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
4176 LOG_API("Error");
4177 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
4178 ENTER_V8;
4179 i::Object* error;
4180 {
4181 HandleScope scope;
4182 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4183 i::Handle<i::Object> result = i::Factory::NewError(message);
4184 error = *result;
4185 }
4186 i::Handle<i::Object> result(error);
4187 return Utils::ToLocal(result);
4188}
4189
4190
4191// --- D e b u g S u p p o r t ---
4192
4193#ifdef ENABLE_DEBUGGER_SUPPORT
Leon Clarkef7060e22010-06-03 12:02:55 +01004194
4195static v8::Debug::EventCallback event_callback = NULL;
4196
4197static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) {
4198 if (event_callback) {
4199 event_callback(event_details.GetEvent(),
4200 event_details.GetExecutionState(),
4201 event_details.GetEventData(),
4202 event_details.GetCallbackData());
4203 }
4204}
4205
4206
Steve Blocka7e24c12009-10-30 11:49:00 +00004207bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
4208 EnsureInitialized("v8::Debug::SetDebugEventListener()");
4209 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4210 ENTER_V8;
Leon Clarkef7060e22010-06-03 12:02:55 +01004211
4212 event_callback = that;
4213
4214 HandleScope scope;
4215 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4216 if (that != NULL) {
4217 proxy = i::Factory::NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
4218 }
4219 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4220 return true;
4221}
4222
4223
4224bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
4225 EnsureInitialized("v8::Debug::SetDebugEventListener2()");
4226 ON_BAILOUT("v8::Debug::SetDebugEventListener2()", return false);
4227 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004228 HandleScope scope;
4229 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4230 if (that != NULL) {
4231 proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
4232 }
4233 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4234 return true;
4235}
4236
4237
4238bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
4239 Handle<Value> data) {
4240 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4241 ENTER_V8;
4242 i::Debugger::SetEventListener(Utils::OpenHandle(*that),
4243 Utils::OpenHandle(*data));
4244 return true;
4245}
4246
4247
4248void Debug::DebugBreak() {
4249 if (!i::V8::IsRunning()) return;
4250 i::StackGuard::DebugBreak();
4251}
4252
4253
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004254void Debug::DebugBreakForCommand(ClientData* data) {
4255 if (!i::V8::IsRunning()) return;
4256 i::Debugger::EnqueueDebugCommand(data);
4257}
4258
4259
Steve Blocka7e24c12009-10-30 11:49:00 +00004260static v8::Debug::MessageHandler message_handler = NULL;
4261
4262static void MessageHandlerWrapper(const v8::Debug::Message& message) {
4263 if (message_handler) {
4264 v8::String::Value json(message.GetJSON());
4265 message_handler(*json, json.length(), message.GetClientData());
4266 }
4267}
4268
4269
4270void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
4271 bool message_handler_thread) {
4272 EnsureInitialized("v8::Debug::SetMessageHandler");
4273 ENTER_V8;
4274 // Message handler thread not supported any more. Parameter temporally left in
4275 // the API for client compatability reasons.
4276 CHECK(!message_handler_thread);
4277
4278 // TODO(sgjesse) support the old message handler API through a simple wrapper.
4279 message_handler = handler;
4280 if (message_handler != NULL) {
4281 i::Debugger::SetMessageHandler(MessageHandlerWrapper);
4282 } else {
4283 i::Debugger::SetMessageHandler(NULL);
4284 }
4285}
4286
4287
4288void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
4289 EnsureInitialized("v8::Debug::SetMessageHandler");
4290 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004291 i::Debugger::SetMessageHandler(handler);
4292}
4293
4294
4295void Debug::SendCommand(const uint16_t* command, int length,
4296 ClientData* client_data) {
4297 if (!i::V8::IsRunning()) return;
4298 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
4299 client_data);
4300}
4301
4302
4303void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
4304 int period) {
4305 EnsureInitialized("v8::Debug::SetHostDispatchHandler");
4306 ENTER_V8;
4307 i::Debugger::SetHostDispatchHandler(handler, period);
4308}
4309
4310
Steve Blockd0582a62009-12-15 09:54:21 +00004311void Debug::SetDebugMessageDispatchHandler(
Leon Clarkee46be812010-01-19 14:06:41 +00004312 DebugMessageDispatchHandler handler, bool provide_locker) {
Steve Blockd0582a62009-12-15 09:54:21 +00004313 EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
4314 ENTER_V8;
Leon Clarkee46be812010-01-19 14:06:41 +00004315 i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
Steve Blockd0582a62009-12-15 09:54:21 +00004316}
4317
4318
Steve Blocka7e24c12009-10-30 11:49:00 +00004319Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
4320 v8::Handle<v8::Value> data) {
4321 if (!i::V8::IsRunning()) return Local<Value>();
4322 ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
4323 ENTER_V8;
4324 i::Handle<i::Object> result;
4325 EXCEPTION_PREAMBLE();
4326 if (data.IsEmpty()) {
4327 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4328 i::Factory::undefined_value(),
4329 &has_pending_exception);
4330 } else {
4331 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4332 Utils::OpenHandle(*data),
4333 &has_pending_exception);
4334 }
4335 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4336 return Utils::ToLocal(result);
4337}
4338
4339
4340Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
4341 if (!i::V8::IsRunning()) return Local<Value>();
4342 ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
4343 ENTER_V8;
4344 v8::HandleScope scope;
4345 i::Debug::Load();
4346 i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
4347 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
4348 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
4349 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
4350 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
4351 const int kArgc = 1;
4352 v8::Handle<v8::Value> argv[kArgc] = { obj };
4353 EXCEPTION_PREAMBLE();
4354 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
4355 kArgc,
4356 argv);
4357 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4358 return scope.Close(result);
4359}
4360
4361
Leon Clarkee46be812010-01-19 14:06:41 +00004362bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
4363 return i::Debugger::StartAgent(name, port, wait_for_connection);
Steve Blocka7e24c12009-10-30 11:49:00 +00004364}
Leon Clarkee46be812010-01-19 14:06:41 +00004365
4366void Debug::ProcessDebugMessages() {
4367 i::Execution::ProcessDebugMesssages(true);
4368}
4369
Steve Block6ded16b2010-05-10 14:33:55 +01004370Local<Context> Debug::GetDebugContext() {
4371 EnsureInitialized("v8::Debug::GetDebugContext()");
4372 ENTER_V8;
4373 return Utils::ToLocal(i::Debugger::GetDebugContext());
4374}
4375
Steve Blocka7e24c12009-10-30 11:49:00 +00004376#endif // ENABLE_DEBUGGER_SUPPORT
4377
Steve Block6ded16b2010-05-10 14:33:55 +01004378
4379#ifdef ENABLE_LOGGING_AND_PROFILING
4380
4381Handle<String> CpuProfileNode::GetFunctionName() const {
4382 IsDeadCheck("v8::CpuProfileNode::GetFunctionName");
4383 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4384 const i::CodeEntry* entry = node->entry();
4385 if (!entry->has_name_prefix()) {
4386 return Handle<String>(ToApi<String>(
4387 i::Factory::LookupAsciiSymbol(entry->name())));
4388 } else {
4389 return Handle<String>(ToApi<String>(i::Factory::NewConsString(
4390 i::Factory::LookupAsciiSymbol(entry->name_prefix()),
4391 i::Factory::LookupAsciiSymbol(entry->name()))));
4392 }
4393}
4394
4395
4396Handle<String> CpuProfileNode::GetScriptResourceName() const {
4397 IsDeadCheck("v8::CpuProfileNode::GetScriptResourceName");
4398 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4399 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4400 node->entry()->resource_name())));
4401}
4402
4403
4404int CpuProfileNode::GetLineNumber() const {
4405 IsDeadCheck("v8::CpuProfileNode::GetLineNumber");
4406 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
4407}
4408
4409
4410double CpuProfileNode::GetTotalTime() const {
4411 IsDeadCheck("v8::CpuProfileNode::GetTotalTime");
4412 return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis();
4413}
4414
4415
4416double CpuProfileNode::GetSelfTime() const {
4417 IsDeadCheck("v8::CpuProfileNode::GetSelfTime");
4418 return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis();
4419}
4420
4421
4422double CpuProfileNode::GetTotalSamplesCount() const {
4423 IsDeadCheck("v8::CpuProfileNode::GetTotalSamplesCount");
4424 return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
4425}
4426
4427
4428double CpuProfileNode::GetSelfSamplesCount() const {
4429 IsDeadCheck("v8::CpuProfileNode::GetSelfSamplesCount");
4430 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
4431}
4432
4433
4434unsigned CpuProfileNode::GetCallUid() const {
4435 IsDeadCheck("v8::CpuProfileNode::GetCallUid");
4436 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->call_uid();
4437}
4438
4439
4440int CpuProfileNode::GetChildrenCount() const {
4441 IsDeadCheck("v8::CpuProfileNode::GetChildrenCount");
4442 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
4443}
4444
4445
4446const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
4447 IsDeadCheck("v8::CpuProfileNode::GetChild");
4448 const i::ProfileNode* child =
4449 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
4450 return reinterpret_cast<const CpuProfileNode*>(child);
4451}
4452
4453
4454unsigned CpuProfile::GetUid() const {
4455 IsDeadCheck("v8::CpuProfile::GetUid");
4456 return reinterpret_cast<const i::CpuProfile*>(this)->uid();
4457}
4458
4459
4460Handle<String> CpuProfile::GetTitle() const {
4461 IsDeadCheck("v8::CpuProfile::GetTitle");
4462 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4463 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4464 profile->title())));
4465}
4466
4467
4468const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
4469 IsDeadCheck("v8::CpuProfile::GetBottomUpRoot");
4470 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4471 return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
4472}
4473
4474
4475const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
4476 IsDeadCheck("v8::CpuProfile::GetTopDownRoot");
4477 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4478 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
4479}
4480
4481
4482int CpuProfiler::GetProfilesCount() {
4483 IsDeadCheck("v8::CpuProfiler::GetProfilesCount");
4484 return i::CpuProfiler::GetProfilesCount();
4485}
4486
4487
Leon Clarkef7060e22010-06-03 12:02:55 +01004488const CpuProfile* CpuProfiler::GetProfile(int index,
4489 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004490 IsDeadCheck("v8::CpuProfiler::GetProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004491 return reinterpret_cast<const CpuProfile*>(
4492 i::CpuProfiler::GetProfile(
4493 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4494 index));
Steve Block6ded16b2010-05-10 14:33:55 +01004495}
4496
4497
Leon Clarkef7060e22010-06-03 12:02:55 +01004498const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
4499 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004500 IsDeadCheck("v8::CpuProfiler::FindProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004501 return reinterpret_cast<const CpuProfile*>(
4502 i::CpuProfiler::FindProfile(
4503 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4504 uid));
Steve Block6ded16b2010-05-10 14:33:55 +01004505}
4506
4507
4508void CpuProfiler::StartProfiling(Handle<String> title) {
4509 IsDeadCheck("v8::CpuProfiler::StartProfiling");
4510 i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
4511}
4512
4513
Leon Clarkef7060e22010-06-03 12:02:55 +01004514const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
4515 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004516 IsDeadCheck("v8::CpuProfiler::StopProfiling");
4517 return reinterpret_cast<const CpuProfile*>(
Leon Clarkef7060e22010-06-03 12:02:55 +01004518 i::CpuProfiler::StopProfiling(
4519 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4520 *Utils::OpenHandle(*title)));
Steve Block6ded16b2010-05-10 14:33:55 +01004521}
4522
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004523
Iain Merrick75681382010-08-19 15:07:18 +01004524static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
4525 return const_cast<i::HeapGraphEdge*>(
4526 reinterpret_cast<const i::HeapGraphEdge*>(edge));
4527}
4528
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004529HeapGraphEdge::Type HeapGraphEdge::GetType() const {
4530 IsDeadCheck("v8::HeapGraphEdge::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004531 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004532}
4533
4534
4535Handle<Value> HeapGraphEdge::GetName() const {
4536 IsDeadCheck("v8::HeapGraphEdge::GetName");
Iain Merrick75681382010-08-19 15:07:18 +01004537 i::HeapGraphEdge* edge = ToInternal(this);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004538 switch (edge->type()) {
Iain Merrick75681382010-08-19 15:07:18 +01004539 case i::HeapGraphEdge::kContextVariable:
4540 case i::HeapGraphEdge::kInternal:
4541 case i::HeapGraphEdge::kProperty:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004542 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4543 edge->name())));
Iain Merrick75681382010-08-19 15:07:18 +01004544 case i::HeapGraphEdge::kElement:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004545 return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt(
4546 edge->index())));
4547 default: UNREACHABLE();
4548 }
4549 return ImplementationUtilities::Undefined();
4550}
4551
4552
4553const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
4554 IsDeadCheck("v8::HeapGraphEdge::GetFromNode");
Iain Merrick75681382010-08-19 15:07:18 +01004555 const i::HeapEntry* from = ToInternal(this)->From();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004556 return reinterpret_cast<const HeapGraphNode*>(from);
4557}
4558
4559
4560const HeapGraphNode* HeapGraphEdge::GetToNode() const {
4561 IsDeadCheck("v8::HeapGraphEdge::GetToNode");
Iain Merrick75681382010-08-19 15:07:18 +01004562 const i::HeapEntry* to = ToInternal(this)->to();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004563 return reinterpret_cast<const HeapGraphNode*>(to);
4564}
4565
4566
Iain Merrick75681382010-08-19 15:07:18 +01004567static i::HeapGraphPath* ToInternal(const HeapGraphPath* path) {
4568 return const_cast<i::HeapGraphPath*>(
4569 reinterpret_cast<const i::HeapGraphPath*>(path));
4570}
4571
4572
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004573int HeapGraphPath::GetEdgesCount() const {
Iain Merrick75681382010-08-19 15:07:18 +01004574 return ToInternal(this)->path()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004575}
4576
4577
4578const HeapGraphEdge* HeapGraphPath::GetEdge(int index) const {
4579 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004580 ToInternal(this)->path()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004581}
4582
4583
4584const HeapGraphNode* HeapGraphPath::GetFromNode() const {
4585 return GetEdgesCount() > 0 ? GetEdge(0)->GetFromNode() : NULL;
4586}
4587
4588
4589const HeapGraphNode* HeapGraphPath::GetToNode() const {
4590 const int count = GetEdgesCount();
4591 return count > 0 ? GetEdge(count - 1)->GetToNode() : NULL;
4592}
4593
4594
Iain Merrick75681382010-08-19 15:07:18 +01004595static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
4596 return const_cast<i::HeapEntry*>(
4597 reinterpret_cast<const i::HeapEntry*>(entry));
4598}
4599
4600
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004601HeapGraphNode::Type HeapGraphNode::GetType() const {
4602 IsDeadCheck("v8::HeapGraphNode::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004603 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004604}
4605
4606
4607Handle<String> HeapGraphNode::GetName() const {
4608 IsDeadCheck("v8::HeapGraphNode::GetName");
4609 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004610 ToInternal(this)->name())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004611}
4612
4613
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004614uint64_t HeapGraphNode::GetId() const {
4615 IsDeadCheck("v8::HeapGraphNode::GetId");
Steve Block791712a2010-08-27 10:21:07 +01004616 ASSERT(ToInternal(this)->snapshot()->type() != i::HeapSnapshot::kAggregated);
Iain Merrick75681382010-08-19 15:07:18 +01004617 return ToInternal(this)->id();
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004618}
4619
4620
Steve Block791712a2010-08-27 10:21:07 +01004621int HeapGraphNode::GetInstancesCount() const {
4622 IsDeadCheck("v8::HeapGraphNode::GetInstancesCount");
4623 ASSERT(ToInternal(this)->snapshot()->type() == i::HeapSnapshot::kAggregated);
4624 return static_cast<int>(ToInternal(this)->id());
4625}
4626
4627
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004628int HeapGraphNode::GetSelfSize() const {
4629 IsDeadCheck("v8::HeapGraphNode::GetSelfSize");
Iain Merrick75681382010-08-19 15:07:18 +01004630 return ToInternal(this)->self_size();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004631}
4632
4633
Iain Merrick75681382010-08-19 15:07:18 +01004634int HeapGraphNode::GetReachableSize() const {
4635 IsDeadCheck("v8::HeapSnapshot::GetReachableSize");
4636 return ToInternal(this)->ReachableSize();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004637}
4638
4639
Iain Merrick75681382010-08-19 15:07:18 +01004640int HeapGraphNode::GetRetainedSize() const {
4641 IsDeadCheck("v8::HeapSnapshot::GetRetainedSize");
4642 return ToInternal(this)->RetainedSize();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004643}
4644
4645
4646int HeapGraphNode::GetChildrenCount() const {
4647 IsDeadCheck("v8::HeapSnapshot::GetChildrenCount");
Iain Merrick75681382010-08-19 15:07:18 +01004648 return ToInternal(this)->children().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004649}
4650
4651
4652const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
4653 IsDeadCheck("v8::HeapSnapshot::GetChild");
4654 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004655 &ToInternal(this)->children()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004656}
4657
4658
4659int HeapGraphNode::GetRetainersCount() const {
4660 IsDeadCheck("v8::HeapSnapshot::GetRetainersCount");
Iain Merrick75681382010-08-19 15:07:18 +01004661 return ToInternal(this)->retainers().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004662}
4663
4664
4665const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const {
4666 IsDeadCheck("v8::HeapSnapshot::GetRetainer");
4667 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004668 ToInternal(this)->retainers()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004669}
4670
4671
4672int HeapGraphNode::GetRetainingPathsCount() const {
4673 IsDeadCheck("v8::HeapSnapshot::GetRetainingPathsCount");
Iain Merrick75681382010-08-19 15:07:18 +01004674 return ToInternal(this)->GetRetainingPaths()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004675}
4676
4677
4678const HeapGraphPath* HeapGraphNode::GetRetainingPath(int index) const {
4679 IsDeadCheck("v8::HeapSnapshot::GetRetainingPath");
4680 return reinterpret_cast<const HeapGraphPath*>(
Iain Merrick75681382010-08-19 15:07:18 +01004681 ToInternal(this)->GetRetainingPaths()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004682}
4683
4684
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004685const HeapGraphNode* HeapSnapshotsDiff::GetAdditionsRoot() const {
4686 IsDeadCheck("v8::HeapSnapshotsDiff::GetAdditionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004687 i::HeapSnapshotsDiff* diff =
4688 const_cast<i::HeapSnapshotsDiff*>(
4689 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004690 return reinterpret_cast<const HeapGraphNode*>(diff->additions_root());
4691}
4692
4693
4694const HeapGraphNode* HeapSnapshotsDiff::GetDeletionsRoot() const {
4695 IsDeadCheck("v8::HeapSnapshotsDiff::GetDeletionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004696 i::HeapSnapshotsDiff* diff =
4697 const_cast<i::HeapSnapshotsDiff*>(
4698 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004699 return reinterpret_cast<const HeapGraphNode*>(diff->deletions_root());
4700}
4701
4702
Iain Merrick75681382010-08-19 15:07:18 +01004703static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
4704 return const_cast<i::HeapSnapshot*>(
4705 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
4706}
4707
4708
Steve Block791712a2010-08-27 10:21:07 +01004709HeapSnapshot::Type HeapSnapshot::GetType() const {
4710 IsDeadCheck("v8::HeapSnapshot::GetType");
4711 return static_cast<HeapSnapshot::Type>(ToInternal(this)->type());
4712}
4713
4714
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004715unsigned HeapSnapshot::GetUid() const {
4716 IsDeadCheck("v8::HeapSnapshot::GetUid");
Iain Merrick75681382010-08-19 15:07:18 +01004717 return ToInternal(this)->uid();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004718}
4719
4720
4721Handle<String> HeapSnapshot::GetTitle() const {
4722 IsDeadCheck("v8::HeapSnapshot::GetTitle");
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004723 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004724 ToInternal(this)->title())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004725}
4726
4727
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004728const HeapGraphNode* HeapSnapshot::GetRoot() const {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004729 IsDeadCheck("v8::HeapSnapshot::GetHead");
Iain Merrick75681382010-08-19 15:07:18 +01004730 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004731}
4732
4733
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004734const HeapSnapshotsDiff* HeapSnapshot::CompareWith(
4735 const HeapSnapshot* snapshot) const {
4736 IsDeadCheck("v8::HeapSnapshot::CompareWith");
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004737 return reinterpret_cast<const HeapSnapshotsDiff*>(
Iain Merrick75681382010-08-19 15:07:18 +01004738 ToInternal(this)->CompareWith(ToInternal(snapshot)));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004739}
4740
4741
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004742int HeapProfiler::GetSnapshotsCount() {
4743 IsDeadCheck("v8::HeapProfiler::GetSnapshotsCount");
4744 return i::HeapProfiler::GetSnapshotsCount();
4745}
4746
4747
4748const HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
4749 IsDeadCheck("v8::HeapProfiler::GetSnapshot");
4750 return reinterpret_cast<const HeapSnapshot*>(
4751 i::HeapProfiler::GetSnapshot(index));
4752}
4753
4754
4755const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
4756 IsDeadCheck("v8::HeapProfiler::FindSnapshot");
4757 return reinterpret_cast<const HeapSnapshot*>(
4758 i::HeapProfiler::FindSnapshot(uid));
4759}
4760
4761
Steve Block791712a2010-08-27 10:21:07 +01004762const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title,
4763 HeapSnapshot::Type type) {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004764 IsDeadCheck("v8::HeapProfiler::TakeSnapshot");
Steve Block791712a2010-08-27 10:21:07 +01004765 i::HeapSnapshot::Type internal_type = i::HeapSnapshot::kFull;
4766 switch (type) {
4767 case HeapSnapshot::kFull:
4768 internal_type = i::HeapSnapshot::kFull;
4769 break;
4770 case HeapSnapshot::kAggregated:
4771 internal_type = i::HeapSnapshot::kAggregated;
4772 break;
4773 default:
4774 UNREACHABLE();
4775 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004776 return reinterpret_cast<const HeapSnapshot*>(
Steve Block791712a2010-08-27 10:21:07 +01004777 i::HeapProfiler::TakeSnapshot(*Utils::OpenHandle(*title), internal_type));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004778}
4779
Steve Block6ded16b2010-05-10 14:33:55 +01004780#endif // ENABLE_LOGGING_AND_PROFILING
4781
4782
Steve Blocka7e24c12009-10-30 11:49:00 +00004783namespace internal {
4784
4785
4786HandleScopeImplementer* HandleScopeImplementer::instance() {
4787 return &thread_local;
4788}
4789
4790
4791void HandleScopeImplementer::FreeThreadResources() {
4792 thread_local.Free();
4793}
4794
4795
4796char* HandleScopeImplementer::ArchiveThread(char* storage) {
4797 return thread_local.ArchiveThreadHelper(storage);
4798}
4799
4800
4801char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
4802 v8::ImplementationUtilities::HandleScopeData* current =
4803 v8::ImplementationUtilities::CurrentHandleScope();
4804 handle_scope_data_ = *current;
4805 memcpy(storage, this, sizeof(*this));
4806
4807 ResetAfterArchive();
4808 current->Initialize();
4809
4810 return storage + ArchiveSpacePerThread();
4811}
4812
4813
4814int HandleScopeImplementer::ArchiveSpacePerThread() {
4815 return sizeof(thread_local);
4816}
4817
4818
4819char* HandleScopeImplementer::RestoreThread(char* storage) {
4820 return thread_local.RestoreThreadHelper(storage);
4821}
4822
4823
4824char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
4825 memcpy(this, storage, sizeof(*this));
4826 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
4827 return storage + ArchiveSpacePerThread();
4828}
4829
4830
4831void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
4832 // Iterate over all handles in the blocks except for the last.
4833 for (int i = blocks()->length() - 2; i >= 0; --i) {
4834 Object** block = blocks()->at(i);
4835 v->VisitPointers(block, &block[kHandleBlockSize]);
4836 }
4837
4838 // Iterate over live handles in the last block (if any).
4839 if (!blocks()->is_empty()) {
4840 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
4841 }
4842
4843 if (!saved_contexts_.is_empty()) {
4844 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
4845 v->VisitPointers(start, start + saved_contexts_.length());
4846 }
4847}
4848
4849
4850void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
4851 v8::ImplementationUtilities::HandleScopeData* current =
4852 v8::ImplementationUtilities::CurrentHandleScope();
4853 thread_local.handle_scope_data_ = *current;
4854 thread_local.IterateThis(v);
4855}
4856
4857
4858char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
4859 HandleScopeImplementer* thread_local =
4860 reinterpret_cast<HandleScopeImplementer*>(storage);
4861 thread_local->IterateThis(v);
4862 return storage + ArchiveSpacePerThread();
4863}
4864
4865} } // namespace v8::internal