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