blob: ee7ad3a5dd7ea810306f3c48c6d5c9047218e665 [file] [log] [blame]
Ben Murdochf87a2032010-10-22 12:50:53 +01001// Copyright 2010 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// 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"
Ben Murdochf87a2032010-10-22 12:50:53 +010031
Steve Blocka7e24c12009-10-30 11:49:00 +000032#include "arguments.h"
33#include "bootstrapper.h"
34#include "compiler.h"
35#include "debug.h"
36#include "execution.h"
37#include "global-handles.h"
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010038#include "heap-profiler.h"
Steve Block6ded16b2010-05-10 14:33:55 +010039#include "messages.h"
Ben Murdochf87a2032010-10-22 12:50:53 +010040#include "parser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000041#include "platform.h"
Steve Block6ded16b2010-05-10 14:33:55 +010042#include "profile-generator-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000043#include "serialize.h"
44#include "snapshot.h"
Steve Block6ded16b2010-05-10 14:33:55 +010045#include "top.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000046#include "v8threads.h"
47#include "version.h"
48
Steve Block6ded16b2010-05-10 14:33:55 +010049#include "../include/v8-profiler.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000050
51#define LOG_API(expr) LOG(ApiEntryCall(expr))
52
Leon Clarkef7060e22010-06-03 12:02:55 +010053#ifdef ENABLE_VMSTATE_TRACKING
Steve Blocka7e24c12009-10-30 11:49:00 +000054#define ENTER_V8 i::VMState __state__(i::OTHER)
55#define LEAVE_V8 i::VMState __state__(i::EXTERNAL)
56#else
57#define ENTER_V8 ((void) 0)
58#define LEAVE_V8 ((void) 0)
59#endif
60
61namespace v8 {
62
Leon Clarkef7060e22010-06-03 12:02:55 +010063#define ON_BAILOUT(location, code) \
64 if (IsDeadCheck(location) || v8::V8::IsExecutionTerminating()) { \
65 code; \
66 UNREACHABLE(); \
Steve Blocka7e24c12009-10-30 11:49:00 +000067 }
68
69
70#define EXCEPTION_PREAMBLE() \
71 thread_local.IncrementCallDepth(); \
72 ASSERT(!i::Top::external_caught_exception()); \
73 bool has_pending_exception = false
74
75
76#define EXCEPTION_BAILOUT_CHECK(value) \
77 do { \
78 thread_local.DecrementCallDepth(); \
79 if (has_pending_exception) { \
80 if (thread_local.CallDepthIsZero() && i::Top::is_out_of_memory()) { \
81 if (!thread_local.ignore_out_of_memory()) \
82 i::V8::FatalProcessOutOfMemory(NULL); \
83 } \
84 bool call_depth_is_zero = thread_local.CallDepthIsZero(); \
85 i::Top::OptionalRescheduleException(call_depth_is_zero); \
86 return value; \
87 } \
88 } while (false)
89
90
91#define API_ENTRY_CHECK(msg) \
92 do { \
93 if (v8::Locker::IsActive()) { \
94 ApiCheck(i::ThreadManager::IsLockedByCurrentThread(), \
95 msg, \
96 "Entering the V8 API without proper locking in place"); \
97 } \
98 } while (false)
99
100// --- 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 ---
101
102
103static i::HandleScopeImplementer thread_local;
104
105
106// --- E x c e p t i o n B e h a v i o r ---
107
108
109static FatalErrorCallback exception_behavior = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000110
111static void DefaultFatalErrorHandler(const char* location,
112 const char* message) {
113 ENTER_V8;
114 API_Fatal(location, message);
115}
116
117
118
119static FatalErrorCallback& GetFatalErrorHandler() {
120 if (exception_behavior == NULL) {
121 exception_behavior = DefaultFatalErrorHandler;
122 }
123 return exception_behavior;
124}
125
126
127
128// When V8 cannot allocated memory FatalProcessOutOfMemory is called.
129// The default fatal error handler is called and execution is stopped.
Ben Murdochbb769b22010-08-11 14:56:33 +0100130void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
Steve Blockd0582a62009-12-15 09:54:21 +0000131 i::HeapStats heap_stats;
132 int start_marker;
133 heap_stats.start_marker = &start_marker;
134 int new_space_size;
135 heap_stats.new_space_size = &new_space_size;
136 int new_space_capacity;
137 heap_stats.new_space_capacity = &new_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100138 intptr_t old_pointer_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000139 heap_stats.old_pointer_space_size = &old_pointer_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100140 intptr_t old_pointer_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000141 heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100142 intptr_t old_data_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000143 heap_stats.old_data_space_size = &old_data_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100144 intptr_t old_data_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000145 heap_stats.old_data_space_capacity = &old_data_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100146 intptr_t code_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000147 heap_stats.code_space_size = &code_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100148 intptr_t code_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000149 heap_stats.code_space_capacity = &code_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100150 intptr_t map_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000151 heap_stats.map_space_size = &map_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100152 intptr_t map_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000153 heap_stats.map_space_capacity = &map_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100154 intptr_t cell_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000155 heap_stats.cell_space_size = &cell_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100156 intptr_t cell_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000157 heap_stats.cell_space_capacity = &cell_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100158 intptr_t lo_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000159 heap_stats.lo_space_size = &lo_space_size;
160 int global_handle_count;
161 heap_stats.global_handle_count = &global_handle_count;
162 int weak_global_handle_count;
163 heap_stats.weak_global_handle_count = &weak_global_handle_count;
164 int pending_global_handle_count;
165 heap_stats.pending_global_handle_count = &pending_global_handle_count;
166 int near_death_global_handle_count;
167 heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
168 int destroyed_global_handle_count;
169 heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count;
Ben Murdochf87a2032010-10-22 12:50:53 +0100170 intptr_t memory_allocator_size;
Ben Murdochbb769b22010-08-11 14:56:33 +0100171 heap_stats.memory_allocator_size = &memory_allocator_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100172 intptr_t memory_allocator_capacity;
Ben Murdochbb769b22010-08-11 14:56:33 +0100173 heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
174 int objects_per_type[LAST_TYPE + 1] = {0};
175 heap_stats.objects_per_type = objects_per_type;
176 int size_per_type[LAST_TYPE + 1] = {0};
177 heap_stats.size_per_type = size_per_type;
Iain Merrick75681382010-08-19 15:07:18 +0100178 int os_error;
179 heap_stats.os_error = &os_error;
Steve Blockd0582a62009-12-15 09:54:21 +0000180 int end_marker;
181 heap_stats.end_marker = &end_marker;
Ben Murdochbb769b22010-08-11 14:56:33 +0100182 i::Heap::RecordStats(&heap_stats, take_snapshot);
Steve Blocka7e24c12009-10-30 11:49:00 +0000183 i::V8::SetFatalError();
184 FatalErrorCallback callback = GetFatalErrorHandler();
185 {
186 LEAVE_V8;
187 callback(location, "Allocation failed - process out of memory");
188 }
189 // If the callback returns, we stop execution.
190 UNREACHABLE();
191}
192
193
194void V8::SetFatalErrorHandler(FatalErrorCallback that) {
195 exception_behavior = that;
196}
197
198
199bool Utils::ReportApiFailure(const char* location, const char* message) {
200 FatalErrorCallback callback = GetFatalErrorHandler();
201 callback(location, message);
202 i::V8::SetFatalError();
203 return false;
204}
205
206
207bool V8::IsDead() {
208 return i::V8::IsDead();
209}
210
211
212static inline bool ApiCheck(bool condition,
213 const char* location,
214 const char* message) {
215 return condition ? true : Utils::ReportApiFailure(location, message);
216}
217
218
219static bool ReportV8Dead(const char* location) {
220 FatalErrorCallback callback = GetFatalErrorHandler();
221 callback(location, "V8 is no longer usable");
222 return true;
223}
224
225
226static bool ReportEmptyHandle(const char* location) {
227 FatalErrorCallback callback = GetFatalErrorHandler();
228 callback(location, "Reading from empty handle");
229 return true;
230}
231
232
233/**
234 * IsDeadCheck checks that the vm is usable. If, for instance, the vm has been
235 * out of memory at some point this check will fail. It should be called on
236 * entry to all methods that touch anything in the heap, except destructors
237 * which you sometimes can't avoid calling after the vm has crashed. Functions
238 * that call EnsureInitialized or ON_BAILOUT don't have to also call
239 * IsDeadCheck. ON_BAILOUT has the advantage over EnsureInitialized that you
240 * can arrange to return if the VM is dead. This is needed to ensure that no VM
241 * heap allocations are attempted on a dead VM. EnsureInitialized has the
242 * advantage over ON_BAILOUT that it actually initializes the VM if this has not
243 * yet been done.
244 */
245static inline bool IsDeadCheck(const char* location) {
246 return !i::V8::IsRunning()
247 && i::V8::IsDead() ? ReportV8Dead(location) : false;
248}
249
250
251static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
252 return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
253}
254
255
256static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
257 return (obj == 0) ? ReportEmptyHandle(location) : false;
258}
259
260// --- S t a t i c s ---
261
262
263static i::StringInputBuffer write_input_buffer;
264
265
266static inline bool EnsureInitialized(const char* location) {
267 if (i::V8::IsRunning()) {
268 return true;
269 }
270 if (IsDeadCheck(location)) {
271 return false;
272 }
273 return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
274}
275
276
277ImplementationUtilities::HandleScopeData*
278 ImplementationUtilities::CurrentHandleScope() {
279 return &i::HandleScope::current_;
280}
281
282
283#ifdef DEBUG
284void ImplementationUtilities::ZapHandleRange(i::Object** begin,
285 i::Object** end) {
286 i::HandleScope::ZapRange(begin, end);
287}
288#endif
289
290
291v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
292 if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
293 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
294}
295
296
297v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
298 if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
299 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
300}
301
302
303v8::Handle<v8::Boolean> ImplementationUtilities::True() {
304 if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
305 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
306}
307
308
309v8::Handle<v8::Boolean> ImplementationUtilities::False() {
310 if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
311 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
312}
313
314
315void V8::SetFlagsFromString(const char* str, int length) {
316 i::FlagList::SetFlagsFromString(str, length);
317}
318
319
320void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
321 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
322}
323
324
325v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
326 if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
327 ENTER_V8;
328 // If we're passed an empty handle, we throw an undefined exception
329 // to deal more gracefully with out of memory situations.
330 if (value.IsEmpty()) {
331 i::Top::ScheduleThrow(i::Heap::undefined_value());
332 } else {
333 i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
334 }
335 return v8::Undefined();
336}
337
338
339RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
340
341
342RegisteredExtension::RegisteredExtension(Extension* extension)
343 : extension_(extension), state_(UNVISITED) { }
344
345
346void RegisteredExtension::Register(RegisteredExtension* that) {
347 that->next_ = RegisteredExtension::first_extension_;
348 RegisteredExtension::first_extension_ = that;
349}
350
351
352void RegisterExtension(Extension* that) {
353 RegisteredExtension* extension = new RegisteredExtension(that);
354 RegisteredExtension::Register(extension);
355}
356
357
358Extension::Extension(const char* name,
359 const char* source,
360 int dep_count,
361 const char** deps)
362 : name_(name),
363 source_(source),
364 dep_count_(dep_count),
365 deps_(deps),
366 auto_enable_(false) { }
367
368
369v8::Handle<Primitive> Undefined() {
370 LOG_API("Undefined");
371 return ImplementationUtilities::Undefined();
372}
373
374
375v8::Handle<Primitive> Null() {
376 LOG_API("Null");
377 return ImplementationUtilities::Null();
378}
379
380
381v8::Handle<Boolean> True() {
382 LOG_API("True");
383 return ImplementationUtilities::True();
384}
385
386
387v8::Handle<Boolean> False() {
388 LOG_API("False");
389 return ImplementationUtilities::False();
390}
391
392
393ResourceConstraints::ResourceConstraints()
394 : max_young_space_size_(0),
395 max_old_space_size_(0),
396 stack_limit_(NULL) { }
397
398
399bool SetResourceConstraints(ResourceConstraints* constraints) {
Steve Block3ce2e202009-11-05 08:53:23 +0000400 int young_space_size = constraints->max_young_space_size();
Steve Blocka7e24c12009-10-30 11:49:00 +0000401 int old_gen_size = constraints->max_old_space_size();
Steve Block3ce2e202009-11-05 08:53:23 +0000402 if (young_space_size != 0 || old_gen_size != 0) {
403 bool result = i::Heap::ConfigureHeap(young_space_size / 2, old_gen_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000404 if (!result) return false;
405 }
406 if (constraints->stack_limit() != NULL) {
407 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
408 i::StackGuard::SetStackLimit(limit);
409 }
410 return true;
411}
412
413
414i::Object** V8::GlobalizeReference(i::Object** obj) {
415 if (IsDeadCheck("V8::Persistent::New")) return NULL;
416 LOG_API("Persistent::New");
417 i::Handle<i::Object> result =
418 i::GlobalHandles::Create(*obj);
419 return result.location();
420}
421
422
423void V8::MakeWeak(i::Object** object, void* parameters,
424 WeakReferenceCallback callback) {
425 LOG_API("MakeWeak");
426 i::GlobalHandles::MakeWeak(object, parameters, callback);
427}
428
429
430void V8::ClearWeak(i::Object** obj) {
431 LOG_API("ClearWeak");
432 i::GlobalHandles::ClearWeakness(obj);
433}
434
435
436bool V8::IsGlobalNearDeath(i::Object** obj) {
437 LOG_API("IsGlobalNearDeath");
438 if (!i::V8::IsRunning()) return false;
439 return i::GlobalHandles::IsNearDeath(obj);
440}
441
442
443bool V8::IsGlobalWeak(i::Object** obj) {
444 LOG_API("IsGlobalWeak");
445 if (!i::V8::IsRunning()) return false;
446 return i::GlobalHandles::IsWeak(obj);
447}
448
449
450void V8::DisposeGlobal(i::Object** obj) {
451 LOG_API("DisposeGlobal");
452 if (!i::V8::IsRunning()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000453 i::GlobalHandles::Destroy(obj);
454}
455
456// --- H a n d l e s ---
457
458
John Reck59135872010-11-02 12:39:01 -0700459HandleScope::HandleScope()
460 : prev_next_(i::HandleScope::current_.next),
461 prev_limit_(i::HandleScope::current_.limit),
462 is_closed_(false) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000463 API_ENTRY_CHECK("HandleScope::HandleScope");
John Reck59135872010-11-02 12:39:01 -0700464 i::HandleScope::current_.level++;
Steve Blocka7e24c12009-10-30 11:49:00 +0000465}
466
467
468HandleScope::~HandleScope() {
469 if (!is_closed_) {
John Reck59135872010-11-02 12:39:01 -0700470 Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +0000471 }
472}
473
474
John Reck59135872010-11-02 12:39:01 -0700475void HandleScope::Leave() {
476 i::HandleScope::current_.level--;
477 ASSERT(i::HandleScope::current_.level >= 0);
478 i::HandleScope::current_.next = prev_next_;
479 if (i::HandleScope::current_.limit != prev_limit_) {
480 i::HandleScope::current_.limit = prev_limit_;
481 i::HandleScope::DeleteExtensions();
482 }
483
484#ifdef DEBUG
485 i::HandleScope::ZapRange(prev_next_, prev_limit_);
486#endif
487}
488
489
Steve Blocka7e24c12009-10-30 11:49:00 +0000490int HandleScope::NumberOfHandles() {
491 return i::HandleScope::NumberOfHandles();
492}
493
494
495i::Object** v8::HandleScope::CreateHandle(i::Object* value) {
496 return i::HandleScope::CreateHandle(value);
497}
498
499
500void Context::Enter() {
501 if (IsDeadCheck("v8::Context::Enter()")) return;
502 ENTER_V8;
503 i::Handle<i::Context> env = Utils::OpenHandle(this);
504 thread_local.EnterContext(env);
505
506 thread_local.SaveContext(i::Top::context());
507 i::Top::set_context(*env);
508}
509
510
511void Context::Exit() {
512 if (!i::V8::IsRunning()) return;
513 if (!ApiCheck(thread_local.LeaveLastContext(),
514 "v8::Context::Exit()",
515 "Cannot exit non-entered context")) {
516 return;
517 }
518
519 // Content of 'last_context' could be NULL.
520 i::Context* last_context = thread_local.RestoreContext();
521 i::Top::set_context(last_context);
522}
523
524
Steve Blockd0582a62009-12-15 09:54:21 +0000525void Context::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000526 if (IsDeadCheck("v8::Context::SetData()")) return;
527 ENTER_V8;
528 {
529 HandleScope scope;
530 i::Handle<i::Context> env = Utils::OpenHandle(this);
531 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
532 ASSERT(env->IsGlobalContext());
533 if (env->IsGlobalContext()) {
534 env->set_data(*raw_data);
535 }
536 }
537}
538
539
540v8::Local<v8::Value> Context::GetData() {
541 if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
542 ENTER_V8;
543 i::Object* raw_result = NULL;
544 {
545 HandleScope scope;
546 i::Handle<i::Context> env = Utils::OpenHandle(this);
547 ASSERT(env->IsGlobalContext());
548 if (env->IsGlobalContext()) {
549 raw_result = env->data();
550 } else {
551 return Local<Value>();
552 }
553 }
554 i::Handle<i::Object> result(raw_result);
555 return Utils::ToLocal(result);
556}
557
558
559i::Object** v8::HandleScope::RawClose(i::Object** value) {
560 if (!ApiCheck(!is_closed_,
561 "v8::HandleScope::Close()",
562 "Local scope has already been closed")) {
563 return 0;
564 }
565 LOG_API("CloseHandleScope");
566
567 // Read the result before popping the handle block.
Steve Block6ded16b2010-05-10 14:33:55 +0100568 i::Object* result = NULL;
569 if (value != NULL) {
570 result = *value;
571 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000572 is_closed_ = true;
John Reck59135872010-11-02 12:39:01 -0700573 Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +0000574
Steve Block6ded16b2010-05-10 14:33:55 +0100575 if (value == NULL) {
576 return NULL;
577 }
578
Steve Blocka7e24c12009-10-30 11:49:00 +0000579 // Allocate a new handle on the previous handle block.
580 i::Handle<i::Object> handle(result);
581 return handle.location();
582}
583
584
585// --- N e a n d e r ---
586
587
588// A constructor cannot easily return an error value, therefore it is necessary
589// to check for a dead VM with ON_BAILOUT before constructing any Neander
590// objects. To remind you about this there is no HandleScope in the
591// NeanderObject constructor. When you add one to the site calling the
592// constructor you should check that you ensured the VM was not dead first.
593NeanderObject::NeanderObject(int size) {
594 EnsureInitialized("v8::Nowhere");
595 ENTER_V8;
596 value_ = i::Factory::NewNeanderObject();
597 i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
598 value_->set_elements(*elements);
599}
600
601
602int NeanderObject::size() {
603 return i::FixedArray::cast(value_->elements())->length();
604}
605
606
607NeanderArray::NeanderArray() : obj_(2) {
608 obj_.set(0, i::Smi::FromInt(0));
609}
610
611
612int NeanderArray::length() {
613 return i::Smi::cast(obj_.get(0))->value();
614}
615
616
617i::Object* NeanderArray::get(int offset) {
618 ASSERT(0 <= offset);
619 ASSERT(offset < length());
620 return obj_.get(offset + 1);
621}
622
623
624// This method cannot easily return an error value, therefore it is necessary
625// to check for a dead VM with ON_BAILOUT before calling it. To remind you
626// about this there is no HandleScope in this method. When you add one to the
627// site calling this method you should check that you ensured the VM was not
628// dead first.
629void NeanderArray::add(i::Handle<i::Object> value) {
630 int length = this->length();
631 int size = obj_.size();
632 if (length == size - 1) {
633 i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
634 for (int i = 0; i < length; i++)
635 new_elms->set(i + 1, get(i));
636 obj_.value()->set_elements(*new_elms);
637 }
638 obj_.set(length + 1, *value);
639 obj_.set(0, i::Smi::FromInt(length + 1));
640}
641
642
643void NeanderArray::set(int index, i::Object* value) {
644 if (index < 0 || index >= this->length()) return;
645 obj_.set(index + 1, value);
646}
647
648
649// --- T e m p l a t e ---
650
651
652static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
653 that->set_tag(i::Smi::FromInt(type));
654}
655
656
657void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
658 v8::PropertyAttribute attribute) {
659 if (IsDeadCheck("v8::Template::SetProperty()")) return;
660 ENTER_V8;
661 HandleScope scope;
662 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
663 if (list->IsUndefined()) {
664 list = NeanderArray().value();
665 Utils::OpenHandle(this)->set_property_list(*list);
666 }
667 NeanderArray array(list);
668 array.add(Utils::OpenHandle(*name));
669 array.add(Utils::OpenHandle(*value));
670 array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
671}
672
673
674// --- F u n c t i o n T e m p l a t e ---
675static void InitializeFunctionTemplate(
676 i::Handle<i::FunctionTemplateInfo> info) {
677 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
678 info->set_flag(0);
679}
680
681
682Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
683 if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
684 return Local<ObjectTemplate>();
685 }
686 ENTER_V8;
687 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
688 if (result->IsUndefined()) {
689 result = Utils::OpenHandle(*ObjectTemplate::New());
690 Utils::OpenHandle(this)->set_prototype_template(*result);
691 }
692 return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
693}
694
695
696void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
697 if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
698 ENTER_V8;
699 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
700}
701
702
703// To distinguish the function templates, so that we can find them in the
704// function cache of the global context.
705static int next_serial_number = 0;
706
707
708Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
709 v8::Handle<Value> data, v8::Handle<Signature> signature) {
710 EnsureInitialized("v8::FunctionTemplate::New()");
711 LOG_API("FunctionTemplate::New");
712 ENTER_V8;
713 i::Handle<i::Struct> struct_obj =
714 i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
715 i::Handle<i::FunctionTemplateInfo> obj =
716 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
717 InitializeFunctionTemplate(obj);
718 obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
719 if (callback != 0) {
720 if (data.IsEmpty()) data = v8::Undefined();
721 Utils::ToLocal(obj)->SetCallHandler(callback, data);
722 }
723 obj->set_undetectable(false);
724 obj->set_needs_access_check(false);
725
726 if (!signature.IsEmpty())
727 obj->set_signature(*Utils::OpenHandle(*signature));
728 return Utils::ToLocal(obj);
729}
730
731
732Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
733 int argc, Handle<FunctionTemplate> argv[]) {
734 EnsureInitialized("v8::Signature::New()");
735 LOG_API("Signature::New");
736 ENTER_V8;
737 i::Handle<i::Struct> struct_obj =
738 i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
739 i::Handle<i::SignatureInfo> obj =
740 i::Handle<i::SignatureInfo>::cast(struct_obj);
741 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
742 if (argc > 0) {
743 i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
744 for (int i = 0; i < argc; i++) {
745 if (!argv[i].IsEmpty())
746 args->set(i, *Utils::OpenHandle(*argv[i]));
747 }
748 obj->set_args(*args);
749 }
750 return Utils::ToLocal(obj);
751}
752
753
754Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
755 Handle<FunctionTemplate> types[1] = { type };
756 return TypeSwitch::New(1, types);
757}
758
759
760Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
761 EnsureInitialized("v8::TypeSwitch::New()");
762 LOG_API("TypeSwitch::New");
763 ENTER_V8;
764 i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
765 for (int i = 0; i < argc; i++)
766 vector->set(i, *Utils::OpenHandle(*types[i]));
767 i::Handle<i::Struct> struct_obj =
768 i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
769 i::Handle<i::TypeSwitchInfo> obj =
770 i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
771 obj->set_types(*vector);
772 return Utils::ToLocal(obj);
773}
774
775
776int TypeSwitch::match(v8::Handle<Value> value) {
777 LOG_API("TypeSwitch::match");
778 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
779 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
780 i::FixedArray* types = i::FixedArray::cast(info->types());
781 for (int i = 0; i < types->length(); i++) {
782 if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
783 return i + 1;
784 }
785 return 0;
786}
787
788
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100789#define SET_FIELD_WRAPPED(obj, setter, cdata) do { \
790 i::Handle<i::Object> proxy = FromCData(cdata); \
791 (obj)->setter(*proxy); \
792 } while (false)
793
794
Steve Blocka7e24c12009-10-30 11:49:00 +0000795void FunctionTemplate::SetCallHandler(InvocationCallback callback,
796 v8::Handle<Value> data) {
797 if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
798 ENTER_V8;
799 HandleScope scope;
800 i::Handle<i::Struct> struct_obj =
801 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
802 i::Handle<i::CallHandlerInfo> obj =
803 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100804 SET_FIELD_WRAPPED(obj, set_callback, callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000805 if (data.IsEmpty()) data = v8::Undefined();
806 obj->set_data(*Utils::OpenHandle(*data));
807 Utils::OpenHandle(this)->set_call_code(*obj);
808}
809
810
Leon Clarkef7060e22010-06-03 12:02:55 +0100811static i::Handle<i::AccessorInfo> MakeAccessorInfo(
812 v8::Handle<String> name,
813 AccessorGetter getter,
814 AccessorSetter setter,
815 v8::Handle<Value> data,
816 v8::AccessControl settings,
817 v8::PropertyAttribute attributes) {
818 i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
819 ASSERT(getter != NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100820 SET_FIELD_WRAPPED(obj, set_getter, getter);
821 SET_FIELD_WRAPPED(obj, set_setter, setter);
Leon Clarkef7060e22010-06-03 12:02:55 +0100822 if (data.IsEmpty()) data = v8::Undefined();
823 obj->set_data(*Utils::OpenHandle(*data));
824 obj->set_name(*Utils::OpenHandle(*name));
825 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
826 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
827 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
828 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
829 return obj;
830}
831
832
Steve Blocka7e24c12009-10-30 11:49:00 +0000833void FunctionTemplate::AddInstancePropertyAccessor(
834 v8::Handle<String> name,
835 AccessorGetter getter,
836 AccessorSetter setter,
837 v8::Handle<Value> data,
838 v8::AccessControl settings,
839 v8::PropertyAttribute attributes) {
840 if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
841 return;
842 }
843 ENTER_V8;
844 HandleScope scope;
Steve Blocka7e24c12009-10-30 11:49:00 +0000845
Leon Clarkef7060e22010-06-03 12:02:55 +0100846 i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name,
847 getter, setter, data,
848 settings, attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000849 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
850 if (list->IsUndefined()) {
851 list = NeanderArray().value();
852 Utils::OpenHandle(this)->set_property_accessors(*list);
853 }
854 NeanderArray array(list);
855 array.add(obj);
856}
857
858
859Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
860 if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
861 || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
862 return Local<ObjectTemplate>();
863 ENTER_V8;
864 if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
865 Local<ObjectTemplate> templ =
866 ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
867 Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
868 }
869 i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
870 Utils::OpenHandle(this)->instance_template()));
871 return Utils::ToLocal(result);
872}
873
874
875void FunctionTemplate::SetClassName(Handle<String> name) {
876 if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
877 ENTER_V8;
878 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
879}
880
881
882void FunctionTemplate::SetHiddenPrototype(bool value) {
883 if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
884 ENTER_V8;
885 Utils::OpenHandle(this)->set_hidden_prototype(value);
886}
887
888
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100889void FunctionTemplate::SetNamedInstancePropertyHandler(
Steve Blocka7e24c12009-10-30 11:49:00 +0000890 NamedPropertyGetter getter,
891 NamedPropertySetter setter,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100892 NamedPropertyQuery query,
Steve Blocka7e24c12009-10-30 11:49:00 +0000893 NamedPropertyDeleter remover,
894 NamedPropertyEnumerator enumerator,
895 Handle<Value> data) {
896 if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
897 return;
898 }
899 ENTER_V8;
900 HandleScope scope;
901 i::Handle<i::Struct> struct_obj =
902 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
903 i::Handle<i::InterceptorInfo> obj =
904 i::Handle<i::InterceptorInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100905
906 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
907 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
908 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
909 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
910 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
911
Steve Blocka7e24c12009-10-30 11:49:00 +0000912 if (data.IsEmpty()) data = v8::Undefined();
913 obj->set_data(*Utils::OpenHandle(*data));
914 Utils::OpenHandle(this)->set_named_property_handler(*obj);
915}
916
917
918void FunctionTemplate::SetIndexedInstancePropertyHandler(
919 IndexedPropertyGetter getter,
920 IndexedPropertySetter setter,
921 IndexedPropertyQuery query,
922 IndexedPropertyDeleter remover,
923 IndexedPropertyEnumerator enumerator,
924 Handle<Value> data) {
925 if (IsDeadCheck(
926 "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
927 return;
928 }
929 ENTER_V8;
930 HandleScope scope;
931 i::Handle<i::Struct> struct_obj =
932 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
933 i::Handle<i::InterceptorInfo> obj =
934 i::Handle<i::InterceptorInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100935
936 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
937 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
938 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
939 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
940 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
941
Steve Blocka7e24c12009-10-30 11:49:00 +0000942 if (data.IsEmpty()) data = v8::Undefined();
943 obj->set_data(*Utils::OpenHandle(*data));
944 Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
945}
946
947
948void FunctionTemplate::SetInstanceCallAsFunctionHandler(
949 InvocationCallback callback,
950 Handle<Value> data) {
951 if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
952 return;
953 }
954 ENTER_V8;
955 HandleScope scope;
956 i::Handle<i::Struct> struct_obj =
957 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
958 i::Handle<i::CallHandlerInfo> obj =
959 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100960 SET_FIELD_WRAPPED(obj, set_callback, callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000961 if (data.IsEmpty()) data = v8::Undefined();
962 obj->set_data(*Utils::OpenHandle(*data));
963 Utils::OpenHandle(this)->set_instance_call_handler(*obj);
964}
965
966
967// --- O b j e c t T e m p l a t e ---
968
969
970Local<ObjectTemplate> ObjectTemplate::New() {
971 return New(Local<FunctionTemplate>());
972}
973
974
975Local<ObjectTemplate> ObjectTemplate::New(
976 v8::Handle<FunctionTemplate> constructor) {
977 if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
978 EnsureInitialized("v8::ObjectTemplate::New()");
979 LOG_API("ObjectTemplate::New");
980 ENTER_V8;
981 i::Handle<i::Struct> struct_obj =
982 i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
983 i::Handle<i::ObjectTemplateInfo> obj =
984 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
985 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
986 if (!constructor.IsEmpty())
987 obj->set_constructor(*Utils::OpenHandle(*constructor));
988 obj->set_internal_field_count(i::Smi::FromInt(0));
989 return Utils::ToLocal(obj);
990}
991
992
993// Ensure that the object template has a constructor. If no
994// constructor is available we create one.
995static void EnsureConstructor(ObjectTemplate* object_template) {
996 if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
997 Local<FunctionTemplate> templ = FunctionTemplate::New();
998 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
999 constructor->set_instance_template(*Utils::OpenHandle(object_template));
1000 Utils::OpenHandle(object_template)->set_constructor(*constructor);
1001 }
1002}
1003
1004
1005void ObjectTemplate::SetAccessor(v8::Handle<String> name,
1006 AccessorGetter getter,
1007 AccessorSetter setter,
1008 v8::Handle<Value> data,
1009 AccessControl settings,
1010 PropertyAttribute attribute) {
1011 if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
1012 ENTER_V8;
1013 HandleScope scope;
1014 EnsureConstructor(this);
1015 i::FunctionTemplateInfo* constructor =
1016 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1017 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1018 Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
1019 getter,
1020 setter,
1021 data,
1022 settings,
1023 attribute);
1024}
1025
1026
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001027void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
1028 NamedPropertySetter setter,
1029 NamedPropertyQuery query,
1030 NamedPropertyDeleter remover,
1031 NamedPropertyEnumerator enumerator,
1032 Handle<Value> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001033 if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
1034 ENTER_V8;
1035 HandleScope scope;
1036 EnsureConstructor(this);
1037 i::FunctionTemplateInfo* constructor =
1038 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1039 i::Handle<i::FunctionTemplateInfo> cons(constructor);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001040 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
1041 setter,
1042 query,
1043 remover,
1044 enumerator,
1045 data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001046}
1047
1048
1049void ObjectTemplate::MarkAsUndetectable() {
1050 if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
1051 ENTER_V8;
1052 HandleScope scope;
1053 EnsureConstructor(this);
1054 i::FunctionTemplateInfo* constructor =
1055 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1056 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1057 cons->set_undetectable(true);
1058}
1059
1060
1061void ObjectTemplate::SetAccessCheckCallbacks(
1062 NamedSecurityCallback named_callback,
1063 IndexedSecurityCallback indexed_callback,
1064 Handle<Value> data,
1065 bool turned_on_by_default) {
1066 if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
1067 ENTER_V8;
1068 HandleScope scope;
1069 EnsureConstructor(this);
1070
1071 i::Handle<i::Struct> struct_info =
1072 i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1073 i::Handle<i::AccessCheckInfo> info =
1074 i::Handle<i::AccessCheckInfo>::cast(struct_info);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001075
1076 SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
1077 SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
1078
Steve Blocka7e24c12009-10-30 11:49:00 +00001079 if (data.IsEmpty()) data = v8::Undefined();
1080 info->set_data(*Utils::OpenHandle(*data));
1081
1082 i::FunctionTemplateInfo* constructor =
1083 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1084 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1085 cons->set_access_check_info(*info);
1086 cons->set_needs_access_check(turned_on_by_default);
1087}
1088
1089
1090void ObjectTemplate::SetIndexedPropertyHandler(
1091 IndexedPropertyGetter getter,
1092 IndexedPropertySetter setter,
1093 IndexedPropertyQuery query,
1094 IndexedPropertyDeleter remover,
1095 IndexedPropertyEnumerator enumerator,
1096 Handle<Value> data) {
1097 if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
1098 ENTER_V8;
1099 HandleScope scope;
1100 EnsureConstructor(this);
1101 i::FunctionTemplateInfo* constructor =
1102 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1103 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1104 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
1105 setter,
1106 query,
1107 remover,
1108 enumerator,
1109 data);
1110}
1111
1112
1113void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1114 Handle<Value> data) {
1115 if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
1116 ENTER_V8;
1117 HandleScope scope;
1118 EnsureConstructor(this);
1119 i::FunctionTemplateInfo* constructor =
1120 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1121 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1122 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1123}
1124
1125
1126int ObjectTemplate::InternalFieldCount() {
1127 if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
1128 return 0;
1129 }
1130 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1131}
1132
1133
1134void ObjectTemplate::SetInternalFieldCount(int value) {
1135 if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
1136 if (!ApiCheck(i::Smi::IsValid(value),
1137 "v8::ObjectTemplate::SetInternalFieldCount()",
1138 "Invalid internal field count")) {
1139 return;
1140 }
1141 ENTER_V8;
1142 if (value > 0) {
1143 // The internal field count is set by the constructor function's
1144 // construct code, so we ensure that there is a constructor
1145 // function to do the setting.
1146 EnsureConstructor(this);
1147 }
1148 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1149}
1150
1151
1152// --- S c r i p t D a t a ---
1153
1154
1155ScriptData* ScriptData::PreCompile(const char* input, int length) {
1156 unibrow::Utf8InputBuffer<> buf(input, length);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001157 return i::ParserApi::PreParse(i::Handle<i::String>(), &buf, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001158}
1159
1160
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001161ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
1162 i::Handle<i::String> str = Utils::OpenHandle(*source);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001163 return i::ParserApi::PreParse(str, NULL, NULL);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001164}
1165
1166
Leon Clarkef7060e22010-06-03 12:02:55 +01001167ScriptData* ScriptData::New(const char* data, int length) {
1168 // Return an empty ScriptData if the length is obviously invalid.
1169 if (length % sizeof(unsigned) != 0) {
Iain Merrick9ac36c92010-09-13 15:29:50 +01001170 return new i::ScriptDataImpl();
Leon Clarkef7060e22010-06-03 12:02:55 +01001171 }
1172
1173 // Copy the data to ensure it is properly aligned.
1174 int deserialized_data_length = length / sizeof(unsigned);
Iain Merrick9ac36c92010-09-13 15:29:50 +01001175 // If aligned, don't create a copy of the data.
1176 if (reinterpret_cast<intptr_t>(data) % sizeof(unsigned) == 0) {
1177 return new i::ScriptDataImpl(data, length);
1178 }
1179 // Copy the data to align it.
Leon Clarkef7060e22010-06-03 12:02:55 +01001180 unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
Iain Merrick9ac36c92010-09-13 15:29:50 +01001181 i::MemCopy(deserialized_data, data, length);
Leon Clarkef7060e22010-06-03 12:02:55 +01001182
1183 return new i::ScriptDataImpl(
1184 i::Vector<unsigned>(deserialized_data, deserialized_data_length));
Steve Blocka7e24c12009-10-30 11:49:00 +00001185}
1186
1187
1188// --- S c r i p t ---
1189
1190
1191Local<Script> Script::New(v8::Handle<String> source,
1192 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001193 v8::ScriptData* pre_data,
1194 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001195 ON_BAILOUT("v8::Script::New()", return Local<Script>());
1196 LOG_API("Script::New");
1197 ENTER_V8;
1198 i::Handle<i::String> str = Utils::OpenHandle(*source);
1199 i::Handle<i::Object> name_obj;
1200 int line_offset = 0;
1201 int column_offset = 0;
1202 if (origin != NULL) {
1203 if (!origin->ResourceName().IsEmpty()) {
1204 name_obj = Utils::OpenHandle(*origin->ResourceName());
1205 }
1206 if (!origin->ResourceLineOffset().IsEmpty()) {
1207 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1208 }
1209 if (!origin->ResourceColumnOffset().IsEmpty()) {
1210 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1211 }
1212 }
1213 EXCEPTION_PREAMBLE();
Andrei Popescu402d9372010-02-26 13:31:12 +00001214 i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001215 // We assert that the pre-data is sane, even though we can actually
1216 // handle it if it turns out not to be in release mode.
Andrei Popescu402d9372010-02-26 13:31:12 +00001217 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
Steve Blocka7e24c12009-10-30 11:49:00 +00001218 // If the pre-data isn't sane we simply ignore it
Andrei Popescu402d9372010-02-26 13:31:12 +00001219 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
1220 pre_data_impl = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001221 }
Steve Block6ded16b2010-05-10 14:33:55 +01001222 i::Handle<i::SharedFunctionInfo> result =
Andrei Popescu31002712010-02-23 13:46:05 +00001223 i::Compiler::Compile(str,
1224 name_obj,
1225 line_offset,
1226 column_offset,
1227 NULL,
Andrei Popescu402d9372010-02-26 13:31:12 +00001228 pre_data_impl,
1229 Utils::OpenHandle(*script_data),
Andrei Popescu31002712010-02-23 13:46:05 +00001230 i::NOT_NATIVES_CODE);
Steve Block6ded16b2010-05-10 14:33:55 +01001231 has_pending_exception = result.is_null();
Steve Blocka7e24c12009-10-30 11:49:00 +00001232 EXCEPTION_BAILOUT_CHECK(Local<Script>());
Steve Block6ded16b2010-05-10 14:33:55 +01001233 return Local<Script>(ToApi<Script>(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00001234}
1235
1236
1237Local<Script> Script::New(v8::Handle<String> source,
1238 v8::Handle<Value> file_name) {
1239 ScriptOrigin origin(file_name);
1240 return New(source, &origin);
1241}
1242
1243
1244Local<Script> Script::Compile(v8::Handle<String> source,
1245 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001246 v8::ScriptData* pre_data,
1247 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001248 ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1249 LOG_API("Script::Compile");
1250 ENTER_V8;
Andrei Popescu402d9372010-02-26 13:31:12 +00001251 Local<Script> generic = New(source, origin, pre_data, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001252 if (generic.IsEmpty())
1253 return generic;
Steve Block6ded16b2010-05-10 14:33:55 +01001254 i::Handle<i::Object> obj = Utils::OpenHandle(*generic);
1255 i::Handle<i::SharedFunctionInfo> function =
1256 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001257 i::Handle<i::JSFunction> result =
Steve Block6ded16b2010-05-10 14:33:55 +01001258 i::Factory::NewFunctionFromSharedFunctionInfo(function,
1259 i::Top::global_context());
Steve Blocka7e24c12009-10-30 11:49:00 +00001260 return Local<Script>(ToApi<Script>(result));
1261}
1262
1263
1264Local<Script> Script::Compile(v8::Handle<String> source,
Andrei Popescu402d9372010-02-26 13:31:12 +00001265 v8::Handle<Value> file_name,
1266 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001267 ScriptOrigin origin(file_name);
Andrei Popescu402d9372010-02-26 13:31:12 +00001268 return Compile(source, &origin, 0, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001269}
1270
1271
1272Local<Value> Script::Run() {
1273 ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1274 LOG_API("Script::Run");
1275 ENTER_V8;
1276 i::Object* raw_result = NULL;
1277 {
1278 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001279 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1280 i::Handle<i::JSFunction> fun;
1281 if (obj->IsSharedFunctionInfo()) {
1282 i::Handle<i::SharedFunctionInfo>
1283 function_info(i::SharedFunctionInfo::cast(*obj));
1284 fun = i::Factory::NewFunctionFromSharedFunctionInfo(
1285 function_info, i::Top::global_context());
1286 } else {
1287 fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001288 }
1289 EXCEPTION_PREAMBLE();
1290 i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
1291 i::Handle<i::Object> result =
1292 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
1293 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1294 raw_result = *result;
1295 }
1296 i::Handle<i::Object> result(raw_result);
1297 return Utils::ToLocal(result);
1298}
1299
1300
Steve Block6ded16b2010-05-10 14:33:55 +01001301static i::Handle<i::SharedFunctionInfo> OpenScript(Script* script) {
1302 i::Handle<i::Object> obj = Utils::OpenHandle(script);
1303 i::Handle<i::SharedFunctionInfo> result;
1304 if (obj->IsSharedFunctionInfo()) {
1305 result =
1306 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
1307 } else {
1308 result =
1309 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared());
1310 }
1311 return result;
1312}
1313
1314
Steve Blocka7e24c12009-10-30 11:49:00 +00001315Local<Value> Script::Id() {
1316 ON_BAILOUT("v8::Script::Id()", return Local<Value>());
1317 LOG_API("Script::Id");
1318 i::Object* raw_id = NULL;
1319 {
1320 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001321 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1322 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001323 i::Handle<i::Object> id(script->id());
1324 raw_id = *id;
1325 }
1326 i::Handle<i::Object> id(raw_id);
1327 return Utils::ToLocal(id);
1328}
1329
1330
Steve Blockd0582a62009-12-15 09:54:21 +00001331void Script::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001332 ON_BAILOUT("v8::Script::SetData()", return);
1333 LOG_API("Script::SetData");
1334 {
1335 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001336 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001337 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
Steve Block6ded16b2010-05-10 14:33:55 +01001338 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001339 script->set_data(*raw_data);
1340 }
1341}
1342
1343
1344// --- E x c e p t i o n s ---
1345
1346
1347v8::TryCatch::TryCatch()
Steve Blockd0582a62009-12-15 09:54:21 +00001348 : next_(i::Top::try_catch_handler_address()),
Steve Blocka7e24c12009-10-30 11:49:00 +00001349 exception_(i::Heap::the_hole_value()),
1350 message_(i::Smi::FromInt(0)),
1351 is_verbose_(false),
1352 can_continue_(true),
1353 capture_message_(true),
Steve Blockd0582a62009-12-15 09:54:21 +00001354 rethrow_(false) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001355 i::Top::RegisterTryCatchHandler(this);
1356}
1357
1358
1359v8::TryCatch::~TryCatch() {
Steve Blockd0582a62009-12-15 09:54:21 +00001360 if (rethrow_) {
1361 v8::HandleScope scope;
1362 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
1363 i::Top::UnregisterTryCatchHandler(this);
1364 v8::ThrowException(exc);
1365 } else {
1366 i::Top::UnregisterTryCatchHandler(this);
1367 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001368}
1369
1370
1371bool v8::TryCatch::HasCaught() const {
1372 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1373}
1374
1375
1376bool v8::TryCatch::CanContinue() const {
1377 return can_continue_;
1378}
1379
1380
Steve Blockd0582a62009-12-15 09:54:21 +00001381v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1382 if (!HasCaught()) return v8::Local<v8::Value>();
1383 rethrow_ = true;
1384 return v8::Undefined();
1385}
1386
1387
Steve Blocka7e24c12009-10-30 11:49:00 +00001388v8::Local<Value> v8::TryCatch::Exception() const {
1389 if (HasCaught()) {
1390 // Check for out of memory exception.
1391 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1392 return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1393 } else {
1394 return v8::Local<Value>();
1395 }
1396}
1397
1398
1399v8::Local<Value> v8::TryCatch::StackTrace() const {
1400 if (HasCaught()) {
1401 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1402 if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1403 v8::HandleScope scope;
1404 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
1405 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
1406 if (!obj->HasProperty(*name))
1407 return v8::Local<Value>();
1408 return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
1409 } else {
1410 return v8::Local<Value>();
1411 }
1412}
1413
1414
1415v8::Local<v8::Message> v8::TryCatch::Message() const {
1416 if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1417 i::Object* message = reinterpret_cast<i::Object*>(message_);
1418 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1419 } else {
1420 return v8::Local<v8::Message>();
1421 }
1422}
1423
1424
1425void v8::TryCatch::Reset() {
1426 exception_ = i::Heap::the_hole_value();
1427 message_ = i::Smi::FromInt(0);
1428}
1429
1430
1431void v8::TryCatch::SetVerbose(bool value) {
1432 is_verbose_ = value;
1433}
1434
1435
1436void v8::TryCatch::SetCaptureMessage(bool value) {
1437 capture_message_ = value;
1438}
1439
1440
1441// --- M e s s a g e ---
1442
1443
1444Local<String> Message::Get() const {
1445 ON_BAILOUT("v8::Message::Get()", return Local<String>());
1446 ENTER_V8;
1447 HandleScope scope;
1448 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1449 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1450 Local<String> result = Utils::ToLocal(raw_result);
1451 return scope.Close(result);
1452}
1453
1454
1455v8::Handle<Value> Message::GetScriptResourceName() const {
1456 if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1457 return Local<String>();
1458 }
1459 ENTER_V8;
1460 HandleScope scope;
1461 i::Handle<i::JSObject> obj =
1462 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1463 // Return this.script.name.
1464 i::Handle<i::JSValue> script =
1465 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1466 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
1467 return scope.Close(Utils::ToLocal(resource_name));
1468}
1469
1470
1471v8::Handle<Value> Message::GetScriptData() const {
1472 if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
1473 return Local<Value>();
1474 }
1475 ENTER_V8;
1476 HandleScope scope;
1477 i::Handle<i::JSObject> obj =
1478 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1479 // Return this.script.data.
1480 i::Handle<i::JSValue> script =
1481 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1482 i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1483 return scope.Close(Utils::ToLocal(data));
1484}
1485
1486
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001487v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
1488 if (IsDeadCheck("v8::Message::GetStackTrace()")) {
1489 return Local<v8::StackTrace>();
1490 }
1491 ENTER_V8;
1492 HandleScope scope;
1493 i::Handle<i::JSObject> obj =
1494 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1495 i::Handle<i::Object> stackFramesObj = GetProperty(obj, "stackFrames");
1496 if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
1497 i::Handle<i::JSArray> stackTrace =
1498 i::Handle<i::JSArray>::cast(stackFramesObj);
1499 return scope.Close(Utils::StackTraceToLocal(stackTrace));
1500}
1501
1502
Steve Blocka7e24c12009-10-30 11:49:00 +00001503static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1504 i::Handle<i::Object> recv,
1505 int argc,
1506 i::Object** argv[],
1507 bool* has_pending_exception) {
1508 i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
John Reck59135872010-11-02 12:39:01 -07001509 i::Object* object_fun =
1510 i::Top::builtins()->GetPropertyNoExceptionThrown(*fmt_str);
Steve Blocka7e24c12009-10-30 11:49:00 +00001511 i::Handle<i::JSFunction> fun =
1512 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1513 i::Handle<i::Object> value =
1514 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1515 return value;
1516}
1517
1518
1519static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1520 i::Handle<i::Object> data,
1521 bool* has_pending_exception) {
1522 i::Object** argv[1] = { data.location() };
1523 return CallV8HeapFunction(name,
1524 i::Top::builtins(),
1525 1,
1526 argv,
1527 has_pending_exception);
1528}
1529
1530
1531int Message::GetLineNumber() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001532 ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001533 ENTER_V8;
1534 HandleScope scope;
1535 EXCEPTION_PREAMBLE();
1536 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1537 Utils::OpenHandle(this),
1538 &has_pending_exception);
1539 EXCEPTION_BAILOUT_CHECK(0);
1540 return static_cast<int>(result->Number());
1541}
1542
1543
1544int Message::GetStartPosition() const {
1545 if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1546 ENTER_V8;
1547 HandleScope scope;
1548
1549 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1550 return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1551}
1552
1553
1554int Message::GetEndPosition() const {
1555 if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1556 ENTER_V8;
1557 HandleScope scope;
1558 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1559 return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1560}
1561
1562
1563int Message::GetStartColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001564 if (IsDeadCheck("v8::Message::GetStartColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001565 ENTER_V8;
1566 HandleScope scope;
1567 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1568 EXCEPTION_PREAMBLE();
1569 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1570 "GetPositionInLine",
1571 data_obj,
1572 &has_pending_exception);
1573 EXCEPTION_BAILOUT_CHECK(0);
1574 return static_cast<int>(start_col_obj->Number());
1575}
1576
1577
1578int Message::GetEndColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001579 if (IsDeadCheck("v8::Message::GetEndColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001580 ENTER_V8;
1581 HandleScope scope;
1582 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1583 EXCEPTION_PREAMBLE();
1584 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1585 "GetPositionInLine",
1586 data_obj,
1587 &has_pending_exception);
1588 EXCEPTION_BAILOUT_CHECK(0);
1589 int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1590 int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1591 return static_cast<int>(start_col_obj->Number()) + (end - start);
1592}
1593
1594
1595Local<String> Message::GetSourceLine() const {
1596 ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
1597 ENTER_V8;
1598 HandleScope scope;
1599 EXCEPTION_PREAMBLE();
1600 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1601 Utils::OpenHandle(this),
1602 &has_pending_exception);
1603 EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1604 if (result->IsString()) {
1605 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1606 } else {
1607 return Local<String>();
1608 }
1609}
1610
1611
1612void Message::PrintCurrentStackTrace(FILE* out) {
1613 if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1614 ENTER_V8;
1615 i::Top::PrintCurrentStackTrace(out);
1616}
1617
1618
Kristian Monsen25f61362010-05-21 11:50:48 +01001619// --- S t a c k T r a c e ---
1620
1621Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
1622 if (IsDeadCheck("v8::StackTrace::GetFrame()")) return Local<StackFrame>();
1623 ENTER_V8;
1624 HandleScope scope;
1625 i::Handle<i::JSArray> self = Utils::OpenHandle(this);
John Reck59135872010-11-02 12:39:01 -07001626 i::Object* raw_object = self->GetElementNoExceptionThrown(index);
1627 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_object));
Kristian Monsen25f61362010-05-21 11:50:48 +01001628 return scope.Close(Utils::StackFrameToLocal(obj));
1629}
1630
1631
1632int StackTrace::GetFrameCount() const {
1633 if (IsDeadCheck("v8::StackTrace::GetFrameCount()")) return -1;
1634 ENTER_V8;
1635 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
1636}
1637
1638
1639Local<Array> StackTrace::AsArray() {
1640 if (IsDeadCheck("v8::StackTrace::AsArray()")) Local<Array>();
1641 ENTER_V8;
1642 return Utils::ToLocal(Utils::OpenHandle(this));
1643}
1644
1645
1646Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
1647 StackTraceOptions options) {
1648 if (IsDeadCheck("v8::StackTrace::CurrentStackTrace()")) Local<StackTrace>();
1649 ENTER_V8;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001650 i::Handle<i::JSArray> stackTrace =
1651 i::Top::CaptureCurrentStackTrace(frame_limit, options);
1652 return Utils::StackTraceToLocal(stackTrace);
Kristian Monsen25f61362010-05-21 11:50:48 +01001653}
1654
1655
1656// --- S t a c k F r a m e ---
1657
1658int StackFrame::GetLineNumber() const {
1659 if (IsDeadCheck("v8::StackFrame::GetLineNumber()")) {
1660 return Message::kNoLineNumberInfo;
1661 }
1662 ENTER_V8;
1663 i::HandleScope scope;
1664 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1665 i::Handle<i::Object> line = GetProperty(self, "lineNumber");
1666 if (!line->IsSmi()) {
1667 return Message::kNoLineNumberInfo;
1668 }
1669 return i::Smi::cast(*line)->value();
1670}
1671
1672
1673int StackFrame::GetColumn() const {
1674 if (IsDeadCheck("v8::StackFrame::GetColumn()")) {
1675 return Message::kNoColumnInfo;
1676 }
1677 ENTER_V8;
1678 i::HandleScope scope;
1679 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1680 i::Handle<i::Object> column = GetProperty(self, "column");
1681 if (!column->IsSmi()) {
1682 return Message::kNoColumnInfo;
1683 }
1684 return i::Smi::cast(*column)->value();
1685}
1686
1687
1688Local<String> StackFrame::GetScriptName() const {
1689 if (IsDeadCheck("v8::StackFrame::GetScriptName()")) return Local<String>();
1690 ENTER_V8;
1691 HandleScope scope;
1692 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1693 i::Handle<i::Object> name = GetProperty(self, "scriptName");
1694 if (!name->IsString()) {
1695 return Local<String>();
1696 }
1697 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1698}
1699
1700
Ben Murdochf87a2032010-10-22 12:50:53 +01001701Local<String> StackFrame::GetScriptNameOrSourceURL() const {
1702 if (IsDeadCheck("v8::StackFrame::GetScriptNameOrSourceURL()")) {
1703 return Local<String>();
1704 }
1705 ENTER_V8;
1706 HandleScope scope;
1707 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1708 i::Handle<i::Object> name = GetProperty(self, "scriptNameOrSourceURL");
1709 if (!name->IsString()) {
1710 return Local<String>();
1711 }
1712 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1713}
1714
1715
Kristian Monsen25f61362010-05-21 11:50:48 +01001716Local<String> StackFrame::GetFunctionName() const {
1717 if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
1718 ENTER_V8;
1719 HandleScope scope;
1720 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1721 i::Handle<i::Object> name = GetProperty(self, "functionName");
1722 if (!name->IsString()) {
1723 return Local<String>();
1724 }
1725 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1726}
1727
1728
1729bool StackFrame::IsEval() const {
1730 if (IsDeadCheck("v8::StackFrame::IsEval()")) return false;
1731 ENTER_V8;
1732 i::HandleScope scope;
1733 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1734 i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
1735 return is_eval->IsTrue();
1736}
1737
1738
1739bool StackFrame::IsConstructor() const {
1740 if (IsDeadCheck("v8::StackFrame::IsConstructor()")) return false;
1741 ENTER_V8;
1742 i::HandleScope scope;
1743 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1744 i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
1745 return is_constructor->IsTrue();
1746}
1747
1748
Steve Blocka7e24c12009-10-30 11:49:00 +00001749// --- D a t a ---
1750
1751bool Value::IsUndefined() const {
1752 if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1753 return Utils::OpenHandle(this)->IsUndefined();
1754}
1755
1756
1757bool Value::IsNull() const {
1758 if (IsDeadCheck("v8::Value::IsNull()")) return false;
1759 return Utils::OpenHandle(this)->IsNull();
1760}
1761
1762
1763bool Value::IsTrue() const {
1764 if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1765 return Utils::OpenHandle(this)->IsTrue();
1766}
1767
1768
1769bool Value::IsFalse() const {
1770 if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1771 return Utils::OpenHandle(this)->IsFalse();
1772}
1773
1774
1775bool Value::IsFunction() const {
1776 if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1777 return Utils::OpenHandle(this)->IsJSFunction();
1778}
1779
1780
1781bool Value::FullIsString() const {
1782 if (IsDeadCheck("v8::Value::IsString()")) return false;
1783 bool result = Utils::OpenHandle(this)->IsString();
1784 ASSERT_EQ(result, QuickIsString());
1785 return result;
1786}
1787
1788
1789bool Value::IsArray() const {
1790 if (IsDeadCheck("v8::Value::IsArray()")) return false;
1791 return Utils::OpenHandle(this)->IsJSArray();
1792}
1793
1794
1795bool Value::IsObject() const {
1796 if (IsDeadCheck("v8::Value::IsObject()")) return false;
1797 return Utils::OpenHandle(this)->IsJSObject();
1798}
1799
1800
1801bool Value::IsNumber() const {
1802 if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1803 return Utils::OpenHandle(this)->IsNumber();
1804}
1805
1806
1807bool Value::IsBoolean() const {
1808 if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1809 return Utils::OpenHandle(this)->IsBoolean();
1810}
1811
1812
1813bool Value::IsExternal() const {
1814 if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1815 return Utils::OpenHandle(this)->IsProxy();
1816}
1817
1818
1819bool Value::IsInt32() const {
1820 if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1821 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1822 if (obj->IsSmi()) return true;
1823 if (obj->IsNumber()) {
1824 double value = obj->Number();
1825 return i::FastI2D(i::FastD2I(value)) == value;
1826 }
1827 return false;
1828}
1829
1830
Steve Block6ded16b2010-05-10 14:33:55 +01001831bool Value::IsUint32() const {
1832 if (IsDeadCheck("v8::Value::IsUint32()")) return false;
1833 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1834 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
1835 if (obj->IsNumber()) {
1836 double value = obj->Number();
1837 return i::FastUI2D(i::FastD2UI(value)) == value;
1838 }
1839 return false;
1840}
1841
1842
Steve Blocka7e24c12009-10-30 11:49:00 +00001843bool Value::IsDate() const {
1844 if (IsDeadCheck("v8::Value::IsDate()")) return false;
1845 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1846 return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1847}
1848
1849
Iain Merrick75681382010-08-19 15:07:18 +01001850bool Value::IsRegExp() const {
1851 if (IsDeadCheck("v8::Value::IsRegExp()")) return false;
1852 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1853 return obj->IsJSRegExp();
1854}
1855
1856
Steve Blocka7e24c12009-10-30 11:49:00 +00001857Local<String> Value::ToString() const {
1858 if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1859 LOG_API("ToString");
1860 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1861 i::Handle<i::Object> str;
1862 if (obj->IsString()) {
1863 str = obj;
1864 } else {
1865 ENTER_V8;
1866 EXCEPTION_PREAMBLE();
1867 str = i::Execution::ToString(obj, &has_pending_exception);
1868 EXCEPTION_BAILOUT_CHECK(Local<String>());
1869 }
1870 return Local<String>(ToApi<String>(str));
1871}
1872
1873
1874Local<String> Value::ToDetailString() const {
1875 if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1876 LOG_API("ToDetailString");
1877 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1878 i::Handle<i::Object> str;
1879 if (obj->IsString()) {
1880 str = obj;
1881 } else {
1882 ENTER_V8;
1883 EXCEPTION_PREAMBLE();
1884 str = i::Execution::ToDetailString(obj, &has_pending_exception);
1885 EXCEPTION_BAILOUT_CHECK(Local<String>());
1886 }
1887 return Local<String>(ToApi<String>(str));
1888}
1889
1890
1891Local<v8::Object> Value::ToObject() const {
1892 if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1893 LOG_API("ToObject");
1894 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1895 i::Handle<i::Object> val;
1896 if (obj->IsJSObject()) {
1897 val = obj;
1898 } else {
1899 ENTER_V8;
1900 EXCEPTION_PREAMBLE();
1901 val = i::Execution::ToObject(obj, &has_pending_exception);
1902 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1903 }
1904 return Local<v8::Object>(ToApi<Object>(val));
1905}
1906
1907
1908Local<Boolean> Value::ToBoolean() const {
1909 if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1910 LOG_API("ToBoolean");
1911 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1912 if (obj->IsBoolean()) {
1913 return Local<Boolean>(ToApi<Boolean>(obj));
1914 } else {
1915 ENTER_V8;
1916 i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1917 return Local<Boolean>(ToApi<Boolean>(val));
1918 }
1919}
1920
1921
1922Local<Number> Value::ToNumber() const {
1923 if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1924 LOG_API("ToNumber");
1925 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1926 i::Handle<i::Object> num;
1927 if (obj->IsNumber()) {
1928 num = obj;
1929 } else {
1930 ENTER_V8;
1931 EXCEPTION_PREAMBLE();
1932 num = i::Execution::ToNumber(obj, &has_pending_exception);
1933 EXCEPTION_BAILOUT_CHECK(Local<Number>());
1934 }
1935 return Local<Number>(ToApi<Number>(num));
1936}
1937
1938
1939Local<Integer> Value::ToInteger() const {
1940 if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1941 LOG_API("ToInteger");
1942 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1943 i::Handle<i::Object> num;
1944 if (obj->IsSmi()) {
1945 num = obj;
1946 } else {
1947 ENTER_V8;
1948 EXCEPTION_PREAMBLE();
1949 num = i::Execution::ToInteger(obj, &has_pending_exception);
1950 EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1951 }
1952 return Local<Integer>(ToApi<Integer>(num));
1953}
1954
1955
1956void External::CheckCast(v8::Value* that) {
1957 if (IsDeadCheck("v8::External::Cast()")) return;
1958 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1959 ApiCheck(obj->IsProxy(),
1960 "v8::External::Cast()",
1961 "Could not convert to external");
1962}
1963
1964
1965void v8::Object::CheckCast(Value* that) {
1966 if (IsDeadCheck("v8::Object::Cast()")) return;
1967 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1968 ApiCheck(obj->IsJSObject(),
1969 "v8::Object::Cast()",
1970 "Could not convert to object");
1971}
1972
1973
1974void v8::Function::CheckCast(Value* that) {
1975 if (IsDeadCheck("v8::Function::Cast()")) return;
1976 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1977 ApiCheck(obj->IsJSFunction(),
1978 "v8::Function::Cast()",
1979 "Could not convert to function");
1980}
1981
1982
1983void v8::String::CheckCast(v8::Value* that) {
1984 if (IsDeadCheck("v8::String::Cast()")) return;
1985 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1986 ApiCheck(obj->IsString(),
1987 "v8::String::Cast()",
1988 "Could not convert to string");
1989}
1990
1991
1992void v8::Number::CheckCast(v8::Value* that) {
1993 if (IsDeadCheck("v8::Number::Cast()")) return;
1994 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1995 ApiCheck(obj->IsNumber(),
1996 "v8::Number::Cast()",
1997 "Could not convert to number");
1998}
1999
2000
2001void v8::Integer::CheckCast(v8::Value* that) {
2002 if (IsDeadCheck("v8::Integer::Cast()")) return;
2003 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2004 ApiCheck(obj->IsNumber(),
2005 "v8::Integer::Cast()",
2006 "Could not convert to number");
2007}
2008
2009
2010void v8::Array::CheckCast(Value* that) {
2011 if (IsDeadCheck("v8::Array::Cast()")) return;
2012 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2013 ApiCheck(obj->IsJSArray(),
2014 "v8::Array::Cast()",
2015 "Could not convert to array");
2016}
2017
2018
2019void v8::Date::CheckCast(v8::Value* that) {
2020 if (IsDeadCheck("v8::Date::Cast()")) return;
2021 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2022 ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
2023 "v8::Date::Cast()",
2024 "Could not convert to date");
2025}
2026
2027
Ben Murdochf87a2032010-10-22 12:50:53 +01002028void v8::RegExp::CheckCast(v8::Value* that) {
2029 if (IsDeadCheck("v8::RegExp::Cast()")) return;
2030 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2031 ApiCheck(obj->IsJSRegExp(),
2032 "v8::RegExp::Cast()",
2033 "Could not convert to regular expression");
2034}
2035
2036
Steve Blocka7e24c12009-10-30 11:49:00 +00002037bool Value::BooleanValue() const {
2038 if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
2039 LOG_API("BooleanValue");
2040 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2041 if (obj->IsBoolean()) {
2042 return obj->IsTrue();
2043 } else {
2044 ENTER_V8;
2045 i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
2046 return value->IsTrue();
2047 }
2048}
2049
2050
2051double Value::NumberValue() const {
2052 if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
2053 LOG_API("NumberValue");
2054 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2055 i::Handle<i::Object> num;
2056 if (obj->IsNumber()) {
2057 num = obj;
2058 } else {
2059 ENTER_V8;
2060 EXCEPTION_PREAMBLE();
2061 num = i::Execution::ToNumber(obj, &has_pending_exception);
2062 EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
2063 }
2064 return num->Number();
2065}
2066
2067
2068int64_t Value::IntegerValue() const {
2069 if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
2070 LOG_API("IntegerValue");
2071 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2072 i::Handle<i::Object> num;
2073 if (obj->IsNumber()) {
2074 num = obj;
2075 } else {
2076 ENTER_V8;
2077 EXCEPTION_PREAMBLE();
2078 num = i::Execution::ToInteger(obj, &has_pending_exception);
2079 EXCEPTION_BAILOUT_CHECK(0);
2080 }
2081 if (num->IsSmi()) {
2082 return i::Smi::cast(*num)->value();
2083 } else {
2084 return static_cast<int64_t>(num->Number());
2085 }
2086}
2087
2088
2089Local<Int32> Value::ToInt32() const {
2090 if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
2091 LOG_API("ToInt32");
2092 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2093 i::Handle<i::Object> num;
2094 if (obj->IsSmi()) {
2095 num = obj;
2096 } else {
2097 ENTER_V8;
2098 EXCEPTION_PREAMBLE();
2099 num = i::Execution::ToInt32(obj, &has_pending_exception);
2100 EXCEPTION_BAILOUT_CHECK(Local<Int32>());
2101 }
2102 return Local<Int32>(ToApi<Int32>(num));
2103}
2104
2105
2106Local<Uint32> Value::ToUint32() const {
2107 if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
2108 LOG_API("ToUInt32");
2109 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2110 i::Handle<i::Object> num;
2111 if (obj->IsSmi()) {
2112 num = obj;
2113 } else {
2114 ENTER_V8;
2115 EXCEPTION_PREAMBLE();
2116 num = i::Execution::ToUint32(obj, &has_pending_exception);
2117 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2118 }
2119 return Local<Uint32>(ToApi<Uint32>(num));
2120}
2121
2122
2123Local<Uint32> Value::ToArrayIndex() const {
2124 if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
2125 LOG_API("ToArrayIndex");
2126 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2127 if (obj->IsSmi()) {
2128 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2129 return Local<Uint32>();
2130 }
2131 ENTER_V8;
2132 EXCEPTION_PREAMBLE();
2133 i::Handle<i::Object> string_obj =
2134 i::Execution::ToString(obj, &has_pending_exception);
2135 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2136 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2137 uint32_t index;
2138 if (str->AsArrayIndex(&index)) {
2139 i::Handle<i::Object> value;
2140 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2141 value = i::Handle<i::Object>(i::Smi::FromInt(index));
2142 } else {
2143 value = i::Factory::NewNumber(index);
2144 }
2145 return Utils::Uint32ToLocal(value);
2146 }
2147 return Local<Uint32>();
2148}
2149
2150
2151int32_t Value::Int32Value() const {
2152 if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
2153 LOG_API("Int32Value");
2154 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2155 if (obj->IsSmi()) {
2156 return i::Smi::cast(*obj)->value();
2157 } else {
2158 LOG_API("Int32Value (slow)");
2159 ENTER_V8;
2160 EXCEPTION_PREAMBLE();
2161 i::Handle<i::Object> num =
2162 i::Execution::ToInt32(obj, &has_pending_exception);
2163 EXCEPTION_BAILOUT_CHECK(0);
2164 if (num->IsSmi()) {
2165 return i::Smi::cast(*num)->value();
2166 } else {
2167 return static_cast<int32_t>(num->Number());
2168 }
2169 }
2170}
2171
2172
2173bool Value::Equals(Handle<Value> that) const {
2174 if (IsDeadCheck("v8::Value::Equals()")
2175 || EmptyCheck("v8::Value::Equals()", this)
2176 || EmptyCheck("v8::Value::Equals()", that)) {
2177 return false;
2178 }
2179 LOG_API("Equals");
2180 ENTER_V8;
2181 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2182 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2183 i::Object** args[1] = { other.location() };
2184 EXCEPTION_PREAMBLE();
2185 i::Handle<i::Object> result =
2186 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
2187 EXCEPTION_BAILOUT_CHECK(false);
2188 return *result == i::Smi::FromInt(i::EQUAL);
2189}
2190
2191
2192bool Value::StrictEquals(Handle<Value> that) const {
2193 if (IsDeadCheck("v8::Value::StrictEquals()")
2194 || EmptyCheck("v8::Value::StrictEquals()", this)
2195 || EmptyCheck("v8::Value::StrictEquals()", that)) {
2196 return false;
2197 }
2198 LOG_API("StrictEquals");
2199 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2200 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2201 // Must check HeapNumber first, since NaN !== NaN.
2202 if (obj->IsHeapNumber()) {
2203 if (!other->IsNumber()) return false;
2204 double x = obj->Number();
2205 double y = other->Number();
2206 // Must check explicitly for NaN:s on Windows, but -0 works fine.
2207 return x == y && !isnan(x) && !isnan(y);
2208 } else if (*obj == *other) { // Also covers Booleans.
2209 return true;
2210 } else if (obj->IsSmi()) {
2211 return other->IsNumber() && obj->Number() == other->Number();
2212 } else if (obj->IsString()) {
2213 return other->IsString() &&
2214 i::String::cast(*obj)->Equals(i::String::cast(*other));
2215 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2216 return other->IsUndefined() || other->IsUndetectableObject();
2217 } else {
2218 return false;
2219 }
2220}
2221
2222
2223uint32_t Value::Uint32Value() const {
2224 if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
2225 LOG_API("Uint32Value");
2226 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2227 if (obj->IsSmi()) {
2228 return i::Smi::cast(*obj)->value();
2229 } else {
2230 ENTER_V8;
2231 EXCEPTION_PREAMBLE();
2232 i::Handle<i::Object> num =
2233 i::Execution::ToUint32(obj, &has_pending_exception);
2234 EXCEPTION_BAILOUT_CHECK(0);
2235 if (num->IsSmi()) {
2236 return i::Smi::cast(*num)->value();
2237 } else {
2238 return static_cast<uint32_t>(num->Number());
2239 }
2240 }
2241}
2242
2243
2244bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
2245 v8::PropertyAttribute attribs) {
2246 ON_BAILOUT("v8::Object::Set()", return false);
2247 ENTER_V8;
2248 HandleScope scope;
2249 i::Handle<i::Object> self = Utils::OpenHandle(this);
2250 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2251 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2252 EXCEPTION_PREAMBLE();
2253 i::Handle<i::Object> obj = i::SetProperty(
2254 self,
2255 key_obj,
2256 value_obj,
2257 static_cast<PropertyAttributes>(attribs));
2258 has_pending_exception = obj.is_null();
2259 EXCEPTION_BAILOUT_CHECK(false);
2260 return true;
2261}
2262
2263
Steve Block6ded16b2010-05-10 14:33:55 +01002264bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
2265 ON_BAILOUT("v8::Object::Set()", return false);
2266 ENTER_V8;
2267 HandleScope scope;
2268 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2269 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2270 EXCEPTION_PREAMBLE();
2271 i::Handle<i::Object> obj = i::SetElement(
2272 self,
2273 index,
2274 value_obj);
2275 has_pending_exception = obj.is_null();
2276 EXCEPTION_BAILOUT_CHECK(false);
2277 return true;
2278}
2279
2280
Steve Blocka7e24c12009-10-30 11:49:00 +00002281bool v8::Object::ForceSet(v8::Handle<Value> key,
2282 v8::Handle<Value> value,
2283 v8::PropertyAttribute attribs) {
2284 ON_BAILOUT("v8::Object::ForceSet()", return false);
2285 ENTER_V8;
2286 HandleScope scope;
2287 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2288 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2289 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2290 EXCEPTION_PREAMBLE();
2291 i::Handle<i::Object> obj = i::ForceSetProperty(
2292 self,
2293 key_obj,
2294 value_obj,
2295 static_cast<PropertyAttributes>(attribs));
2296 has_pending_exception = obj.is_null();
2297 EXCEPTION_BAILOUT_CHECK(false);
2298 return true;
2299}
2300
2301
2302bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2303 ON_BAILOUT("v8::Object::ForceDelete()", return false);
2304 ENTER_V8;
2305 HandleScope scope;
2306 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2307 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2308 EXCEPTION_PREAMBLE();
2309 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2310 has_pending_exception = obj.is_null();
2311 EXCEPTION_BAILOUT_CHECK(false);
2312 return obj->IsTrue();
2313}
2314
2315
2316Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2317 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2318 ENTER_V8;
2319 i::Handle<i::Object> self = Utils::OpenHandle(this);
2320 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2321 EXCEPTION_PREAMBLE();
2322 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2323 has_pending_exception = result.is_null();
2324 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2325 return Utils::ToLocal(result);
2326}
2327
2328
Steve Block6ded16b2010-05-10 14:33:55 +01002329Local<Value> v8::Object::Get(uint32_t index) {
2330 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2331 ENTER_V8;
2332 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2333 EXCEPTION_PREAMBLE();
2334 i::Handle<i::Object> result = i::GetElement(self, index);
2335 has_pending_exception = result.is_null();
2336 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2337 return Utils::ToLocal(result);
2338}
2339
2340
Steve Blocka7e24c12009-10-30 11:49:00 +00002341Local<Value> v8::Object::GetPrototype() {
2342 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
2343 ENTER_V8;
2344 i::Handle<i::Object> self = Utils::OpenHandle(this);
2345 i::Handle<i::Object> result = i::GetPrototype(self);
2346 return Utils::ToLocal(result);
2347}
2348
2349
Andrei Popescu402d9372010-02-26 13:31:12 +00002350bool v8::Object::SetPrototype(Handle<Value> value) {
2351 ON_BAILOUT("v8::Object::SetPrototype()", return false);
2352 ENTER_V8;
2353 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2354 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2355 EXCEPTION_PREAMBLE();
2356 i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2357 has_pending_exception = result.is_null();
2358 EXCEPTION_BAILOUT_CHECK(false);
2359 return true;
2360}
2361
2362
Steve Blocka7e24c12009-10-30 11:49:00 +00002363Local<Object> v8::Object::FindInstanceInPrototypeChain(
2364 v8::Handle<FunctionTemplate> tmpl) {
2365 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
2366 return Local<v8::Object>());
2367 ENTER_V8;
2368 i::JSObject* object = *Utils::OpenHandle(this);
2369 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2370 while (!object->IsInstanceOf(tmpl_info)) {
2371 i::Object* prototype = object->GetPrototype();
2372 if (!prototype->IsJSObject()) return Local<Object>();
2373 object = i::JSObject::cast(prototype);
2374 }
2375 return Utils::ToLocal(i::Handle<i::JSObject>(object));
2376}
2377
2378
2379Local<Array> v8::Object::GetPropertyNames() {
2380 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
2381 ENTER_V8;
2382 v8::HandleScope scope;
2383 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2384 i::Handle<i::FixedArray> value =
2385 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2386 // Because we use caching to speed up enumeration it is important
2387 // to never change the result of the basic enumeration function so
2388 // we clone the result.
2389 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
2390 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
2391 return scope.Close(Utils::ToLocal(result));
2392}
2393
2394
2395Local<String> v8::Object::ObjectProtoToString() {
2396 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2397 ENTER_V8;
2398 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2399
2400 i::Handle<i::Object> name(self->class_name());
2401
2402 // Native implementation of Object.prototype.toString (v8natives.js):
2403 // var c = %ClassOf(this);
2404 // if (c === 'Arguments') c = 'Object';
2405 // return "[object " + c + "]";
2406
2407 if (!name->IsString()) {
2408 return v8::String::New("[object ]");
2409
2410 } else {
2411 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2412 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2413 return v8::String::New("[object Object]");
2414
2415 } else {
2416 const char* prefix = "[object ";
2417 Local<String> str = Utils::ToLocal(class_name);
2418 const char* postfix = "]";
2419
Steve Blockd0582a62009-12-15 09:54:21 +00002420 int prefix_len = i::StrLength(prefix);
2421 int str_len = str->Length();
2422 int postfix_len = i::StrLength(postfix);
Steve Blocka7e24c12009-10-30 11:49:00 +00002423
Steve Blockd0582a62009-12-15 09:54:21 +00002424 int buf_len = prefix_len + str_len + postfix_len;
Kristian Monsen25f61362010-05-21 11:50:48 +01002425 i::ScopedVector<char> buf(buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002426
2427 // Write prefix.
Kristian Monsen25f61362010-05-21 11:50:48 +01002428 char* ptr = buf.start();
Steve Blocka7e24c12009-10-30 11:49:00 +00002429 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2430 ptr += prefix_len;
2431
2432 // Write real content.
2433 str->WriteAscii(ptr, 0, str_len);
2434 ptr += str_len;
2435
2436 // Write postfix.
2437 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2438
2439 // Copy the buffer into a heap-allocated string and return it.
Kristian Monsen25f61362010-05-21 11:50:48 +01002440 Local<String> result = v8::String::New(buf.start(), buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002441 return result;
2442 }
2443 }
2444}
2445
2446
2447bool v8::Object::Delete(v8::Handle<String> key) {
2448 ON_BAILOUT("v8::Object::Delete()", return false);
2449 ENTER_V8;
2450 HandleScope scope;
2451 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2452 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2453 return i::DeleteProperty(self, key_obj)->IsTrue();
2454}
2455
2456
2457bool v8::Object::Has(v8::Handle<String> key) {
2458 ON_BAILOUT("v8::Object::Has()", return false);
2459 ENTER_V8;
2460 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2461 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2462 return self->HasProperty(*key_obj);
2463}
2464
2465
2466bool v8::Object::Delete(uint32_t index) {
2467 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2468 ENTER_V8;
2469 HandleScope scope;
2470 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2471 return i::DeleteElement(self, index)->IsTrue();
2472}
2473
2474
2475bool v8::Object::Has(uint32_t index) {
2476 ON_BAILOUT("v8::Object::HasProperty()", return false);
2477 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2478 return self->HasElement(index);
2479}
2480
2481
Leon Clarkef7060e22010-06-03 12:02:55 +01002482bool Object::SetAccessor(Handle<String> name,
2483 AccessorGetter getter,
2484 AccessorSetter setter,
2485 v8::Handle<Value> data,
2486 AccessControl settings,
2487 PropertyAttribute attributes) {
2488 ON_BAILOUT("v8::Object::SetAccessor()", return false);
2489 ENTER_V8;
2490 HandleScope scope;
2491 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name,
2492 getter, setter, data,
2493 settings, attributes);
2494 i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info);
2495 return !result.is_null() && !result->IsUndefined();
2496}
2497
2498
Steve Blocka7e24c12009-10-30 11:49:00 +00002499bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2500 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2501 return Utils::OpenHandle(this)->HasRealNamedProperty(
2502 *Utils::OpenHandle(*key));
2503}
2504
2505
2506bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2507 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2508 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2509}
2510
2511
2512bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2513 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2514 ENTER_V8;
2515 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2516 *Utils::OpenHandle(*key));
2517}
2518
2519
2520bool v8::Object::HasNamedLookupInterceptor() {
2521 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2522 return Utils::OpenHandle(this)->HasNamedInterceptor();
2523}
2524
2525
2526bool v8::Object::HasIndexedLookupInterceptor() {
2527 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2528 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2529}
2530
2531
2532Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2533 Handle<String> key) {
2534 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2535 return Local<Value>());
2536 ENTER_V8;
2537 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2538 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2539 i::LookupResult lookup;
2540 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002541 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002542 PropertyAttributes attributes;
John Reck59135872010-11-02 12:39:01 -07002543 i::Object* property =
2544 self_obj->GetProperty(*self_obj,
2545 &lookup,
2546 *key_obj,
2547 &attributes)->ToObjectUnchecked();
2548 i::Handle<i::Object> result(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00002549 return Utils::ToLocal(result);
2550 }
2551 return Local<Value>(); // No real property was found in prototype chain.
2552}
2553
2554
2555Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2556 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
2557 ENTER_V8;
2558 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2559 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2560 i::LookupResult lookup;
2561 self_obj->LookupRealNamedProperty(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002562 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002563 PropertyAttributes attributes;
John Reck59135872010-11-02 12:39:01 -07002564 i::Object* property =
2565 self_obj->GetProperty(*self_obj,
2566 &lookup,
2567 *key_obj,
2568 &attributes)->ToObjectUnchecked();
2569 i::Handle<i::Object> result(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00002570 return Utils::ToLocal(result);
2571 }
2572 return Local<Value>(); // No real property was found in prototype chain.
2573}
2574
2575
2576// Turns on access checks by copying the map and setting the check flag.
2577// Because the object gets a new map, existing inline cache caching
2578// the old map of this object will fail.
2579void v8::Object::TurnOnAccessCheck() {
2580 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2581 ENTER_V8;
2582 HandleScope scope;
2583 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2584
2585 i::Handle<i::Map> new_map =
2586 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2587 new_map->set_is_access_check_needed(true);
2588 obj->set_map(*new_map);
2589}
2590
2591
2592bool v8::Object::IsDirty() {
2593 return Utils::OpenHandle(this)->IsDirty();
2594}
2595
2596
2597Local<v8::Object> v8::Object::Clone() {
2598 ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2599 ENTER_V8;
2600 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2601 EXCEPTION_PREAMBLE();
2602 i::Handle<i::JSObject> result = i::Copy(self);
2603 has_pending_exception = result.is_null();
2604 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2605 return Utils::ToLocal(result);
2606}
2607
2608
2609int v8::Object::GetIdentityHash() {
2610 ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2611 ENTER_V8;
2612 HandleScope scope;
2613 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2614 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2615 i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
2616 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2617 int hash_value;
2618 if (hash->IsSmi()) {
2619 hash_value = i::Smi::cast(*hash)->value();
2620 } else {
2621 int attempts = 0;
2622 do {
2623 // Generate a random 32-bit hash value but limit range to fit
2624 // within a smi.
2625 hash_value = i::V8::Random() & i::Smi::kMaxValue;
2626 attempts++;
2627 } while (hash_value == 0 && attempts < 30);
2628 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
2629 i::SetProperty(hidden_props,
2630 hash_symbol,
2631 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2632 static_cast<PropertyAttributes>(None));
2633 }
2634 return hash_value;
2635}
2636
2637
2638bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2639 v8::Handle<v8::Value> value) {
2640 ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
2641 ENTER_V8;
2642 HandleScope scope;
2643 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2644 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2645 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2646 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2647 EXCEPTION_PREAMBLE();
2648 i::Handle<i::Object> obj = i::SetProperty(
2649 hidden_props,
2650 key_obj,
2651 value_obj,
2652 static_cast<PropertyAttributes>(None));
2653 has_pending_exception = obj.is_null();
2654 EXCEPTION_BAILOUT_CHECK(false);
2655 return true;
2656}
2657
2658
2659v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2660 ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2661 ENTER_V8;
2662 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2663 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2664 if (hidden_props->IsUndefined()) {
2665 return v8::Local<v8::Value>();
2666 }
2667 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2668 EXCEPTION_PREAMBLE();
2669 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2670 has_pending_exception = result.is_null();
2671 EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2672 if (result->IsUndefined()) {
2673 return v8::Local<v8::Value>();
2674 }
2675 return Utils::ToLocal(result);
2676}
2677
2678
2679bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2680 ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2681 ENTER_V8;
2682 HandleScope scope;
2683 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2684 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2685 if (hidden_props->IsUndefined()) {
2686 return true;
2687 }
2688 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2689 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2690 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2691}
2692
2693
2694void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2695 ON_BAILOUT("v8::SetElementsToPixelData()", return);
2696 ENTER_V8;
2697 HandleScope scope;
Steve Block3ce2e202009-11-05 08:53:23 +00002698 if (!ApiCheck(length <= i::PixelArray::kMaxLength,
Steve Blocka7e24c12009-10-30 11:49:00 +00002699 "v8::Object::SetIndexedPropertiesToPixelData()",
2700 "length exceeds max acceptable value")) {
2701 return;
2702 }
2703 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2704 if (!ApiCheck(!self->IsJSArray(),
2705 "v8::Object::SetIndexedPropertiesToPixelData()",
2706 "JSArray is not supported")) {
2707 return;
2708 }
2709 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002710 i::Handle<i::Map> slow_map =
2711 i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map()));
2712 self->set_map(*slow_map);
Steve Blocka7e24c12009-10-30 11:49:00 +00002713 self->set_elements(*pixels);
2714}
2715
2716
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002717bool v8::Object::HasIndexedPropertiesInPixelData() {
2718 ON_BAILOUT("v8::HasIndexedPropertiesInPixelData()", return false);
2719 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2720 return self->HasPixelElements();
2721}
2722
2723
2724uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
2725 ON_BAILOUT("v8::GetIndexedPropertiesPixelData()", return NULL);
2726 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2727 if (self->HasPixelElements()) {
2728 return i::PixelArray::cast(self->elements())->external_pointer();
2729 } else {
2730 return NULL;
2731 }
2732}
2733
2734
2735int v8::Object::GetIndexedPropertiesPixelDataLength() {
2736 ON_BAILOUT("v8::GetIndexedPropertiesPixelDataLength()", return -1);
2737 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2738 if (self->HasPixelElements()) {
2739 return i::PixelArray::cast(self->elements())->length();
2740 } else {
2741 return -1;
2742 }
2743}
2744
2745
Steve Block3ce2e202009-11-05 08:53:23 +00002746void v8::Object::SetIndexedPropertiesToExternalArrayData(
2747 void* data,
2748 ExternalArrayType array_type,
2749 int length) {
2750 ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
2751 ENTER_V8;
2752 HandleScope scope;
2753 if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
2754 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2755 "length exceeds max acceptable value")) {
2756 return;
2757 }
2758 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2759 if (!ApiCheck(!self->IsJSArray(),
2760 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2761 "JSArray is not supported")) {
2762 return;
2763 }
2764 i::Handle<i::ExternalArray> array =
2765 i::Factory::NewExternalArray(length, array_type, data);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002766 i::Handle<i::Map> slow_map =
2767 i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map()));
2768 self->set_map(*slow_map);
Steve Block3ce2e202009-11-05 08:53:23 +00002769 self->set_elements(*array);
2770}
2771
2772
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002773bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
2774 ON_BAILOUT("v8::HasIndexedPropertiesInExternalArrayData()", return false);
2775 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2776 return self->HasExternalArrayElements();
2777}
2778
2779
2780void* v8::Object::GetIndexedPropertiesExternalArrayData() {
2781 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayData()", return NULL);
2782 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2783 if (self->HasExternalArrayElements()) {
2784 return i::ExternalArray::cast(self->elements())->external_pointer();
2785 } else {
2786 return NULL;
2787 }
2788}
2789
2790
2791ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
2792 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataType()",
2793 return static_cast<ExternalArrayType>(-1));
2794 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2795 switch (self->elements()->map()->instance_type()) {
2796 case i::EXTERNAL_BYTE_ARRAY_TYPE:
2797 return kExternalByteArray;
2798 case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2799 return kExternalUnsignedByteArray;
2800 case i::EXTERNAL_SHORT_ARRAY_TYPE:
2801 return kExternalShortArray;
2802 case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2803 return kExternalUnsignedShortArray;
2804 case i::EXTERNAL_INT_ARRAY_TYPE:
2805 return kExternalIntArray;
2806 case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2807 return kExternalUnsignedIntArray;
2808 case i::EXTERNAL_FLOAT_ARRAY_TYPE:
2809 return kExternalFloatArray;
2810 default:
2811 return static_cast<ExternalArrayType>(-1);
2812 }
2813}
2814
2815
2816int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
2817 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataLength()", return 0);
2818 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2819 if (self->HasExternalArrayElements()) {
2820 return i::ExternalArray::cast(self->elements())->length();
2821 } else {
2822 return -1;
2823 }
2824}
2825
2826
Steve Blocka7e24c12009-10-30 11:49:00 +00002827Local<v8::Object> Function::NewInstance() const {
2828 return NewInstance(0, NULL);
2829}
2830
2831
2832Local<v8::Object> Function::NewInstance(int argc,
2833 v8::Handle<v8::Value> argv[]) const {
2834 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2835 LOG_API("Function::NewInstance");
2836 ENTER_V8;
2837 HandleScope scope;
2838 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2839 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2840 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2841 EXCEPTION_PREAMBLE();
2842 i::Handle<i::Object> returned =
2843 i::Execution::New(function, argc, args, &has_pending_exception);
2844 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2845 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2846}
2847
2848
2849Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2850 v8::Handle<v8::Value> argv[]) {
2851 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2852 LOG_API("Function::Call");
2853 ENTER_V8;
2854 i::Object* raw_result = NULL;
2855 {
2856 HandleScope scope;
2857 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2858 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2859 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2860 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2861 EXCEPTION_PREAMBLE();
2862 i::Handle<i::Object> returned =
2863 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2864 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2865 raw_result = *returned;
2866 }
2867 i::Handle<i::Object> result(raw_result);
2868 return Utils::ToLocal(result);
2869}
2870
2871
2872void Function::SetName(v8::Handle<v8::String> name) {
2873 ENTER_V8;
2874 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2875 func->shared()->set_name(*Utils::OpenHandle(*name));
2876}
2877
2878
2879Handle<Value> Function::GetName() const {
2880 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2881 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2882}
2883
2884
Andrei Popescu402d9372010-02-26 13:31:12 +00002885ScriptOrigin Function::GetScriptOrigin() const {
2886 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2887 if (func->shared()->script()->IsScript()) {
2888 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2889 v8::ScriptOrigin origin(
2890 Utils::ToLocal(i::Handle<i::Object>(script->name())),
2891 v8::Integer::New(script->line_offset()->value()),
2892 v8::Integer::New(script->column_offset()->value()));
2893 return origin;
2894 }
2895 return v8::ScriptOrigin(Handle<Value>());
2896}
2897
2898
2899const int Function::kLineOffsetNotFound = -1;
2900
2901
2902int Function::GetScriptLineNumber() const {
2903 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2904 if (func->shared()->script()->IsScript()) {
2905 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2906 return i::GetScriptLineNumber(script, func->shared()->start_position());
2907 }
2908 return kLineOffsetNotFound;
2909}
2910
2911
2912namespace {
2913
2914// Tracks string usage to help make better decisions when
2915// externalizing strings.
2916//
2917// Implementation note: internally this class only tracks fresh
2918// strings and keeps a single use counter for them.
2919class StringTracker {
2920 public:
2921 // Records that the given string's characters were copied to some
2922 // external buffer. If this happens often we should honor
2923 // externalization requests for the string.
2924 static void RecordWrite(i::Handle<i::String> string) {
2925 i::Address address = reinterpret_cast<i::Address>(*string);
2926 i::Address top = i::Heap::NewSpaceTop();
2927 if (IsFreshString(address, top)) {
2928 IncrementUseCount(top);
2929 }
2930 }
2931
2932 // Estimates freshness and use frequency of the given string based
2933 // on how close it is to the new space top and the recorded usage
2934 // history.
2935 static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
2936 i::Address address = reinterpret_cast<i::Address>(*string);
2937 i::Address top = i::Heap::NewSpaceTop();
2938 return IsFreshString(address, top) && IsUseCountLow(top);
2939 }
2940
2941 private:
2942 static inline bool IsFreshString(i::Address string, i::Address top) {
2943 return top - kFreshnessLimit <= string && string <= top;
2944 }
2945
2946 static inline bool IsUseCountLow(i::Address top) {
2947 if (last_top_ != top) return true;
2948 return use_count_ < kUseLimit;
2949 }
2950
2951 static inline void IncrementUseCount(i::Address top) {
2952 if (last_top_ != top) {
2953 use_count_ = 0;
2954 last_top_ = top;
2955 }
2956 ++use_count_;
2957 }
2958
2959 // How close to the new space top a fresh string has to be.
2960 static const int kFreshnessLimit = 1024;
2961
2962 // The number of uses required to consider a string useful.
2963 static const int kUseLimit = 32;
2964
2965 // Single use counter shared by all fresh strings.
2966 static int use_count_;
2967
2968 // Last new space top when the use count above was valid.
2969 static i::Address last_top_;
2970};
2971
2972int StringTracker::use_count_ = 0;
2973i::Address StringTracker::last_top_ = NULL;
2974
2975} // namespace
2976
2977
Steve Blocka7e24c12009-10-30 11:49:00 +00002978int String::Length() const {
2979 if (IsDeadCheck("v8::String::Length()")) return 0;
2980 return Utils::OpenHandle(this)->length();
2981}
2982
2983
2984int String::Utf8Length() const {
2985 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
2986 return Utils::OpenHandle(this)->Utf8Length();
2987}
2988
2989
Steve Block6ded16b2010-05-10 14:33:55 +01002990int String::WriteUtf8(char* buffer,
2991 int capacity,
2992 int* nchars_ref,
2993 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002994 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
2995 LOG_API("String::WriteUtf8");
2996 ENTER_V8;
2997 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002998 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002999 if (hints & HINT_MANY_WRITES_EXPECTED) {
3000 // Flatten the string for efficiency. This applies whether we are
3001 // using StringInputBuffer or Get(i) to access the characters.
3002 str->TryFlatten();
3003 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003004 write_input_buffer.Reset(0, *str);
3005 int len = str->length();
3006 // Encode the first K - 3 bytes directly into the buffer since we
3007 // know there's room for them. If no capacity is given we copy all
3008 // of them here.
3009 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
3010 int i;
3011 int pos = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01003012 int nchars = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00003013 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
3014 i::uc32 c = write_input_buffer.GetNext();
3015 int written = unibrow::Utf8::Encode(buffer + pos, c);
3016 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01003017 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00003018 }
3019 if (i < len) {
3020 // For the last characters we need to check the length for each one
3021 // because they may be longer than the remaining space in the
3022 // buffer.
3023 char intermediate[unibrow::Utf8::kMaxEncodedSize];
3024 for (; i < len && pos < capacity; i++) {
3025 i::uc32 c = write_input_buffer.GetNext();
3026 int written = unibrow::Utf8::Encode(intermediate, c);
3027 if (pos + written <= capacity) {
3028 for (int j = 0; j < written; j++)
3029 buffer[pos + j] = intermediate[j];
3030 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01003031 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00003032 } else {
3033 // We've reached the end of the buffer
3034 break;
3035 }
3036 }
3037 }
Steve Block6ded16b2010-05-10 14:33:55 +01003038 if (nchars_ref != NULL) *nchars_ref = nchars;
Steve Blocka7e24c12009-10-30 11:49:00 +00003039 if (i == len && (capacity == -1 || pos < capacity))
3040 buffer[pos++] = '\0';
3041 return pos;
3042}
3043
3044
Steve Block6ded16b2010-05-10 14:33:55 +01003045int String::WriteAscii(char* buffer,
3046 int start,
3047 int length,
3048 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003049 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
3050 LOG_API("String::WriteAscii");
3051 ENTER_V8;
3052 ASSERT(start >= 0 && length >= -1);
3053 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003054 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003055 if (hints & HINT_MANY_WRITES_EXPECTED) {
3056 // Flatten the string for efficiency. This applies whether we are
3057 // using StringInputBuffer or Get(i) to access the characters.
3058 str->TryFlatten();
3059 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003060 int end = length;
3061 if ( (length == -1) || (length > str->length() - start) )
3062 end = str->length() - start;
3063 if (end < 0) return 0;
3064 write_input_buffer.Reset(start, *str);
3065 int i;
3066 for (i = 0; i < end; i++) {
3067 char c = static_cast<char>(write_input_buffer.GetNext());
3068 if (c == '\0') c = ' ';
3069 buffer[i] = c;
3070 }
3071 if (length == -1 || i < length)
3072 buffer[i] = '\0';
3073 return i;
3074}
3075
3076
Steve Block6ded16b2010-05-10 14:33:55 +01003077int String::Write(uint16_t* buffer,
3078 int start,
3079 int length,
3080 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003081 if (IsDeadCheck("v8::String::Write()")) return 0;
3082 LOG_API("String::Write");
3083 ENTER_V8;
3084 ASSERT(start >= 0 && length >= -1);
3085 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003086 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003087 if (hints & HINT_MANY_WRITES_EXPECTED) {
3088 // Flatten the string for efficiency. This applies whether we are
3089 // using StringInputBuffer or Get(i) to access the characters.
3090 str->TryFlatten();
3091 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003092 int end = length;
3093 if ( (length == -1) || (length > str->length() - start) )
3094 end = str->length() - start;
3095 if (end < 0) return 0;
3096 i::String::WriteToFlat(*str, buffer, start, end);
3097 if (length == -1 || end < length)
3098 buffer[end] = '\0';
3099 return end;
3100}
3101
3102
3103bool v8::String::IsExternal() const {
3104 EnsureInitialized("v8::String::IsExternal()");
3105 i::Handle<i::String> str = Utils::OpenHandle(this);
3106 return i::StringShape(*str).IsExternalTwoByte();
3107}
3108
3109
3110bool v8::String::IsExternalAscii() const {
3111 EnsureInitialized("v8::String::IsExternalAscii()");
3112 i::Handle<i::String> str = Utils::OpenHandle(this);
3113 return i::StringShape(*str).IsExternalAscii();
3114}
3115
3116
3117void v8::String::VerifyExternalStringResource(
3118 v8::String::ExternalStringResource* value) const {
3119 i::Handle<i::String> str = Utils::OpenHandle(this);
3120 v8::String::ExternalStringResource* expected;
3121 if (i::StringShape(*str).IsExternalTwoByte()) {
3122 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
3123 expected = reinterpret_cast<ExternalStringResource*>(resource);
3124 } else {
3125 expected = NULL;
3126 }
3127 CHECK_EQ(expected, value);
3128}
3129
3130
3131v8::String::ExternalAsciiStringResource*
3132 v8::String::GetExternalAsciiStringResource() const {
3133 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
3134 i::Handle<i::String> str = Utils::OpenHandle(this);
3135 if (i::StringShape(*str).IsExternalAscii()) {
3136 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
3137 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
3138 } else {
3139 return NULL;
3140 }
3141}
3142
3143
3144double Number::Value() const {
3145 if (IsDeadCheck("v8::Number::Value()")) return 0;
3146 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3147 return obj->Number();
3148}
3149
3150
3151bool Boolean::Value() const {
3152 if (IsDeadCheck("v8::Boolean::Value()")) return false;
3153 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3154 return obj->IsTrue();
3155}
3156
3157
3158int64_t Integer::Value() const {
3159 if (IsDeadCheck("v8::Integer::Value()")) return 0;
3160 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3161 if (obj->IsSmi()) {
3162 return i::Smi::cast(*obj)->value();
3163 } else {
3164 return static_cast<int64_t>(obj->Number());
3165 }
3166}
3167
3168
3169int32_t Int32::Value() const {
3170 if (IsDeadCheck("v8::Int32::Value()")) return 0;
3171 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3172 if (obj->IsSmi()) {
3173 return i::Smi::cast(*obj)->value();
3174 } else {
3175 return static_cast<int32_t>(obj->Number());
3176 }
3177}
3178
3179
Steve Block6ded16b2010-05-10 14:33:55 +01003180uint32_t Uint32::Value() const {
3181 if (IsDeadCheck("v8::Uint32::Value()")) return 0;
3182 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3183 if (obj->IsSmi()) {
3184 return i::Smi::cast(*obj)->value();
3185 } else {
3186 return static_cast<uint32_t>(obj->Number());
3187 }
3188}
3189
3190
Steve Blocka7e24c12009-10-30 11:49:00 +00003191int v8::Object::InternalFieldCount() {
3192 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
3193 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3194 return obj->GetInternalFieldCount();
3195}
3196
3197
3198Local<Value> v8::Object::CheckedGetInternalField(int index) {
3199 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
3200 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3201 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3202 "v8::Object::GetInternalField()",
3203 "Reading internal field out of bounds")) {
3204 return Local<Value>();
3205 }
3206 i::Handle<i::Object> value(obj->GetInternalField(index));
3207 Local<Value> result = Utils::ToLocal(value);
3208#ifdef DEBUG
3209 Local<Value> unchecked = UncheckedGetInternalField(index);
3210 ASSERT(unchecked.IsEmpty() || (unchecked == result));
3211#endif
3212 return result;
3213}
3214
3215
3216void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
3217 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
3218 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3219 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3220 "v8::Object::SetInternalField()",
3221 "Writing internal field out of bounds")) {
3222 return;
3223 }
3224 ENTER_V8;
3225 i::Handle<i::Object> val = Utils::OpenHandle(*value);
3226 obj->SetInternalField(index, *val);
3227}
3228
3229
3230void v8::Object::SetPointerInInternalField(int index, void* value) {
Steve Block6ded16b2010-05-10 14:33:55 +01003231 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003232 i::Object* as_object = reinterpret_cast<i::Object*>(value);
3233 if (as_object->IsSmi()) {
3234 Utils::OpenHandle(this)->SetInternalField(index, as_object);
3235 return;
3236 }
3237 HandleScope scope;
3238 i::Handle<i::Proxy> proxy =
3239 i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
3240 if (!proxy.is_null())
3241 Utils::OpenHandle(this)->SetInternalField(index, *proxy);
Steve Blocka7e24c12009-10-30 11:49:00 +00003242}
3243
3244
3245// --- E n v i r o n m e n t ---
3246
3247bool v8::V8::Initialize() {
3248 if (i::V8::IsRunning()) return true;
3249 ENTER_V8;
3250 HandleScope scope;
Steve Blockd0582a62009-12-15 09:54:21 +00003251 if (i::Snapshot::Initialize()) return true;
3252 return i::V8::Initialize(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00003253}
3254
3255
3256bool v8::V8::Dispose() {
3257 i::V8::TearDown();
3258 return true;
3259}
3260
3261
Steve Block3ce2e202009-11-05 08:53:23 +00003262HeapStatistics::HeapStatistics(): total_heap_size_(0), used_heap_size_(0) { }
3263
3264
3265void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
3266 heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
3267 heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
3268}
3269
3270
3271bool v8::V8::IdleNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003272 // Returning true tells the caller that it need not
3273 // continue to call IdleNotification.
3274 if (!i::V8::IsRunning()) return true;
Steve Block3ce2e202009-11-05 08:53:23 +00003275 return i::V8::IdleNotification();
Steve Blocka7e24c12009-10-30 11:49:00 +00003276}
3277
3278
3279void v8::V8::LowMemoryNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003280 if (!i::V8::IsRunning()) return;
3281 i::Heap::CollectAllGarbage(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00003282}
3283
3284
Steve Block6ded16b2010-05-10 14:33:55 +01003285int v8::V8::ContextDisposedNotification() {
3286 if (!i::V8::IsRunning()) return 0;
3287 return i::Heap::NotifyContextDisposed();
3288}
3289
3290
Steve Blocka7e24c12009-10-30 11:49:00 +00003291const char* v8::V8::GetVersion() {
3292 static v8::internal::EmbeddedVector<char, 128> buffer;
3293 v8::internal::Version::GetString(buffer);
3294 return buffer.start();
3295}
3296
3297
3298static i::Handle<i::FunctionTemplateInfo>
3299 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
3300 if (templ->constructor()->IsUndefined()) {
3301 Local<FunctionTemplate> constructor = FunctionTemplate::New();
3302 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
3303 templ->set_constructor(*Utils::OpenHandle(*constructor));
3304 }
3305 return i::Handle<i::FunctionTemplateInfo>(
3306 i::FunctionTemplateInfo::cast(templ->constructor()));
3307}
3308
3309
3310Persistent<Context> v8::Context::New(
3311 v8::ExtensionConfiguration* extensions,
3312 v8::Handle<ObjectTemplate> global_template,
3313 v8::Handle<Value> global_object) {
3314 EnsureInitialized("v8::Context::New()");
3315 LOG_API("Context::New");
3316 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
3317
3318 // Enter V8 via an ENTER_V8 scope.
3319 i::Handle<i::Context> env;
3320 {
3321 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003322 v8::Handle<ObjectTemplate> proxy_template = global_template;
3323 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
3324 i::Handle<i::FunctionTemplateInfo> global_constructor;
3325
3326 if (!global_template.IsEmpty()) {
3327 // Make sure that the global_template has a constructor.
3328 global_constructor =
3329 EnsureConstructor(Utils::OpenHandle(*global_template));
3330
3331 // Create a fresh template for the global proxy object.
3332 proxy_template = ObjectTemplate::New();
3333 proxy_constructor =
3334 EnsureConstructor(Utils::OpenHandle(*proxy_template));
3335
3336 // Set the global template to be the prototype template of
3337 // global proxy template.
3338 proxy_constructor->set_prototype_template(
3339 *Utils::OpenHandle(*global_template));
3340
3341 // Migrate security handlers from global_template to
3342 // proxy_template. Temporarily removing access check
3343 // information from the global template.
3344 if (!global_constructor->access_check_info()->IsUndefined()) {
3345 proxy_constructor->set_access_check_info(
3346 global_constructor->access_check_info());
3347 proxy_constructor->set_needs_access_check(
3348 global_constructor->needs_access_check());
3349 global_constructor->set_needs_access_check(false);
3350 global_constructor->set_access_check_info(i::Heap::undefined_value());
3351 }
3352 }
3353
3354 // Create the environment.
3355 env = i::Bootstrapper::CreateEnvironment(
3356 Utils::OpenHandle(*global_object),
3357 proxy_template,
3358 extensions);
3359
3360 // Restore the access check info on the global template.
3361 if (!global_template.IsEmpty()) {
3362 ASSERT(!global_constructor.is_null());
3363 ASSERT(!proxy_constructor.is_null());
3364 global_constructor->set_access_check_info(
3365 proxy_constructor->access_check_info());
3366 global_constructor->set_needs_access_check(
3367 proxy_constructor->needs_access_check());
3368 }
3369 }
3370 // Leave V8.
3371
3372 if (env.is_null())
3373 return Persistent<Context>();
3374 return Persistent<Context>(Utils::ToLocal(env));
3375}
3376
3377
3378void v8::Context::SetSecurityToken(Handle<Value> token) {
3379 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
3380 ENTER_V8;
3381 i::Handle<i::Context> env = Utils::OpenHandle(this);
3382 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
3383 env->set_security_token(*token_handle);
3384}
3385
3386
3387void v8::Context::UseDefaultSecurityToken() {
3388 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
3389 ENTER_V8;
3390 i::Handle<i::Context> env = Utils::OpenHandle(this);
3391 env->set_security_token(env->global());
3392}
3393
3394
3395Handle<Value> v8::Context::GetSecurityToken() {
3396 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
3397 i::Handle<i::Context> env = Utils::OpenHandle(this);
3398 i::Object* security_token = env->security_token();
3399 i::Handle<i::Object> token_handle(security_token);
3400 return Utils::ToLocal(token_handle);
3401}
3402
3403
3404bool Context::HasOutOfMemoryException() {
3405 i::Handle<i::Context> env = Utils::OpenHandle(this);
3406 return env->has_out_of_memory();
3407}
3408
3409
3410bool Context::InContext() {
3411 return i::Top::context() != NULL;
3412}
3413
3414
3415v8::Local<v8::Context> Context::GetEntered() {
3416 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
3417 i::Handle<i::Object> last = thread_local.LastEnteredContext();
3418 if (last.is_null()) return Local<Context>();
3419 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
3420 return Utils::ToLocal(context);
3421}
3422
3423
3424v8::Local<v8::Context> Context::GetCurrent() {
3425 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
Steve Block3ce2e202009-11-05 08:53:23 +00003426 i::Handle<i::Object> current = i::Top::global_context();
3427 if (current.is_null()) return Local<Context>();
3428 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
Steve Blocka7e24c12009-10-30 11:49:00 +00003429 return Utils::ToLocal(context);
3430}
3431
3432
3433v8::Local<v8::Context> Context::GetCalling() {
3434 if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
3435 i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
3436 if (calling.is_null()) return Local<Context>();
3437 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
3438 return Utils::ToLocal(context);
3439}
3440
3441
3442v8::Local<v8::Object> Context::Global() {
3443 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
3444 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3445 i::Handle<i::Context> context =
3446 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3447 i::Handle<i::Object> global(context->global_proxy());
3448 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
3449}
3450
3451
3452void Context::DetachGlobal() {
3453 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
3454 ENTER_V8;
3455 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3456 i::Handle<i::Context> context =
3457 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3458 i::Bootstrapper::DetachGlobal(context);
3459}
3460
3461
Andrei Popescu74b3c142010-03-29 12:03:09 +01003462void Context::ReattachGlobal(Handle<Object> global_object) {
3463 if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
3464 ENTER_V8;
3465 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3466 i::Handle<i::Context> context =
3467 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3468 i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
3469}
3470
3471
Steve Blocka7e24c12009-10-30 11:49:00 +00003472Local<v8::Object> ObjectTemplate::NewInstance() {
3473 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
3474 LOG_API("ObjectTemplate::NewInstance");
3475 ENTER_V8;
3476 EXCEPTION_PREAMBLE();
3477 i::Handle<i::Object> obj =
3478 i::Execution::InstantiateObject(Utils::OpenHandle(this),
3479 &has_pending_exception);
3480 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
3481 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3482}
3483
3484
3485Local<v8::Function> FunctionTemplate::GetFunction() {
3486 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
3487 return Local<v8::Function>());
3488 LOG_API("FunctionTemplate::GetFunction");
3489 ENTER_V8;
3490 EXCEPTION_PREAMBLE();
3491 i::Handle<i::Object> obj =
3492 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3493 &has_pending_exception);
3494 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
3495 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3496}
3497
3498
3499bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3500 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
3501 i::Object* obj = *Utils::OpenHandle(*value);
3502 return obj->IsInstanceOf(*Utils::OpenHandle(this));
3503}
3504
3505
3506static Local<External> ExternalNewImpl(void* data) {
3507 return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
3508}
3509
3510static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3511 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3512}
3513
3514
Steve Blocka7e24c12009-10-30 11:49:00 +00003515Local<Value> v8::External::Wrap(void* data) {
3516 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3517 LOG_API("External::Wrap");
3518 EnsureInitialized("v8::External::Wrap()");
3519 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003520 i::Object* as_object = reinterpret_cast<i::Object*>(data);
3521 if (as_object->IsSmi()) {
3522 return Utils::ToLocal(i::Handle<i::Object>(as_object));
Steve Blocka7e24c12009-10-30 11:49:00 +00003523 }
3524 return ExternalNewImpl(data);
3525}
3526
3527
Steve Block3ce2e202009-11-05 08:53:23 +00003528void* v8::Object::SlowGetPointerFromInternalField(int index) {
3529 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3530 i::Object* value = obj->GetInternalField(index);
3531 if (value->IsSmi()) {
3532 return value;
3533 } else if (value->IsProxy()) {
3534 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3535 } else {
3536 return NULL;
3537 }
3538}
3539
3540
Steve Blocka7e24c12009-10-30 11:49:00 +00003541void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3542 if (IsDeadCheck("v8::External::Unwrap()")) return 0;
3543 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3544 void* result;
3545 if (obj->IsSmi()) {
3546 // The external value was an aligned pointer.
Steve Block3ce2e202009-11-05 08:53:23 +00003547 result = *obj;
Steve Blocka7e24c12009-10-30 11:49:00 +00003548 } else if (obj->IsProxy()) {
3549 result = ExternalValueImpl(obj);
3550 } else {
3551 result = NULL;
3552 }
3553 ASSERT_EQ(result, QuickUnwrap(wrapper));
3554 return result;
3555}
3556
3557
3558Local<External> v8::External::New(void* data) {
3559 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3560 LOG_API("External::New");
3561 EnsureInitialized("v8::External::New()");
3562 ENTER_V8;
3563 return ExternalNewImpl(data);
3564}
3565
3566
3567void* External::Value() const {
3568 if (IsDeadCheck("v8::External::Value()")) return 0;
3569 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3570 return ExternalValueImpl(obj);
3571}
3572
3573
3574Local<String> v8::String::Empty() {
3575 EnsureInitialized("v8::String::Empty()");
3576 LOG_API("String::Empty()");
3577 return Utils::ToLocal(i::Factory::empty_symbol());
3578}
3579
3580
3581Local<String> v8::String::New(const char* data, int length) {
3582 EnsureInitialized("v8::String::New()");
3583 LOG_API("String::New(char)");
3584 if (length == 0) return Empty();
3585 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003586 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003587 i::Handle<i::String> result =
3588 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3589 return Utils::ToLocal(result);
3590}
3591
3592
Steve Block3ce2e202009-11-05 08:53:23 +00003593Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3594 EnsureInitialized("v8::String::New()");
3595 LOG_API("String::New(char)");
3596 ENTER_V8;
3597 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3598 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3599 i::Handle<i::String> result = i::Factory::NewConsString(left_string,
3600 right_string);
3601 return Utils::ToLocal(result);
3602}
3603
3604
Steve Blocka7e24c12009-10-30 11:49:00 +00003605Local<String> v8::String::NewUndetectable(const char* data, int length) {
3606 EnsureInitialized("v8::String::NewUndetectable()");
3607 LOG_API("String::NewUndetectable(char)");
3608 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003609 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003610 i::Handle<i::String> result =
3611 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3612 result->MarkAsUndetectable();
3613 return Utils::ToLocal(result);
3614}
3615
3616
3617static int TwoByteStringLength(const uint16_t* data) {
3618 int length = 0;
3619 while (data[length] != '\0') length++;
3620 return length;
3621}
3622
3623
3624Local<String> v8::String::New(const uint16_t* data, int length) {
3625 EnsureInitialized("v8::String::New()");
3626 LOG_API("String::New(uint16_)");
3627 if (length == 0) return Empty();
3628 ENTER_V8;
3629 if (length == -1) length = TwoByteStringLength(data);
3630 i::Handle<i::String> result =
3631 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3632 return Utils::ToLocal(result);
3633}
3634
3635
3636Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
3637 EnsureInitialized("v8::String::NewUndetectable()");
3638 LOG_API("String::NewUndetectable(uint16_)");
3639 ENTER_V8;
3640 if (length == -1) length = TwoByteStringLength(data);
3641 i::Handle<i::String> result =
3642 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3643 result->MarkAsUndetectable();
3644 return Utils::ToLocal(result);
3645}
3646
3647
3648i::Handle<i::String> NewExternalStringHandle(
3649 v8::String::ExternalStringResource* resource) {
3650 i::Handle<i::String> result =
3651 i::Factory::NewExternalStringFromTwoByte(resource);
3652 return result;
3653}
3654
3655
3656i::Handle<i::String> NewExternalAsciiStringHandle(
3657 v8::String::ExternalAsciiStringResource* resource) {
3658 i::Handle<i::String> result =
3659 i::Factory::NewExternalStringFromAscii(resource);
3660 return result;
3661}
3662
3663
Steve Blocka7e24c12009-10-30 11:49:00 +00003664Local<String> v8::String::NewExternal(
3665 v8::String::ExternalStringResource* resource) {
3666 EnsureInitialized("v8::String::NewExternal()");
3667 LOG_API("String::NewExternal");
3668 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003669 i::Handle<i::String> result = NewExternalStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003670 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003671 return Utils::ToLocal(result);
3672}
3673
3674
3675bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3676 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3677 if (this->IsExternal()) return false; // Already an external string.
3678 ENTER_V8;
3679 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003680 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003681 bool result = obj->MakeExternal(resource);
3682 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003683 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003684 }
3685 return result;
3686}
3687
3688
3689Local<String> v8::String::NewExternal(
3690 v8::String::ExternalAsciiStringResource* resource) {
3691 EnsureInitialized("v8::String::NewExternal()");
3692 LOG_API("String::NewExternal");
3693 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003694 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003695 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003696 return Utils::ToLocal(result);
3697}
3698
3699
3700bool v8::String::MakeExternal(
3701 v8::String::ExternalAsciiStringResource* resource) {
3702 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3703 if (this->IsExternal()) return false; // Already an external string.
3704 ENTER_V8;
3705 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003706 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003707 bool result = obj->MakeExternal(resource);
3708 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003709 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003710 }
3711 return result;
3712}
3713
3714
3715bool v8::String::CanMakeExternal() {
3716 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3717 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003718 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003719 int size = obj->Size(); // Byte size of the original string.
3720 if (size < i::ExternalString::kSize)
3721 return false;
3722 i::StringShape shape(*obj);
3723 return !shape.IsExternal();
3724}
3725
3726
3727Local<v8::Object> v8::Object::New() {
3728 EnsureInitialized("v8::Object::New()");
3729 LOG_API("Object::New");
3730 ENTER_V8;
3731 i::Handle<i::JSObject> obj =
3732 i::Factory::NewJSObject(i::Top::object_function());
3733 return Utils::ToLocal(obj);
3734}
3735
3736
3737Local<v8::Value> v8::Date::New(double time) {
3738 EnsureInitialized("v8::Date::New()");
3739 LOG_API("Date::New");
Steve Blockd0582a62009-12-15 09:54:21 +00003740 if (isnan(time)) {
3741 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3742 time = i::OS::nan_value();
3743 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003744 ENTER_V8;
3745 EXCEPTION_PREAMBLE();
3746 i::Handle<i::Object> obj =
3747 i::Execution::NewDate(time, &has_pending_exception);
3748 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3749 return Utils::ToLocal(obj);
3750}
3751
3752
3753double v8::Date::NumberValue() const {
3754 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3755 LOG_API("Date::NumberValue");
3756 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3757 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3758 return jsvalue->value()->Number();
3759}
3760
3761
Ben Murdochf87a2032010-10-22 12:50:53 +01003762static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
3763 char flags_buf[3];
3764 int num_flags = 0;
3765 if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
3766 if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
3767 if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
3768 ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
3769 return i::Factory::LookupSymbol(
3770 i::Vector<const char>(flags_buf, num_flags));
3771}
3772
3773
3774Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
3775 Flags flags) {
3776 EnsureInitialized("v8::RegExp::New()");
3777 LOG_API("RegExp::New");
3778 ENTER_V8;
3779 EXCEPTION_PREAMBLE();
3780 i::Handle<i::JSRegExp> obj = i::Execution::NewJSRegExp(
3781 Utils::OpenHandle(*pattern),
3782 RegExpFlagsToString(flags),
3783 &has_pending_exception);
3784 EXCEPTION_BAILOUT_CHECK(Local<v8::RegExp>());
3785 return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
3786}
3787
3788
3789Local<v8::String> v8::RegExp::GetSource() const {
3790 if (IsDeadCheck("v8::RegExp::GetSource()")) return Local<v8::String>();
3791 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
3792 return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
3793}
3794
3795
3796// Assert that the static flags cast in GetFlags is valid.
3797#define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \
3798 STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \
3799 static_cast<int>(i::JSRegExp::internal_flag))
3800REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
3801REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
3802REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
3803REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
3804#undef REGEXP_FLAG_ASSERT_EQ
3805
3806v8::RegExp::Flags v8::RegExp::GetFlags() const {
3807 if (IsDeadCheck("v8::RegExp::GetFlags()")) return v8::RegExp::kNone;
3808 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
3809 return static_cast<RegExp::Flags>(obj->GetFlags().value());
3810}
3811
3812
Steve Blocka7e24c12009-10-30 11:49:00 +00003813Local<v8::Array> v8::Array::New(int length) {
3814 EnsureInitialized("v8::Array::New()");
3815 LOG_API("Array::New");
3816 ENTER_V8;
3817 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3818 return Utils::ToLocal(obj);
3819}
3820
3821
3822uint32_t v8::Array::Length() const {
3823 if (IsDeadCheck("v8::Array::Length()")) return 0;
3824 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3825 i::Object* length = obj->length();
3826 if (length->IsSmi()) {
3827 return i::Smi::cast(length)->value();
3828 } else {
3829 return static_cast<uint32_t>(length->Number());
3830 }
3831}
3832
3833
3834Local<Object> Array::CloneElementAt(uint32_t index) {
3835 ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3836 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3837 if (!self->HasFastElements()) {
3838 return Local<Object>();
3839 }
3840 i::FixedArray* elms = i::FixedArray::cast(self->elements());
3841 i::Object* paragon = elms->get(index);
3842 if (!paragon->IsJSObject()) {
3843 return Local<Object>();
3844 }
3845 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3846 EXCEPTION_PREAMBLE();
Steve Block6ded16b2010-05-10 14:33:55 +01003847 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003848 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3849 has_pending_exception = result.is_null();
3850 EXCEPTION_BAILOUT_CHECK(Local<Object>());
3851 return Utils::ToLocal(result);
3852}
3853
3854
3855Local<String> v8::String::NewSymbol(const char* data, int length) {
3856 EnsureInitialized("v8::String::NewSymbol()");
3857 LOG_API("String::NewSymbol(char)");
3858 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003859 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003860 i::Handle<i::String> result =
3861 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3862 return Utils::ToLocal(result);
3863}
3864
3865
3866Local<Number> v8::Number::New(double value) {
3867 EnsureInitialized("v8::Number::New()");
Steve Blockd0582a62009-12-15 09:54:21 +00003868 if (isnan(value)) {
3869 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3870 value = i::OS::nan_value();
3871 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003872 ENTER_V8;
3873 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3874 return Utils::NumberToLocal(result);
3875}
3876
3877
3878Local<Integer> v8::Integer::New(int32_t value) {
3879 EnsureInitialized("v8::Integer::New()");
3880 if (i::Smi::IsValid(value)) {
3881 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3882 }
3883 ENTER_V8;
3884 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3885 return Utils::IntegerToLocal(result);
3886}
3887
3888
Steve Block3ce2e202009-11-05 08:53:23 +00003889Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
3890 bool fits_into_int32_t = (value & (1 << 31)) == 0;
3891 if (fits_into_int32_t) {
3892 return Integer::New(static_cast<int32_t>(value));
3893 }
3894 ENTER_V8;
3895 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3896 return Utils::IntegerToLocal(result);
3897}
3898
3899
Steve Blocka7e24c12009-10-30 11:49:00 +00003900void V8::IgnoreOutOfMemoryException() {
3901 thread_local.set_ignore_out_of_memory(true);
3902}
3903
3904
3905bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
3906 EnsureInitialized("v8::V8::AddMessageListener()");
3907 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
3908 ENTER_V8;
3909 HandleScope scope;
3910 NeanderArray listeners(i::Factory::message_listeners());
3911 NeanderObject obj(2);
3912 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
3913 obj.set(1, data.IsEmpty() ?
3914 i::Heap::undefined_value() :
3915 *Utils::OpenHandle(*data));
3916 listeners.add(obj.value());
3917 return true;
3918}
3919
3920
3921void V8::RemoveMessageListeners(MessageCallback that) {
3922 EnsureInitialized("v8::V8::RemoveMessageListener()");
3923 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
3924 ENTER_V8;
3925 HandleScope scope;
3926 NeanderArray listeners(i::Factory::message_listeners());
3927 for (int i = 0; i < listeners.length(); i++) {
3928 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
3929
3930 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
3931 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
3932 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
3933 listeners.set(i, i::Heap::undefined_value());
3934 }
3935 }
3936}
3937
3938
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003939void V8::SetCaptureStackTraceForUncaughtExceptions(
3940 bool capture,
3941 int frame_limit,
3942 StackTrace::StackTraceOptions options) {
3943 i::Top::SetCaptureStackTraceForUncaughtExceptions(
3944 capture,
3945 frame_limit,
3946 options);
3947}
3948
3949
Steve Blocka7e24c12009-10-30 11:49:00 +00003950void V8::SetCounterFunction(CounterLookupCallback callback) {
3951 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
3952 i::StatsTable::SetCounterFunction(callback);
3953}
3954
3955void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
3956 if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
3957 i::StatsTable::SetCreateHistogramFunction(callback);
3958}
3959
3960void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
3961 if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
3962 i::StatsTable::SetAddHistogramSampleFunction(callback);
3963}
3964
3965void V8::EnableSlidingStateWindow() {
3966 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
3967 i::Logger::EnableSlidingStateWindow();
3968}
3969
3970
3971void V8::SetFailedAccessCheckCallbackFunction(
3972 FailedAccessCheckCallback callback) {
3973 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
3974 i::Top::SetFailedAccessCheckCallback(callback);
3975}
3976
3977
3978void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
3979 if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
3980 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
3981 i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
3982}
3983
3984
3985int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
3986 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
3987 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
3988}
3989
3990
3991void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
3992 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
3993 i::Heap::SetGlobalGCPrologueCallback(callback);
3994}
3995
3996
3997void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
3998 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
3999 i::Heap::SetGlobalGCEpilogueCallback(callback);
4000}
4001
4002
Steve Block6ded16b2010-05-10 14:33:55 +01004003void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
4004 if (IsDeadCheck("v8::V8::AddGCPrologueCallback()")) return;
4005 i::Heap::AddGCPrologueCallback(callback, gc_type);
4006}
4007
4008
4009void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
4010 if (IsDeadCheck("v8::V8::RemoveGCPrologueCallback()")) return;
4011 i::Heap::RemoveGCPrologueCallback(callback);
4012}
4013
4014
4015void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
4016 if (IsDeadCheck("v8::V8::AddGCEpilogueCallback()")) return;
4017 i::Heap::AddGCEpilogueCallback(callback, gc_type);
4018}
4019
4020
4021void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
4022 if (IsDeadCheck("v8::V8::RemoveGCEpilogueCallback()")) return;
4023 i::Heap::RemoveGCEpilogueCallback(callback);
4024}
4025
4026
Iain Merrick9ac36c92010-09-13 15:29:50 +01004027void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
4028 ObjectSpace space,
4029 AllocationAction action) {
4030 if (IsDeadCheck("v8::V8::AddMemoryAllocationCallback()")) return;
4031 i::MemoryAllocator::AddMemoryAllocationCallback(callback,
4032 space,
4033 action);
4034}
4035
4036
4037void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
4038 if (IsDeadCheck("v8::V8::RemoveMemoryAllocationCallback()")) return;
4039 i::MemoryAllocator::RemoveMemoryAllocationCallback(callback);
4040}
4041
4042
Steve Blocka7e24c12009-10-30 11:49:00 +00004043void V8::PauseProfiler() {
4044#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004045 PauseProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00004046#endif
4047}
4048
4049
4050void V8::ResumeProfiler() {
4051#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004052 ResumeProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00004053#endif
4054}
4055
4056
4057bool V8::IsProfilerPaused() {
4058#ifdef ENABLE_LOGGING_AND_PROFILING
4059 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
4060#else
4061 return true;
4062#endif
4063}
4064
4065
Andrei Popescu402d9372010-02-26 13:31:12 +00004066void V8::ResumeProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004067#ifdef ENABLE_LOGGING_AND_PROFILING
4068 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
4069 // Snapshot mode: resume modules, perform GC, then pause only
4070 // those modules which haven't been started prior to making a
4071 // snapshot.
4072
Steve Block6ded16b2010-05-10 14:33:55 +01004073 // Make a GC prior to taking a snapshot.
4074 i::Heap::CollectAllGarbage(false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004075 // Reset snapshot flag and CPU module flags.
4076 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
4077 const int current_flags = i::Logger::GetActiveProfilerModules();
Andrei Popescu402d9372010-02-26 13:31:12 +00004078 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004079 i::Heap::CollectAllGarbage(false);
Andrei Popescu402d9372010-02-26 13:31:12 +00004080 i::Logger::PauseProfiler(~current_flags & flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004081 } else {
Andrei Popescu402d9372010-02-26 13:31:12 +00004082 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004083 }
4084#endif
4085}
4086
4087
Andrei Popescu402d9372010-02-26 13:31:12 +00004088void V8::PauseProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004089#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004090 i::Logger::PauseProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004091#endif
4092}
4093
4094
4095int V8::GetActiveProfilerModules() {
4096#ifdef ENABLE_LOGGING_AND_PROFILING
4097 return i::Logger::GetActiveProfilerModules();
4098#else
4099 return PROFILER_MODULE_NONE;
4100#endif
4101}
4102
4103
4104int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
4105#ifdef ENABLE_LOGGING_AND_PROFILING
Steve Block6ded16b2010-05-10 14:33:55 +01004106 ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
Steve Blocka7e24c12009-10-30 11:49:00 +00004107 return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
4108#endif
4109 return 0;
4110}
4111
4112
4113int V8::GetCurrentThreadId() {
4114 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
4115 EnsureInitialized("V8::GetCurrentThreadId()");
4116 return i::Top::thread_id();
4117}
4118
4119
4120void V8::TerminateExecution(int thread_id) {
4121 if (!i::V8::IsRunning()) return;
4122 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
4123 // If the thread_id identifies the current thread just terminate
4124 // execution right away. Otherwise, ask the thread manager to
4125 // terminate the thread with the given id if any.
4126 if (thread_id == i::Top::thread_id()) {
4127 i::StackGuard::TerminateExecution();
4128 } else {
4129 i::ThreadManager::TerminateExecution(thread_id);
4130 }
4131}
4132
4133
4134void V8::TerminateExecution() {
4135 if (!i::V8::IsRunning()) return;
4136 i::StackGuard::TerminateExecution();
4137}
4138
4139
Steve Block6ded16b2010-05-10 14:33:55 +01004140bool V8::IsExecutionTerminating() {
4141 if (!i::V8::IsRunning()) return false;
4142 if (i::Top::has_scheduled_exception()) {
4143 return i::Top::scheduled_exception() == i::Heap::termination_exception();
4144 }
4145 return false;
4146}
4147
4148
Steve Blocka7e24c12009-10-30 11:49:00 +00004149String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
4150 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
4151 if (obj.IsEmpty()) {
4152 str_ = NULL;
4153 length_ = 0;
4154 return;
4155 }
4156 ENTER_V8;
4157 HandleScope scope;
4158 TryCatch try_catch;
4159 Handle<String> str = obj->ToString();
4160 if (str.IsEmpty()) {
4161 str_ = NULL;
4162 length_ = 0;
4163 } else {
4164 length_ = str->Utf8Length();
4165 str_ = i::NewArray<char>(length_ + 1);
4166 str->WriteUtf8(str_);
4167 }
4168}
4169
4170
4171String::Utf8Value::~Utf8Value() {
4172 i::DeleteArray(str_);
4173}
4174
4175
4176String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
4177 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
4178 if (obj.IsEmpty()) {
4179 str_ = NULL;
4180 length_ = 0;
4181 return;
4182 }
4183 ENTER_V8;
4184 HandleScope scope;
4185 TryCatch try_catch;
4186 Handle<String> str = obj->ToString();
4187 if (str.IsEmpty()) {
4188 str_ = NULL;
4189 length_ = 0;
4190 } else {
4191 length_ = str->Length();
4192 str_ = i::NewArray<char>(length_ + 1);
4193 str->WriteAscii(str_);
4194 }
4195}
4196
4197
4198String::AsciiValue::~AsciiValue() {
4199 i::DeleteArray(str_);
4200}
4201
4202
4203String::Value::Value(v8::Handle<v8::Value> obj) {
4204 EnsureInitialized("v8::String::Value::Value()");
4205 if (obj.IsEmpty()) {
4206 str_ = NULL;
4207 length_ = 0;
4208 return;
4209 }
4210 ENTER_V8;
4211 HandleScope scope;
4212 TryCatch try_catch;
4213 Handle<String> str = obj->ToString();
4214 if (str.IsEmpty()) {
4215 str_ = NULL;
4216 length_ = 0;
4217 } else {
4218 length_ = str->Length();
4219 str_ = i::NewArray<uint16_t>(length_ + 1);
4220 str->Write(str_);
4221 }
4222}
4223
4224
4225String::Value::~Value() {
4226 i::DeleteArray(str_);
4227}
4228
4229Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
4230 LOG_API("RangeError");
4231 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
4232 ENTER_V8;
4233 i::Object* error;
4234 {
4235 HandleScope scope;
4236 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4237 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
4238 error = *result;
4239 }
4240 i::Handle<i::Object> result(error);
4241 return Utils::ToLocal(result);
4242}
4243
4244Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
4245 LOG_API("ReferenceError");
4246 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
4247 ENTER_V8;
4248 i::Object* error;
4249 {
4250 HandleScope scope;
4251 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4252 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
4253 error = *result;
4254 }
4255 i::Handle<i::Object> result(error);
4256 return Utils::ToLocal(result);
4257}
4258
4259Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
4260 LOG_API("SyntaxError");
4261 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
4262 ENTER_V8;
4263 i::Object* error;
4264 {
4265 HandleScope scope;
4266 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4267 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
4268 error = *result;
4269 }
4270 i::Handle<i::Object> result(error);
4271 return Utils::ToLocal(result);
4272}
4273
4274Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
4275 LOG_API("TypeError");
4276 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
4277 ENTER_V8;
4278 i::Object* error;
4279 {
4280 HandleScope scope;
4281 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4282 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
4283 error = *result;
4284 }
4285 i::Handle<i::Object> result(error);
4286 return Utils::ToLocal(result);
4287}
4288
4289Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
4290 LOG_API("Error");
4291 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
4292 ENTER_V8;
4293 i::Object* error;
4294 {
4295 HandleScope scope;
4296 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4297 i::Handle<i::Object> result = i::Factory::NewError(message);
4298 error = *result;
4299 }
4300 i::Handle<i::Object> result(error);
4301 return Utils::ToLocal(result);
4302}
4303
4304
4305// --- D e b u g S u p p o r t ---
4306
4307#ifdef ENABLE_DEBUGGER_SUPPORT
Leon Clarkef7060e22010-06-03 12:02:55 +01004308
4309static v8::Debug::EventCallback event_callback = NULL;
4310
4311static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) {
4312 if (event_callback) {
4313 event_callback(event_details.GetEvent(),
4314 event_details.GetExecutionState(),
4315 event_details.GetEventData(),
4316 event_details.GetCallbackData());
4317 }
4318}
4319
4320
Steve Blocka7e24c12009-10-30 11:49:00 +00004321bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
4322 EnsureInitialized("v8::Debug::SetDebugEventListener()");
4323 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4324 ENTER_V8;
Leon Clarkef7060e22010-06-03 12:02:55 +01004325
4326 event_callback = that;
4327
4328 HandleScope scope;
4329 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4330 if (that != NULL) {
4331 proxy = i::Factory::NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
4332 }
4333 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4334 return true;
4335}
4336
4337
4338bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
4339 EnsureInitialized("v8::Debug::SetDebugEventListener2()");
4340 ON_BAILOUT("v8::Debug::SetDebugEventListener2()", return false);
4341 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004342 HandleScope scope;
4343 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4344 if (that != NULL) {
4345 proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
4346 }
4347 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4348 return true;
4349}
4350
4351
4352bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
4353 Handle<Value> data) {
4354 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4355 ENTER_V8;
4356 i::Debugger::SetEventListener(Utils::OpenHandle(*that),
4357 Utils::OpenHandle(*data));
4358 return true;
4359}
4360
4361
4362void Debug::DebugBreak() {
4363 if (!i::V8::IsRunning()) return;
4364 i::StackGuard::DebugBreak();
4365}
4366
4367
Ben Murdochf87a2032010-10-22 12:50:53 +01004368void Debug::CancelDebugBreak() {
4369 i::StackGuard::Continue(i::DEBUGBREAK);
4370}
4371
4372
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004373void Debug::DebugBreakForCommand(ClientData* data) {
4374 if (!i::V8::IsRunning()) return;
4375 i::Debugger::EnqueueDebugCommand(data);
4376}
4377
4378
Steve Blocka7e24c12009-10-30 11:49:00 +00004379static v8::Debug::MessageHandler message_handler = NULL;
4380
4381static void MessageHandlerWrapper(const v8::Debug::Message& message) {
4382 if (message_handler) {
4383 v8::String::Value json(message.GetJSON());
4384 message_handler(*json, json.length(), message.GetClientData());
4385 }
4386}
4387
4388
4389void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
4390 bool message_handler_thread) {
4391 EnsureInitialized("v8::Debug::SetMessageHandler");
4392 ENTER_V8;
4393 // Message handler thread not supported any more. Parameter temporally left in
4394 // the API for client compatability reasons.
4395 CHECK(!message_handler_thread);
4396
4397 // TODO(sgjesse) support the old message handler API through a simple wrapper.
4398 message_handler = handler;
4399 if (message_handler != NULL) {
4400 i::Debugger::SetMessageHandler(MessageHandlerWrapper);
4401 } else {
4402 i::Debugger::SetMessageHandler(NULL);
4403 }
4404}
4405
4406
4407void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
4408 EnsureInitialized("v8::Debug::SetMessageHandler");
4409 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004410 i::Debugger::SetMessageHandler(handler);
4411}
4412
4413
4414void Debug::SendCommand(const uint16_t* command, int length,
4415 ClientData* client_data) {
4416 if (!i::V8::IsRunning()) return;
4417 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
4418 client_data);
4419}
4420
4421
4422void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
4423 int period) {
4424 EnsureInitialized("v8::Debug::SetHostDispatchHandler");
4425 ENTER_V8;
4426 i::Debugger::SetHostDispatchHandler(handler, period);
4427}
4428
4429
Steve Blockd0582a62009-12-15 09:54:21 +00004430void Debug::SetDebugMessageDispatchHandler(
Leon Clarkee46be812010-01-19 14:06:41 +00004431 DebugMessageDispatchHandler handler, bool provide_locker) {
Steve Blockd0582a62009-12-15 09:54:21 +00004432 EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
4433 ENTER_V8;
Leon Clarkee46be812010-01-19 14:06:41 +00004434 i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
Steve Blockd0582a62009-12-15 09:54:21 +00004435}
4436
4437
Steve Blocka7e24c12009-10-30 11:49:00 +00004438Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
4439 v8::Handle<v8::Value> data) {
4440 if (!i::V8::IsRunning()) return Local<Value>();
4441 ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
4442 ENTER_V8;
4443 i::Handle<i::Object> result;
4444 EXCEPTION_PREAMBLE();
4445 if (data.IsEmpty()) {
4446 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4447 i::Factory::undefined_value(),
4448 &has_pending_exception);
4449 } else {
4450 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4451 Utils::OpenHandle(*data),
4452 &has_pending_exception);
4453 }
4454 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4455 return Utils::ToLocal(result);
4456}
4457
4458
4459Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
4460 if (!i::V8::IsRunning()) return Local<Value>();
4461 ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
4462 ENTER_V8;
4463 v8::HandleScope scope;
4464 i::Debug::Load();
4465 i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
4466 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
4467 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
4468 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
4469 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
4470 const int kArgc = 1;
4471 v8::Handle<v8::Value> argv[kArgc] = { obj };
4472 EXCEPTION_PREAMBLE();
4473 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
4474 kArgc,
4475 argv);
4476 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4477 return scope.Close(result);
4478}
4479
4480
Leon Clarkee46be812010-01-19 14:06:41 +00004481bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
4482 return i::Debugger::StartAgent(name, port, wait_for_connection);
Steve Blocka7e24c12009-10-30 11:49:00 +00004483}
Leon Clarkee46be812010-01-19 14:06:41 +00004484
4485void Debug::ProcessDebugMessages() {
4486 i::Execution::ProcessDebugMesssages(true);
4487}
4488
Steve Block6ded16b2010-05-10 14:33:55 +01004489Local<Context> Debug::GetDebugContext() {
4490 EnsureInitialized("v8::Debug::GetDebugContext()");
4491 ENTER_V8;
4492 return Utils::ToLocal(i::Debugger::GetDebugContext());
4493}
4494
Steve Blocka7e24c12009-10-30 11:49:00 +00004495#endif // ENABLE_DEBUGGER_SUPPORT
4496
Steve Block6ded16b2010-05-10 14:33:55 +01004497
4498#ifdef ENABLE_LOGGING_AND_PROFILING
4499
4500Handle<String> CpuProfileNode::GetFunctionName() const {
4501 IsDeadCheck("v8::CpuProfileNode::GetFunctionName");
4502 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4503 const i::CodeEntry* entry = node->entry();
4504 if (!entry->has_name_prefix()) {
4505 return Handle<String>(ToApi<String>(
4506 i::Factory::LookupAsciiSymbol(entry->name())));
4507 } else {
4508 return Handle<String>(ToApi<String>(i::Factory::NewConsString(
4509 i::Factory::LookupAsciiSymbol(entry->name_prefix()),
4510 i::Factory::LookupAsciiSymbol(entry->name()))));
4511 }
4512}
4513
4514
4515Handle<String> CpuProfileNode::GetScriptResourceName() const {
4516 IsDeadCheck("v8::CpuProfileNode::GetScriptResourceName");
4517 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4518 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4519 node->entry()->resource_name())));
4520}
4521
4522
4523int CpuProfileNode::GetLineNumber() const {
4524 IsDeadCheck("v8::CpuProfileNode::GetLineNumber");
4525 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
4526}
4527
4528
4529double CpuProfileNode::GetTotalTime() const {
4530 IsDeadCheck("v8::CpuProfileNode::GetTotalTime");
4531 return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis();
4532}
4533
4534
4535double CpuProfileNode::GetSelfTime() const {
4536 IsDeadCheck("v8::CpuProfileNode::GetSelfTime");
4537 return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis();
4538}
4539
4540
4541double CpuProfileNode::GetTotalSamplesCount() const {
4542 IsDeadCheck("v8::CpuProfileNode::GetTotalSamplesCount");
4543 return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
4544}
4545
4546
4547double CpuProfileNode::GetSelfSamplesCount() const {
4548 IsDeadCheck("v8::CpuProfileNode::GetSelfSamplesCount");
4549 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
4550}
4551
4552
4553unsigned CpuProfileNode::GetCallUid() const {
4554 IsDeadCheck("v8::CpuProfileNode::GetCallUid");
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004555 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
Steve Block6ded16b2010-05-10 14:33:55 +01004556}
4557
4558
4559int CpuProfileNode::GetChildrenCount() const {
4560 IsDeadCheck("v8::CpuProfileNode::GetChildrenCount");
4561 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
4562}
4563
4564
4565const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
4566 IsDeadCheck("v8::CpuProfileNode::GetChild");
4567 const i::ProfileNode* child =
4568 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
4569 return reinterpret_cast<const CpuProfileNode*>(child);
4570}
4571
4572
4573unsigned CpuProfile::GetUid() const {
4574 IsDeadCheck("v8::CpuProfile::GetUid");
4575 return reinterpret_cast<const i::CpuProfile*>(this)->uid();
4576}
4577
4578
4579Handle<String> CpuProfile::GetTitle() const {
4580 IsDeadCheck("v8::CpuProfile::GetTitle");
4581 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4582 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4583 profile->title())));
4584}
4585
4586
4587const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
4588 IsDeadCheck("v8::CpuProfile::GetBottomUpRoot");
4589 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4590 return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
4591}
4592
4593
4594const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
4595 IsDeadCheck("v8::CpuProfile::GetTopDownRoot");
4596 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4597 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
4598}
4599
4600
4601int CpuProfiler::GetProfilesCount() {
4602 IsDeadCheck("v8::CpuProfiler::GetProfilesCount");
4603 return i::CpuProfiler::GetProfilesCount();
4604}
4605
4606
Leon Clarkef7060e22010-06-03 12:02:55 +01004607const CpuProfile* CpuProfiler::GetProfile(int index,
4608 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004609 IsDeadCheck("v8::CpuProfiler::GetProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004610 return reinterpret_cast<const CpuProfile*>(
4611 i::CpuProfiler::GetProfile(
4612 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4613 index));
Steve Block6ded16b2010-05-10 14:33:55 +01004614}
4615
4616
Leon Clarkef7060e22010-06-03 12:02:55 +01004617const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
4618 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004619 IsDeadCheck("v8::CpuProfiler::FindProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004620 return reinterpret_cast<const CpuProfile*>(
4621 i::CpuProfiler::FindProfile(
4622 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4623 uid));
Steve Block6ded16b2010-05-10 14:33:55 +01004624}
4625
4626
4627void CpuProfiler::StartProfiling(Handle<String> title) {
4628 IsDeadCheck("v8::CpuProfiler::StartProfiling");
4629 i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
4630}
4631
4632
Leon Clarkef7060e22010-06-03 12:02:55 +01004633const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
4634 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004635 IsDeadCheck("v8::CpuProfiler::StopProfiling");
4636 return reinterpret_cast<const CpuProfile*>(
Leon Clarkef7060e22010-06-03 12:02:55 +01004637 i::CpuProfiler::StopProfiling(
4638 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4639 *Utils::OpenHandle(*title)));
Steve Block6ded16b2010-05-10 14:33:55 +01004640}
4641
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004642
Iain Merrick75681382010-08-19 15:07:18 +01004643static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
4644 return const_cast<i::HeapGraphEdge*>(
4645 reinterpret_cast<const i::HeapGraphEdge*>(edge));
4646}
4647
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004648HeapGraphEdge::Type HeapGraphEdge::GetType() const {
4649 IsDeadCheck("v8::HeapGraphEdge::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004650 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004651}
4652
4653
4654Handle<Value> HeapGraphEdge::GetName() const {
4655 IsDeadCheck("v8::HeapGraphEdge::GetName");
Iain Merrick75681382010-08-19 15:07:18 +01004656 i::HeapGraphEdge* edge = ToInternal(this);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004657 switch (edge->type()) {
Iain Merrick75681382010-08-19 15:07:18 +01004658 case i::HeapGraphEdge::kContextVariable:
4659 case i::HeapGraphEdge::kInternal:
4660 case i::HeapGraphEdge::kProperty:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004661 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4662 edge->name())));
Iain Merrick75681382010-08-19 15:07:18 +01004663 case i::HeapGraphEdge::kElement:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004664 return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt(
4665 edge->index())));
4666 default: UNREACHABLE();
4667 }
4668 return ImplementationUtilities::Undefined();
4669}
4670
4671
4672const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
4673 IsDeadCheck("v8::HeapGraphEdge::GetFromNode");
Iain Merrick75681382010-08-19 15:07:18 +01004674 const i::HeapEntry* from = ToInternal(this)->From();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004675 return reinterpret_cast<const HeapGraphNode*>(from);
4676}
4677
4678
4679const HeapGraphNode* HeapGraphEdge::GetToNode() const {
4680 IsDeadCheck("v8::HeapGraphEdge::GetToNode");
Iain Merrick75681382010-08-19 15:07:18 +01004681 const i::HeapEntry* to = ToInternal(this)->to();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004682 return reinterpret_cast<const HeapGraphNode*>(to);
4683}
4684
4685
Iain Merrick75681382010-08-19 15:07:18 +01004686static i::HeapGraphPath* ToInternal(const HeapGraphPath* path) {
4687 return const_cast<i::HeapGraphPath*>(
4688 reinterpret_cast<const i::HeapGraphPath*>(path));
4689}
4690
4691
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004692int HeapGraphPath::GetEdgesCount() const {
Iain Merrick75681382010-08-19 15:07:18 +01004693 return ToInternal(this)->path()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004694}
4695
4696
4697const HeapGraphEdge* HeapGraphPath::GetEdge(int index) const {
4698 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004699 ToInternal(this)->path()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004700}
4701
4702
4703const HeapGraphNode* HeapGraphPath::GetFromNode() const {
4704 return GetEdgesCount() > 0 ? GetEdge(0)->GetFromNode() : NULL;
4705}
4706
4707
4708const HeapGraphNode* HeapGraphPath::GetToNode() const {
4709 const int count = GetEdgesCount();
4710 return count > 0 ? GetEdge(count - 1)->GetToNode() : NULL;
4711}
4712
4713
Iain Merrick75681382010-08-19 15:07:18 +01004714static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
4715 return const_cast<i::HeapEntry*>(
4716 reinterpret_cast<const i::HeapEntry*>(entry));
4717}
4718
4719
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004720HeapGraphNode::Type HeapGraphNode::GetType() const {
4721 IsDeadCheck("v8::HeapGraphNode::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004722 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004723}
4724
4725
4726Handle<String> HeapGraphNode::GetName() const {
4727 IsDeadCheck("v8::HeapGraphNode::GetName");
4728 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004729 ToInternal(this)->name())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004730}
4731
4732
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004733uint64_t HeapGraphNode::GetId() const {
4734 IsDeadCheck("v8::HeapGraphNode::GetId");
Steve Block791712a2010-08-27 10:21:07 +01004735 ASSERT(ToInternal(this)->snapshot()->type() != i::HeapSnapshot::kAggregated);
Iain Merrick75681382010-08-19 15:07:18 +01004736 return ToInternal(this)->id();
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004737}
4738
4739
Steve Block791712a2010-08-27 10:21:07 +01004740int HeapGraphNode::GetInstancesCount() const {
4741 IsDeadCheck("v8::HeapGraphNode::GetInstancesCount");
4742 ASSERT(ToInternal(this)->snapshot()->type() == i::HeapSnapshot::kAggregated);
4743 return static_cast<int>(ToInternal(this)->id());
4744}
4745
4746
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004747int HeapGraphNode::GetSelfSize() const {
4748 IsDeadCheck("v8::HeapGraphNode::GetSelfSize");
Iain Merrick75681382010-08-19 15:07:18 +01004749 return ToInternal(this)->self_size();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004750}
4751
4752
Iain Merrick75681382010-08-19 15:07:18 +01004753int HeapGraphNode::GetReachableSize() const {
4754 IsDeadCheck("v8::HeapSnapshot::GetReachableSize");
4755 return ToInternal(this)->ReachableSize();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004756}
4757
4758
Iain Merrick75681382010-08-19 15:07:18 +01004759int HeapGraphNode::GetRetainedSize() const {
4760 IsDeadCheck("v8::HeapSnapshot::GetRetainedSize");
4761 return ToInternal(this)->RetainedSize();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004762}
4763
4764
4765int HeapGraphNode::GetChildrenCount() const {
4766 IsDeadCheck("v8::HeapSnapshot::GetChildrenCount");
Iain Merrick75681382010-08-19 15:07:18 +01004767 return ToInternal(this)->children().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004768}
4769
4770
4771const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
4772 IsDeadCheck("v8::HeapSnapshot::GetChild");
4773 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004774 &ToInternal(this)->children()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004775}
4776
4777
4778int HeapGraphNode::GetRetainersCount() const {
4779 IsDeadCheck("v8::HeapSnapshot::GetRetainersCount");
Iain Merrick75681382010-08-19 15:07:18 +01004780 return ToInternal(this)->retainers().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004781}
4782
4783
4784const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const {
4785 IsDeadCheck("v8::HeapSnapshot::GetRetainer");
4786 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004787 ToInternal(this)->retainers()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004788}
4789
4790
4791int HeapGraphNode::GetRetainingPathsCount() const {
4792 IsDeadCheck("v8::HeapSnapshot::GetRetainingPathsCount");
Iain Merrick75681382010-08-19 15:07:18 +01004793 return ToInternal(this)->GetRetainingPaths()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004794}
4795
4796
4797const HeapGraphPath* HeapGraphNode::GetRetainingPath(int index) const {
4798 IsDeadCheck("v8::HeapSnapshot::GetRetainingPath");
4799 return reinterpret_cast<const HeapGraphPath*>(
Iain Merrick75681382010-08-19 15:07:18 +01004800 ToInternal(this)->GetRetainingPaths()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004801}
4802
4803
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004804const HeapGraphNode* HeapSnapshotsDiff::GetAdditionsRoot() const {
4805 IsDeadCheck("v8::HeapSnapshotsDiff::GetAdditionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004806 i::HeapSnapshotsDiff* diff =
4807 const_cast<i::HeapSnapshotsDiff*>(
4808 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004809 return reinterpret_cast<const HeapGraphNode*>(diff->additions_root());
4810}
4811
4812
4813const HeapGraphNode* HeapSnapshotsDiff::GetDeletionsRoot() const {
4814 IsDeadCheck("v8::HeapSnapshotsDiff::GetDeletionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004815 i::HeapSnapshotsDiff* diff =
4816 const_cast<i::HeapSnapshotsDiff*>(
4817 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004818 return reinterpret_cast<const HeapGraphNode*>(diff->deletions_root());
4819}
4820
4821
Iain Merrick75681382010-08-19 15:07:18 +01004822static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
4823 return const_cast<i::HeapSnapshot*>(
4824 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
4825}
4826
4827
Steve Block791712a2010-08-27 10:21:07 +01004828HeapSnapshot::Type HeapSnapshot::GetType() const {
4829 IsDeadCheck("v8::HeapSnapshot::GetType");
4830 return static_cast<HeapSnapshot::Type>(ToInternal(this)->type());
4831}
4832
4833
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004834unsigned HeapSnapshot::GetUid() const {
4835 IsDeadCheck("v8::HeapSnapshot::GetUid");
Iain Merrick75681382010-08-19 15:07:18 +01004836 return ToInternal(this)->uid();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004837}
4838
4839
4840Handle<String> HeapSnapshot::GetTitle() const {
4841 IsDeadCheck("v8::HeapSnapshot::GetTitle");
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004842 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004843 ToInternal(this)->title())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004844}
4845
4846
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004847const HeapGraphNode* HeapSnapshot::GetRoot() const {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004848 IsDeadCheck("v8::HeapSnapshot::GetHead");
Iain Merrick75681382010-08-19 15:07:18 +01004849 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004850}
4851
4852
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004853const HeapSnapshotsDiff* HeapSnapshot::CompareWith(
4854 const HeapSnapshot* snapshot) const {
4855 IsDeadCheck("v8::HeapSnapshot::CompareWith");
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004856 return reinterpret_cast<const HeapSnapshotsDiff*>(
Iain Merrick75681382010-08-19 15:07:18 +01004857 ToInternal(this)->CompareWith(ToInternal(snapshot)));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004858}
4859
4860
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004861void HeapSnapshot::Serialize(OutputStream* stream,
4862 HeapSnapshot::SerializationFormat format) const {
4863 IsDeadCheck("v8::HeapSnapshot::Serialize");
4864 ApiCheck(format == kJSON,
4865 "v8::HeapSnapshot::Serialize",
4866 "Unknown serialization format");
4867 ApiCheck(stream->GetOutputEncoding() == OutputStream::kAscii,
4868 "v8::HeapSnapshot::Serialize",
4869 "Unsupported output encoding");
4870 ApiCheck(stream->GetChunkSize() > 0,
4871 "v8::HeapSnapshot::Serialize",
4872 "Invalid stream chunk size");
4873 i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
4874 serializer.Serialize(stream);
4875}
4876
4877
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004878int HeapProfiler::GetSnapshotsCount() {
4879 IsDeadCheck("v8::HeapProfiler::GetSnapshotsCount");
4880 return i::HeapProfiler::GetSnapshotsCount();
4881}
4882
4883
4884const HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
4885 IsDeadCheck("v8::HeapProfiler::GetSnapshot");
4886 return reinterpret_cast<const HeapSnapshot*>(
4887 i::HeapProfiler::GetSnapshot(index));
4888}
4889
4890
4891const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
4892 IsDeadCheck("v8::HeapProfiler::FindSnapshot");
4893 return reinterpret_cast<const HeapSnapshot*>(
4894 i::HeapProfiler::FindSnapshot(uid));
4895}
4896
4897
Steve Block791712a2010-08-27 10:21:07 +01004898const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title,
4899 HeapSnapshot::Type type) {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004900 IsDeadCheck("v8::HeapProfiler::TakeSnapshot");
Steve Block791712a2010-08-27 10:21:07 +01004901 i::HeapSnapshot::Type internal_type = i::HeapSnapshot::kFull;
4902 switch (type) {
4903 case HeapSnapshot::kFull:
4904 internal_type = i::HeapSnapshot::kFull;
4905 break;
4906 case HeapSnapshot::kAggregated:
4907 internal_type = i::HeapSnapshot::kAggregated;
4908 break;
4909 default:
4910 UNREACHABLE();
4911 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004912 return reinterpret_cast<const HeapSnapshot*>(
Steve Block791712a2010-08-27 10:21:07 +01004913 i::HeapProfiler::TakeSnapshot(*Utils::OpenHandle(*title), internal_type));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004914}
4915
Steve Block6ded16b2010-05-10 14:33:55 +01004916#endif // ENABLE_LOGGING_AND_PROFILING
4917
4918
Steve Blocka7e24c12009-10-30 11:49:00 +00004919namespace internal {
4920
4921
4922HandleScopeImplementer* HandleScopeImplementer::instance() {
4923 return &thread_local;
4924}
4925
4926
4927void HandleScopeImplementer::FreeThreadResources() {
4928 thread_local.Free();
4929}
4930
4931
4932char* HandleScopeImplementer::ArchiveThread(char* storage) {
4933 return thread_local.ArchiveThreadHelper(storage);
4934}
4935
4936
4937char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
4938 v8::ImplementationUtilities::HandleScopeData* current =
4939 v8::ImplementationUtilities::CurrentHandleScope();
4940 handle_scope_data_ = *current;
4941 memcpy(storage, this, sizeof(*this));
4942
4943 ResetAfterArchive();
4944 current->Initialize();
4945
4946 return storage + ArchiveSpacePerThread();
4947}
4948
4949
4950int HandleScopeImplementer::ArchiveSpacePerThread() {
4951 return sizeof(thread_local);
4952}
4953
4954
4955char* HandleScopeImplementer::RestoreThread(char* storage) {
4956 return thread_local.RestoreThreadHelper(storage);
4957}
4958
4959
4960char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
4961 memcpy(this, storage, sizeof(*this));
4962 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
4963 return storage + ArchiveSpacePerThread();
4964}
4965
4966
4967void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
4968 // Iterate over all handles in the blocks except for the last.
4969 for (int i = blocks()->length() - 2; i >= 0; --i) {
4970 Object** block = blocks()->at(i);
4971 v->VisitPointers(block, &block[kHandleBlockSize]);
4972 }
4973
4974 // Iterate over live handles in the last block (if any).
4975 if (!blocks()->is_empty()) {
4976 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
4977 }
4978
4979 if (!saved_contexts_.is_empty()) {
4980 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
4981 v->VisitPointers(start, start + saved_contexts_.length());
4982 }
4983}
4984
4985
4986void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
4987 v8::ImplementationUtilities::HandleScopeData* current =
4988 v8::ImplementationUtilities::CurrentHandleScope();
4989 thread_local.handle_scope_data_ = *current;
4990 thread_local.IterateThis(v);
4991}
4992
4993
4994char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
4995 HandleScopeImplementer* thread_local =
4996 reinterpret_cast<HandleScopeImplementer*>(storage);
4997 thread_local->IterateThis(v);
4998 return storage + ArchiveSpacePerThread();
4999}
5000
5001} } // namespace v8::internal