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