blob: 962723d4e8811b831b1f637b003a1e32a5dd887f [file] [log] [blame]
Ben Murdochf87a2032010-10-22 12:50:53 +01001// Copyright 2010 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "api.h"
Ben Murdochf87a2032010-10-22 12:50:53 +010031
Steve Blocka7e24c12009-10-30 11:49:00 +000032#include "arguments.h"
33#include "bootstrapper.h"
34#include "compiler.h"
35#include "debug.h"
36#include "execution.h"
37#include "global-handles.h"
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010038#include "heap-profiler.h"
Steve Block6ded16b2010-05-10 14:33:55 +010039#include "messages.h"
Ben Murdochf87a2032010-10-22 12:50:53 +010040#include "parser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000041#include "platform.h"
Steve Block6ded16b2010-05-10 14:33:55 +010042#include "profile-generator-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000043#include "serialize.h"
44#include "snapshot.h"
Steve Block6ded16b2010-05-10 14:33:55 +010045#include "top.h"
Steve Blockd0582a62009-12-15 09:54:21 +000046#include "utils.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000047#include "v8threads.h"
48#include "version.h"
49
Steve Block6ded16b2010-05-10 14:33:55 +010050#include "../include/v8-profiler.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000051
52#define LOG_API(expr) LOG(ApiEntryCall(expr))
53
Leon Clarkef7060e22010-06-03 12:02:55 +010054#ifdef ENABLE_VMSTATE_TRACKING
Steve Blocka7e24c12009-10-30 11:49:00 +000055#define ENTER_V8 i::VMState __state__(i::OTHER)
56#define LEAVE_V8 i::VMState __state__(i::EXTERNAL)
57#else
58#define ENTER_V8 ((void) 0)
59#define LEAVE_V8 ((void) 0)
60#endif
61
62namespace v8 {
63
Leon Clarkef7060e22010-06-03 12:02:55 +010064#define ON_BAILOUT(location, code) \
65 if (IsDeadCheck(location) || v8::V8::IsExecutionTerminating()) { \
66 code; \
67 UNREACHABLE(); \
Steve Blocka7e24c12009-10-30 11:49:00 +000068 }
69
70
71#define EXCEPTION_PREAMBLE() \
72 thread_local.IncrementCallDepth(); \
73 ASSERT(!i::Top::external_caught_exception()); \
74 bool has_pending_exception = false
75
76
77#define EXCEPTION_BAILOUT_CHECK(value) \
78 do { \
79 thread_local.DecrementCallDepth(); \
80 if (has_pending_exception) { \
81 if (thread_local.CallDepthIsZero() && i::Top::is_out_of_memory()) { \
82 if (!thread_local.ignore_out_of_memory()) \
83 i::V8::FatalProcessOutOfMemory(NULL); \
84 } \
85 bool call_depth_is_zero = thread_local.CallDepthIsZero(); \
86 i::Top::OptionalRescheduleException(call_depth_is_zero); \
87 return value; \
88 } \
89 } while (false)
90
91
92#define API_ENTRY_CHECK(msg) \
93 do { \
94 if (v8::Locker::IsActive()) { \
95 ApiCheck(i::ThreadManager::IsLockedByCurrentThread(), \
96 msg, \
97 "Entering the V8 API without proper locking in place"); \
98 } \
99 } while (false)
100
101// --- D a t a t h a t i s s p e c i f i c t o a t h r e a d ---
102
103
104static i::HandleScopeImplementer thread_local;
105
106
107// --- E x c e p t i o n B e h a v i o r ---
108
109
110static FatalErrorCallback exception_behavior = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000111
112static void DefaultFatalErrorHandler(const char* location,
113 const char* message) {
114 ENTER_V8;
115 API_Fatal(location, message);
116}
117
118
119
120static FatalErrorCallback& GetFatalErrorHandler() {
121 if (exception_behavior == NULL) {
122 exception_behavior = DefaultFatalErrorHandler;
123 }
124 return exception_behavior;
125}
126
127
128
129// When V8 cannot allocated memory FatalProcessOutOfMemory is called.
130// The default fatal error handler is called and execution is stopped.
Ben Murdochbb769b22010-08-11 14:56:33 +0100131void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
Steve Blockd0582a62009-12-15 09:54:21 +0000132 i::HeapStats heap_stats;
133 int start_marker;
134 heap_stats.start_marker = &start_marker;
135 int new_space_size;
136 heap_stats.new_space_size = &new_space_size;
137 int new_space_capacity;
138 heap_stats.new_space_capacity = &new_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100139 intptr_t old_pointer_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000140 heap_stats.old_pointer_space_size = &old_pointer_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100141 intptr_t old_pointer_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000142 heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100143 intptr_t old_data_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000144 heap_stats.old_data_space_size = &old_data_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100145 intptr_t old_data_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000146 heap_stats.old_data_space_capacity = &old_data_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100147 intptr_t code_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000148 heap_stats.code_space_size = &code_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100149 intptr_t code_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000150 heap_stats.code_space_capacity = &code_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100151 intptr_t map_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000152 heap_stats.map_space_size = &map_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100153 intptr_t map_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000154 heap_stats.map_space_capacity = &map_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100155 intptr_t cell_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000156 heap_stats.cell_space_size = &cell_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100157 intptr_t cell_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000158 heap_stats.cell_space_capacity = &cell_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100159 intptr_t lo_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000160 heap_stats.lo_space_size = &lo_space_size;
161 int global_handle_count;
162 heap_stats.global_handle_count = &global_handle_count;
163 int weak_global_handle_count;
164 heap_stats.weak_global_handle_count = &weak_global_handle_count;
165 int pending_global_handle_count;
166 heap_stats.pending_global_handle_count = &pending_global_handle_count;
167 int near_death_global_handle_count;
168 heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
169 int destroyed_global_handle_count;
170 heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count;
Ben Murdochf87a2032010-10-22 12:50:53 +0100171 intptr_t memory_allocator_size;
Ben Murdochbb769b22010-08-11 14:56:33 +0100172 heap_stats.memory_allocator_size = &memory_allocator_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100173 intptr_t memory_allocator_capacity;
Ben Murdochbb769b22010-08-11 14:56:33 +0100174 heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
175 int objects_per_type[LAST_TYPE + 1] = {0};
176 heap_stats.objects_per_type = objects_per_type;
177 int size_per_type[LAST_TYPE + 1] = {0};
178 heap_stats.size_per_type = size_per_type;
Iain Merrick75681382010-08-19 15:07:18 +0100179 int os_error;
180 heap_stats.os_error = &os_error;
Steve Blockd0582a62009-12-15 09:54:21 +0000181 int end_marker;
182 heap_stats.end_marker = &end_marker;
Ben Murdochbb769b22010-08-11 14:56:33 +0100183 i::Heap::RecordStats(&heap_stats, take_snapshot);
Steve Blocka7e24c12009-10-30 11:49:00 +0000184 i::V8::SetFatalError();
185 FatalErrorCallback callback = GetFatalErrorHandler();
186 {
187 LEAVE_V8;
188 callback(location, "Allocation failed - process out of memory");
189 }
190 // If the callback returns, we stop execution.
191 UNREACHABLE();
192}
193
194
195void V8::SetFatalErrorHandler(FatalErrorCallback that) {
196 exception_behavior = that;
197}
198
199
200bool Utils::ReportApiFailure(const char* location, const char* message) {
201 FatalErrorCallback callback = GetFatalErrorHandler();
202 callback(location, message);
203 i::V8::SetFatalError();
204 return false;
205}
206
207
208bool V8::IsDead() {
209 return i::V8::IsDead();
210}
211
212
213static inline bool ApiCheck(bool condition,
214 const char* location,
215 const char* message) {
216 return condition ? true : Utils::ReportApiFailure(location, message);
217}
218
219
220static bool ReportV8Dead(const char* location) {
221 FatalErrorCallback callback = GetFatalErrorHandler();
222 callback(location, "V8 is no longer usable");
223 return true;
224}
225
226
227static bool ReportEmptyHandle(const char* location) {
228 FatalErrorCallback callback = GetFatalErrorHandler();
229 callback(location, "Reading from empty handle");
230 return true;
231}
232
233
234/**
235 * IsDeadCheck checks that the vm is usable. If, for instance, the vm has been
236 * out of memory at some point this check will fail. It should be called on
237 * entry to all methods that touch anything in the heap, except destructors
238 * which you sometimes can't avoid calling after the vm has crashed. Functions
239 * that call EnsureInitialized or ON_BAILOUT don't have to also call
240 * IsDeadCheck. ON_BAILOUT has the advantage over EnsureInitialized that you
241 * can arrange to return if the VM is dead. This is needed to ensure that no VM
242 * heap allocations are attempted on a dead VM. EnsureInitialized has the
243 * advantage over ON_BAILOUT that it actually initializes the VM if this has not
244 * yet been done.
245 */
246static inline bool IsDeadCheck(const char* location) {
247 return !i::V8::IsRunning()
248 && i::V8::IsDead() ? ReportV8Dead(location) : false;
249}
250
251
252static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
253 return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
254}
255
256
257static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
258 return (obj == 0) ? ReportEmptyHandle(location) : false;
259}
260
261// --- S t a t i c s ---
262
263
264static i::StringInputBuffer write_input_buffer;
265
266
267static inline bool EnsureInitialized(const char* location) {
268 if (i::V8::IsRunning()) {
269 return true;
270 }
271 if (IsDeadCheck(location)) {
272 return false;
273 }
274 return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
275}
276
277
278ImplementationUtilities::HandleScopeData*
279 ImplementationUtilities::CurrentHandleScope() {
280 return &i::HandleScope::current_;
281}
282
283
284#ifdef DEBUG
285void ImplementationUtilities::ZapHandleRange(i::Object** begin,
286 i::Object** end) {
287 i::HandleScope::ZapRange(begin, end);
288}
289#endif
290
291
292v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
293 if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
294 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
295}
296
297
298v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
299 if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
300 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
301}
302
303
304v8::Handle<v8::Boolean> ImplementationUtilities::True() {
305 if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
306 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
307}
308
309
310v8::Handle<v8::Boolean> ImplementationUtilities::False() {
311 if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
312 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
313}
314
315
316void V8::SetFlagsFromString(const char* str, int length) {
317 i::FlagList::SetFlagsFromString(str, length);
318}
319
320
321void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
322 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
323}
324
325
326v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
327 if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
328 ENTER_V8;
329 // If we're passed an empty handle, we throw an undefined exception
330 // to deal more gracefully with out of memory situations.
331 if (value.IsEmpty()) {
332 i::Top::ScheduleThrow(i::Heap::undefined_value());
333 } else {
334 i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
335 }
336 return v8::Undefined();
337}
338
339
340RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
341
342
343RegisteredExtension::RegisteredExtension(Extension* extension)
344 : extension_(extension), state_(UNVISITED) { }
345
346
347void RegisteredExtension::Register(RegisteredExtension* that) {
348 that->next_ = RegisteredExtension::first_extension_;
349 RegisteredExtension::first_extension_ = that;
350}
351
352
353void RegisterExtension(Extension* that) {
354 RegisteredExtension* extension = new RegisteredExtension(that);
355 RegisteredExtension::Register(extension);
356}
357
358
359Extension::Extension(const char* name,
360 const char* source,
361 int dep_count,
362 const char** deps)
363 : name_(name),
364 source_(source),
365 dep_count_(dep_count),
366 deps_(deps),
367 auto_enable_(false) { }
368
369
370v8::Handle<Primitive> Undefined() {
371 LOG_API("Undefined");
372 return ImplementationUtilities::Undefined();
373}
374
375
376v8::Handle<Primitive> Null() {
377 LOG_API("Null");
378 return ImplementationUtilities::Null();
379}
380
381
382v8::Handle<Boolean> True() {
383 LOG_API("True");
384 return ImplementationUtilities::True();
385}
386
387
388v8::Handle<Boolean> False() {
389 LOG_API("False");
390 return ImplementationUtilities::False();
391}
392
393
394ResourceConstraints::ResourceConstraints()
395 : max_young_space_size_(0),
396 max_old_space_size_(0),
397 stack_limit_(NULL) { }
398
399
400bool SetResourceConstraints(ResourceConstraints* constraints) {
Steve Block3ce2e202009-11-05 08:53:23 +0000401 int young_space_size = constraints->max_young_space_size();
Steve Blocka7e24c12009-10-30 11:49:00 +0000402 int old_gen_size = constraints->max_old_space_size();
Steve Block3ce2e202009-11-05 08:53:23 +0000403 if (young_space_size != 0 || old_gen_size != 0) {
404 bool result = i::Heap::ConfigureHeap(young_space_size / 2, old_gen_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000405 if (!result) return false;
406 }
407 if (constraints->stack_limit() != NULL) {
408 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
409 i::StackGuard::SetStackLimit(limit);
410 }
411 return true;
412}
413
414
415i::Object** V8::GlobalizeReference(i::Object** obj) {
416 if (IsDeadCheck("V8::Persistent::New")) return NULL;
417 LOG_API("Persistent::New");
418 i::Handle<i::Object> result =
419 i::GlobalHandles::Create(*obj);
420 return result.location();
421}
422
423
424void V8::MakeWeak(i::Object** object, void* parameters,
425 WeakReferenceCallback callback) {
426 LOG_API("MakeWeak");
427 i::GlobalHandles::MakeWeak(object, parameters, callback);
428}
429
430
431void V8::ClearWeak(i::Object** obj) {
432 LOG_API("ClearWeak");
433 i::GlobalHandles::ClearWeakness(obj);
434}
435
436
437bool V8::IsGlobalNearDeath(i::Object** obj) {
438 LOG_API("IsGlobalNearDeath");
439 if (!i::V8::IsRunning()) return false;
440 return i::GlobalHandles::IsNearDeath(obj);
441}
442
443
444bool V8::IsGlobalWeak(i::Object** obj) {
445 LOG_API("IsGlobalWeak");
446 if (!i::V8::IsRunning()) return false;
447 return i::GlobalHandles::IsWeak(obj);
448}
449
450
451void V8::DisposeGlobal(i::Object** obj) {
452 LOG_API("DisposeGlobal");
453 if (!i::V8::IsRunning()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000454 i::GlobalHandles::Destroy(obj);
455}
456
457// --- H a n d l e s ---
458
459
460HandleScope::HandleScope() : is_closed_(false) {
461 API_ENTRY_CHECK("HandleScope::HandleScope");
462 i::HandleScope::Enter(&previous_);
463}
464
465
466HandleScope::~HandleScope() {
467 if (!is_closed_) {
468 i::HandleScope::Leave(&previous_);
469 }
470}
471
472
473int HandleScope::NumberOfHandles() {
474 return i::HandleScope::NumberOfHandles();
475}
476
477
478i::Object** v8::HandleScope::CreateHandle(i::Object* value) {
479 return i::HandleScope::CreateHandle(value);
480}
481
482
483void Context::Enter() {
484 if (IsDeadCheck("v8::Context::Enter()")) return;
485 ENTER_V8;
486 i::Handle<i::Context> env = Utils::OpenHandle(this);
487 thread_local.EnterContext(env);
488
489 thread_local.SaveContext(i::Top::context());
490 i::Top::set_context(*env);
491}
492
493
494void Context::Exit() {
495 if (!i::V8::IsRunning()) return;
496 if (!ApiCheck(thread_local.LeaveLastContext(),
497 "v8::Context::Exit()",
498 "Cannot exit non-entered context")) {
499 return;
500 }
501
502 // Content of 'last_context' could be NULL.
503 i::Context* last_context = thread_local.RestoreContext();
504 i::Top::set_context(last_context);
505}
506
507
Steve Blockd0582a62009-12-15 09:54:21 +0000508void Context::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000509 if (IsDeadCheck("v8::Context::SetData()")) return;
510 ENTER_V8;
511 {
512 HandleScope scope;
513 i::Handle<i::Context> env = Utils::OpenHandle(this);
514 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
515 ASSERT(env->IsGlobalContext());
516 if (env->IsGlobalContext()) {
517 env->set_data(*raw_data);
518 }
519 }
520}
521
522
523v8::Local<v8::Value> Context::GetData() {
524 if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
525 ENTER_V8;
526 i::Object* raw_result = NULL;
527 {
528 HandleScope scope;
529 i::Handle<i::Context> env = Utils::OpenHandle(this);
530 ASSERT(env->IsGlobalContext());
531 if (env->IsGlobalContext()) {
532 raw_result = env->data();
533 } else {
534 return Local<Value>();
535 }
536 }
537 i::Handle<i::Object> result(raw_result);
538 return Utils::ToLocal(result);
539}
540
541
542i::Object** v8::HandleScope::RawClose(i::Object** value) {
543 if (!ApiCheck(!is_closed_,
544 "v8::HandleScope::Close()",
545 "Local scope has already been closed")) {
546 return 0;
547 }
548 LOG_API("CloseHandleScope");
549
550 // Read the result before popping the handle block.
Steve Block6ded16b2010-05-10 14:33:55 +0100551 i::Object* result = NULL;
552 if (value != NULL) {
553 result = *value;
554 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000555 is_closed_ = true;
556 i::HandleScope::Leave(&previous_);
557
Steve Block6ded16b2010-05-10 14:33:55 +0100558 if (value == NULL) {
559 return NULL;
560 }
561
Steve Blocka7e24c12009-10-30 11:49:00 +0000562 // Allocate a new handle on the previous handle block.
563 i::Handle<i::Object> handle(result);
564 return handle.location();
565}
566
567
568// --- N e a n d e r ---
569
570
571// A constructor cannot easily return an error value, therefore it is necessary
572// to check for a dead VM with ON_BAILOUT before constructing any Neander
573// objects. To remind you about this there is no HandleScope in the
574// NeanderObject constructor. When you add one to the site calling the
575// constructor you should check that you ensured the VM was not dead first.
576NeanderObject::NeanderObject(int size) {
577 EnsureInitialized("v8::Nowhere");
578 ENTER_V8;
579 value_ = i::Factory::NewNeanderObject();
580 i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
581 value_->set_elements(*elements);
582}
583
584
585int NeanderObject::size() {
586 return i::FixedArray::cast(value_->elements())->length();
587}
588
589
590NeanderArray::NeanderArray() : obj_(2) {
591 obj_.set(0, i::Smi::FromInt(0));
592}
593
594
595int NeanderArray::length() {
596 return i::Smi::cast(obj_.get(0))->value();
597}
598
599
600i::Object* NeanderArray::get(int offset) {
601 ASSERT(0 <= offset);
602 ASSERT(offset < length());
603 return obj_.get(offset + 1);
604}
605
606
607// This method cannot easily return an error value, therefore it is necessary
608// to check for a dead VM with ON_BAILOUT before calling it. To remind you
609// about this there is no HandleScope in this method. When you add one to the
610// site calling this method you should check that you ensured the VM was not
611// dead first.
612void NeanderArray::add(i::Handle<i::Object> value) {
613 int length = this->length();
614 int size = obj_.size();
615 if (length == size - 1) {
616 i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
617 for (int i = 0; i < length; i++)
618 new_elms->set(i + 1, get(i));
619 obj_.value()->set_elements(*new_elms);
620 }
621 obj_.set(length + 1, *value);
622 obj_.set(0, i::Smi::FromInt(length + 1));
623}
624
625
626void NeanderArray::set(int index, i::Object* value) {
627 if (index < 0 || index >= this->length()) return;
628 obj_.set(index + 1, value);
629}
630
631
632// --- T e m p l a t e ---
633
634
635static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
636 that->set_tag(i::Smi::FromInt(type));
637}
638
639
640void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
641 v8::PropertyAttribute attribute) {
642 if (IsDeadCheck("v8::Template::SetProperty()")) return;
643 ENTER_V8;
644 HandleScope scope;
645 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
646 if (list->IsUndefined()) {
647 list = NeanderArray().value();
648 Utils::OpenHandle(this)->set_property_list(*list);
649 }
650 NeanderArray array(list);
651 array.add(Utils::OpenHandle(*name));
652 array.add(Utils::OpenHandle(*value));
653 array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
654}
655
656
657// --- F u n c t i o n T e m p l a t e ---
658static void InitializeFunctionTemplate(
659 i::Handle<i::FunctionTemplateInfo> info) {
660 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
661 info->set_flag(0);
662}
663
664
665Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
666 if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
667 return Local<ObjectTemplate>();
668 }
669 ENTER_V8;
670 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
671 if (result->IsUndefined()) {
672 result = Utils::OpenHandle(*ObjectTemplate::New());
673 Utils::OpenHandle(this)->set_prototype_template(*result);
674 }
675 return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
676}
677
678
679void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
680 if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
681 ENTER_V8;
682 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
683}
684
685
686// To distinguish the function templates, so that we can find them in the
687// function cache of the global context.
688static int next_serial_number = 0;
689
690
691Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
692 v8::Handle<Value> data, v8::Handle<Signature> signature) {
693 EnsureInitialized("v8::FunctionTemplate::New()");
694 LOG_API("FunctionTemplate::New");
695 ENTER_V8;
696 i::Handle<i::Struct> struct_obj =
697 i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
698 i::Handle<i::FunctionTemplateInfo> obj =
699 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
700 InitializeFunctionTemplate(obj);
701 obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
702 if (callback != 0) {
703 if (data.IsEmpty()) data = v8::Undefined();
704 Utils::ToLocal(obj)->SetCallHandler(callback, data);
705 }
706 obj->set_undetectable(false);
707 obj->set_needs_access_check(false);
708
709 if (!signature.IsEmpty())
710 obj->set_signature(*Utils::OpenHandle(*signature));
711 return Utils::ToLocal(obj);
712}
713
714
715Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
716 int argc, Handle<FunctionTemplate> argv[]) {
717 EnsureInitialized("v8::Signature::New()");
718 LOG_API("Signature::New");
719 ENTER_V8;
720 i::Handle<i::Struct> struct_obj =
721 i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
722 i::Handle<i::SignatureInfo> obj =
723 i::Handle<i::SignatureInfo>::cast(struct_obj);
724 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
725 if (argc > 0) {
726 i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
727 for (int i = 0; i < argc; i++) {
728 if (!argv[i].IsEmpty())
729 args->set(i, *Utils::OpenHandle(*argv[i]));
730 }
731 obj->set_args(*args);
732 }
733 return Utils::ToLocal(obj);
734}
735
736
737Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
738 Handle<FunctionTemplate> types[1] = { type };
739 return TypeSwitch::New(1, types);
740}
741
742
743Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
744 EnsureInitialized("v8::TypeSwitch::New()");
745 LOG_API("TypeSwitch::New");
746 ENTER_V8;
747 i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
748 for (int i = 0; i < argc; i++)
749 vector->set(i, *Utils::OpenHandle(*types[i]));
750 i::Handle<i::Struct> struct_obj =
751 i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
752 i::Handle<i::TypeSwitchInfo> obj =
753 i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
754 obj->set_types(*vector);
755 return Utils::ToLocal(obj);
756}
757
758
759int TypeSwitch::match(v8::Handle<Value> value) {
760 LOG_API("TypeSwitch::match");
761 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
762 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
763 i::FixedArray* types = i::FixedArray::cast(info->types());
764 for (int i = 0; i < types->length(); i++) {
765 if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
766 return i + 1;
767 }
768 return 0;
769}
770
771
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100772#define SET_FIELD_WRAPPED(obj, setter, cdata) do { \
773 i::Handle<i::Object> proxy = FromCData(cdata); \
774 (obj)->setter(*proxy); \
775 } while (false)
776
777
Steve Blocka7e24c12009-10-30 11:49:00 +0000778void FunctionTemplate::SetCallHandler(InvocationCallback callback,
779 v8::Handle<Value> data) {
780 if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
781 ENTER_V8;
782 HandleScope scope;
783 i::Handle<i::Struct> struct_obj =
784 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
785 i::Handle<i::CallHandlerInfo> obj =
786 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100787 SET_FIELD_WRAPPED(obj, set_callback, callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000788 if (data.IsEmpty()) data = v8::Undefined();
789 obj->set_data(*Utils::OpenHandle(*data));
790 Utils::OpenHandle(this)->set_call_code(*obj);
791}
792
793
Leon Clarkef7060e22010-06-03 12:02:55 +0100794static i::Handle<i::AccessorInfo> MakeAccessorInfo(
795 v8::Handle<String> name,
796 AccessorGetter getter,
797 AccessorSetter setter,
798 v8::Handle<Value> data,
799 v8::AccessControl settings,
800 v8::PropertyAttribute attributes) {
801 i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
802 ASSERT(getter != NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100803 SET_FIELD_WRAPPED(obj, set_getter, getter);
804 SET_FIELD_WRAPPED(obj, set_setter, setter);
Leon Clarkef7060e22010-06-03 12:02:55 +0100805 if (data.IsEmpty()) data = v8::Undefined();
806 obj->set_data(*Utils::OpenHandle(*data));
807 obj->set_name(*Utils::OpenHandle(*name));
808 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
809 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
810 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
811 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
812 return obj;
813}
814
815
Steve Blocka7e24c12009-10-30 11:49:00 +0000816void FunctionTemplate::AddInstancePropertyAccessor(
817 v8::Handle<String> name,
818 AccessorGetter getter,
819 AccessorSetter setter,
820 v8::Handle<Value> data,
821 v8::AccessControl settings,
822 v8::PropertyAttribute attributes) {
823 if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
824 return;
825 }
826 ENTER_V8;
827 HandleScope scope;
Steve Blocka7e24c12009-10-30 11:49:00 +0000828
Leon Clarkef7060e22010-06-03 12:02:55 +0100829 i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name,
830 getter, setter, data,
831 settings, attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000832 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
833 if (list->IsUndefined()) {
834 list = NeanderArray().value();
835 Utils::OpenHandle(this)->set_property_accessors(*list);
836 }
837 NeanderArray array(list);
838 array.add(obj);
839}
840
841
842Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
843 if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
844 || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
845 return Local<ObjectTemplate>();
846 ENTER_V8;
847 if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
848 Local<ObjectTemplate> templ =
849 ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
850 Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
851 }
852 i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
853 Utils::OpenHandle(this)->instance_template()));
854 return Utils::ToLocal(result);
855}
856
857
858void FunctionTemplate::SetClassName(Handle<String> name) {
859 if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
860 ENTER_V8;
861 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
862}
863
864
865void FunctionTemplate::SetHiddenPrototype(bool value) {
866 if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
867 ENTER_V8;
868 Utils::OpenHandle(this)->set_hidden_prototype(value);
869}
870
871
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100872void FunctionTemplate::SetNamedInstancePropertyHandler(
Steve Blocka7e24c12009-10-30 11:49:00 +0000873 NamedPropertyGetter getter,
874 NamedPropertySetter setter,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100875 NamedPropertyQuery query,
Steve Blocka7e24c12009-10-30 11:49:00 +0000876 NamedPropertyDeleter remover,
877 NamedPropertyEnumerator enumerator,
878 Handle<Value> data) {
879 if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
880 return;
881 }
882 ENTER_V8;
883 HandleScope scope;
884 i::Handle<i::Struct> struct_obj =
885 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
886 i::Handle<i::InterceptorInfo> obj =
887 i::Handle<i::InterceptorInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100888
889 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
890 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
891 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
892 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
893 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
894
Steve Blocka7e24c12009-10-30 11:49:00 +0000895 if (data.IsEmpty()) data = v8::Undefined();
896 obj->set_data(*Utils::OpenHandle(*data));
897 Utils::OpenHandle(this)->set_named_property_handler(*obj);
898}
899
900
901void FunctionTemplate::SetIndexedInstancePropertyHandler(
902 IndexedPropertyGetter getter,
903 IndexedPropertySetter setter,
904 IndexedPropertyQuery query,
905 IndexedPropertyDeleter remover,
906 IndexedPropertyEnumerator enumerator,
907 Handle<Value> data) {
908 if (IsDeadCheck(
909 "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
910 return;
911 }
912 ENTER_V8;
913 HandleScope scope;
914 i::Handle<i::Struct> struct_obj =
915 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
916 i::Handle<i::InterceptorInfo> obj =
917 i::Handle<i::InterceptorInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100918
919 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
920 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
921 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
922 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
923 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
924
Steve Blocka7e24c12009-10-30 11:49:00 +0000925 if (data.IsEmpty()) data = v8::Undefined();
926 obj->set_data(*Utils::OpenHandle(*data));
927 Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
928}
929
930
931void FunctionTemplate::SetInstanceCallAsFunctionHandler(
932 InvocationCallback callback,
933 Handle<Value> data) {
934 if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
935 return;
936 }
937 ENTER_V8;
938 HandleScope scope;
939 i::Handle<i::Struct> struct_obj =
940 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
941 i::Handle<i::CallHandlerInfo> obj =
942 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100943 SET_FIELD_WRAPPED(obj, set_callback, callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000944 if (data.IsEmpty()) data = v8::Undefined();
945 obj->set_data(*Utils::OpenHandle(*data));
946 Utils::OpenHandle(this)->set_instance_call_handler(*obj);
947}
948
949
950// --- O b j e c t T e m p l a t e ---
951
952
953Local<ObjectTemplate> ObjectTemplate::New() {
954 return New(Local<FunctionTemplate>());
955}
956
957
958Local<ObjectTemplate> ObjectTemplate::New(
959 v8::Handle<FunctionTemplate> constructor) {
960 if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
961 EnsureInitialized("v8::ObjectTemplate::New()");
962 LOG_API("ObjectTemplate::New");
963 ENTER_V8;
964 i::Handle<i::Struct> struct_obj =
965 i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
966 i::Handle<i::ObjectTemplateInfo> obj =
967 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
968 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
969 if (!constructor.IsEmpty())
970 obj->set_constructor(*Utils::OpenHandle(*constructor));
971 obj->set_internal_field_count(i::Smi::FromInt(0));
972 return Utils::ToLocal(obj);
973}
974
975
976// Ensure that the object template has a constructor. If no
977// constructor is available we create one.
978static void EnsureConstructor(ObjectTemplate* object_template) {
979 if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
980 Local<FunctionTemplate> templ = FunctionTemplate::New();
981 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
982 constructor->set_instance_template(*Utils::OpenHandle(object_template));
983 Utils::OpenHandle(object_template)->set_constructor(*constructor);
984 }
985}
986
987
988void ObjectTemplate::SetAccessor(v8::Handle<String> name,
989 AccessorGetter getter,
990 AccessorSetter setter,
991 v8::Handle<Value> data,
992 AccessControl settings,
993 PropertyAttribute attribute) {
994 if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
995 ENTER_V8;
996 HandleScope scope;
997 EnsureConstructor(this);
998 i::FunctionTemplateInfo* constructor =
999 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1000 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1001 Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
1002 getter,
1003 setter,
1004 data,
1005 settings,
1006 attribute);
1007}
1008
1009
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001010void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
1011 NamedPropertySetter setter,
1012 NamedPropertyQuery query,
1013 NamedPropertyDeleter remover,
1014 NamedPropertyEnumerator enumerator,
1015 Handle<Value> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001016 if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
1017 ENTER_V8;
1018 HandleScope scope;
1019 EnsureConstructor(this);
1020 i::FunctionTemplateInfo* constructor =
1021 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1022 i::Handle<i::FunctionTemplateInfo> cons(constructor);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001023 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
1024 setter,
1025 query,
1026 remover,
1027 enumerator,
1028 data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001029}
1030
1031
1032void ObjectTemplate::MarkAsUndetectable() {
1033 if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
1034 ENTER_V8;
1035 HandleScope scope;
1036 EnsureConstructor(this);
1037 i::FunctionTemplateInfo* constructor =
1038 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1039 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1040 cons->set_undetectable(true);
1041}
1042
1043
1044void ObjectTemplate::SetAccessCheckCallbacks(
1045 NamedSecurityCallback named_callback,
1046 IndexedSecurityCallback indexed_callback,
1047 Handle<Value> data,
1048 bool turned_on_by_default) {
1049 if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
1050 ENTER_V8;
1051 HandleScope scope;
1052 EnsureConstructor(this);
1053
1054 i::Handle<i::Struct> struct_info =
1055 i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1056 i::Handle<i::AccessCheckInfo> info =
1057 i::Handle<i::AccessCheckInfo>::cast(struct_info);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001058
1059 SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
1060 SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
1061
Steve Blocka7e24c12009-10-30 11:49:00 +00001062 if (data.IsEmpty()) data = v8::Undefined();
1063 info->set_data(*Utils::OpenHandle(*data));
1064
1065 i::FunctionTemplateInfo* constructor =
1066 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1067 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1068 cons->set_access_check_info(*info);
1069 cons->set_needs_access_check(turned_on_by_default);
1070}
1071
1072
1073void ObjectTemplate::SetIndexedPropertyHandler(
1074 IndexedPropertyGetter getter,
1075 IndexedPropertySetter setter,
1076 IndexedPropertyQuery query,
1077 IndexedPropertyDeleter remover,
1078 IndexedPropertyEnumerator enumerator,
1079 Handle<Value> data) {
1080 if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
1081 ENTER_V8;
1082 HandleScope scope;
1083 EnsureConstructor(this);
1084 i::FunctionTemplateInfo* constructor =
1085 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1086 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1087 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
1088 setter,
1089 query,
1090 remover,
1091 enumerator,
1092 data);
1093}
1094
1095
1096void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1097 Handle<Value> data) {
1098 if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
1099 ENTER_V8;
1100 HandleScope scope;
1101 EnsureConstructor(this);
1102 i::FunctionTemplateInfo* constructor =
1103 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1104 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1105 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1106}
1107
1108
1109int ObjectTemplate::InternalFieldCount() {
1110 if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
1111 return 0;
1112 }
1113 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1114}
1115
1116
1117void ObjectTemplate::SetInternalFieldCount(int value) {
1118 if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
1119 if (!ApiCheck(i::Smi::IsValid(value),
1120 "v8::ObjectTemplate::SetInternalFieldCount()",
1121 "Invalid internal field count")) {
1122 return;
1123 }
1124 ENTER_V8;
1125 if (value > 0) {
1126 // The internal field count is set by the constructor function's
1127 // construct code, so we ensure that there is a constructor
1128 // function to do the setting.
1129 EnsureConstructor(this);
1130 }
1131 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1132}
1133
1134
1135// --- S c r i p t D a t a ---
1136
1137
1138ScriptData* ScriptData::PreCompile(const char* input, int length) {
1139 unibrow::Utf8InputBuffer<> buf(input, length);
Ben Murdochf87a2032010-10-22 12:50:53 +01001140 return i::Parser::PreParse(i::Handle<i::String>(), &buf, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001141}
1142
1143
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001144ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
1145 i::Handle<i::String> str = Utils::OpenHandle(*source);
Ben Murdochf87a2032010-10-22 12:50:53 +01001146 return i::Parser::PreParse(str, NULL, NULL);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001147}
1148
1149
Leon Clarkef7060e22010-06-03 12:02:55 +01001150ScriptData* ScriptData::New(const char* data, int length) {
1151 // Return an empty ScriptData if the length is obviously invalid.
1152 if (length % sizeof(unsigned) != 0) {
Iain Merrick9ac36c92010-09-13 15:29:50 +01001153 return new i::ScriptDataImpl();
Leon Clarkef7060e22010-06-03 12:02:55 +01001154 }
1155
1156 // Copy the data to ensure it is properly aligned.
1157 int deserialized_data_length = length / sizeof(unsigned);
Iain Merrick9ac36c92010-09-13 15:29:50 +01001158 // If aligned, don't create a copy of the data.
1159 if (reinterpret_cast<intptr_t>(data) % sizeof(unsigned) == 0) {
1160 return new i::ScriptDataImpl(data, length);
1161 }
1162 // Copy the data to align it.
Leon Clarkef7060e22010-06-03 12:02:55 +01001163 unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
Iain Merrick9ac36c92010-09-13 15:29:50 +01001164 i::MemCopy(deserialized_data, data, length);
Leon Clarkef7060e22010-06-03 12:02:55 +01001165
1166 return new i::ScriptDataImpl(
1167 i::Vector<unsigned>(deserialized_data, deserialized_data_length));
Steve Blocka7e24c12009-10-30 11:49:00 +00001168}
1169
1170
1171// --- S c r i p t ---
1172
1173
1174Local<Script> Script::New(v8::Handle<String> source,
1175 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001176 v8::ScriptData* pre_data,
1177 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001178 ON_BAILOUT("v8::Script::New()", return Local<Script>());
1179 LOG_API("Script::New");
1180 ENTER_V8;
1181 i::Handle<i::String> str = Utils::OpenHandle(*source);
1182 i::Handle<i::Object> name_obj;
1183 int line_offset = 0;
1184 int column_offset = 0;
1185 if (origin != NULL) {
1186 if (!origin->ResourceName().IsEmpty()) {
1187 name_obj = Utils::OpenHandle(*origin->ResourceName());
1188 }
1189 if (!origin->ResourceLineOffset().IsEmpty()) {
1190 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1191 }
1192 if (!origin->ResourceColumnOffset().IsEmpty()) {
1193 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1194 }
1195 }
1196 EXCEPTION_PREAMBLE();
Andrei Popescu402d9372010-02-26 13:31:12 +00001197 i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001198 // We assert that the pre-data is sane, even though we can actually
1199 // handle it if it turns out not to be in release mode.
Andrei Popescu402d9372010-02-26 13:31:12 +00001200 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
Steve Blocka7e24c12009-10-30 11:49:00 +00001201 // If the pre-data isn't sane we simply ignore it
Andrei Popescu402d9372010-02-26 13:31:12 +00001202 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
1203 pre_data_impl = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001204 }
Steve Block6ded16b2010-05-10 14:33:55 +01001205 i::Handle<i::SharedFunctionInfo> result =
Andrei Popescu31002712010-02-23 13:46:05 +00001206 i::Compiler::Compile(str,
1207 name_obj,
1208 line_offset,
1209 column_offset,
1210 NULL,
Andrei Popescu402d9372010-02-26 13:31:12 +00001211 pre_data_impl,
1212 Utils::OpenHandle(*script_data),
Andrei Popescu31002712010-02-23 13:46:05 +00001213 i::NOT_NATIVES_CODE);
Steve Block6ded16b2010-05-10 14:33:55 +01001214 has_pending_exception = result.is_null();
Steve Blocka7e24c12009-10-30 11:49:00 +00001215 EXCEPTION_BAILOUT_CHECK(Local<Script>());
Steve Block6ded16b2010-05-10 14:33:55 +01001216 return Local<Script>(ToApi<Script>(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00001217}
1218
1219
1220Local<Script> Script::New(v8::Handle<String> source,
1221 v8::Handle<Value> file_name) {
1222 ScriptOrigin origin(file_name);
1223 return New(source, &origin);
1224}
1225
1226
1227Local<Script> Script::Compile(v8::Handle<String> source,
1228 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001229 v8::ScriptData* pre_data,
1230 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001231 ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1232 LOG_API("Script::Compile");
1233 ENTER_V8;
Andrei Popescu402d9372010-02-26 13:31:12 +00001234 Local<Script> generic = New(source, origin, pre_data, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001235 if (generic.IsEmpty())
1236 return generic;
Steve Block6ded16b2010-05-10 14:33:55 +01001237 i::Handle<i::Object> obj = Utils::OpenHandle(*generic);
1238 i::Handle<i::SharedFunctionInfo> function =
1239 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001240 i::Handle<i::JSFunction> result =
Steve Block6ded16b2010-05-10 14:33:55 +01001241 i::Factory::NewFunctionFromSharedFunctionInfo(function,
1242 i::Top::global_context());
Steve Blocka7e24c12009-10-30 11:49:00 +00001243 return Local<Script>(ToApi<Script>(result));
1244}
1245
1246
1247Local<Script> Script::Compile(v8::Handle<String> source,
Andrei Popescu402d9372010-02-26 13:31:12 +00001248 v8::Handle<Value> file_name,
1249 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001250 ScriptOrigin origin(file_name);
Andrei Popescu402d9372010-02-26 13:31:12 +00001251 return Compile(source, &origin, 0, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001252}
1253
1254
1255Local<Value> Script::Run() {
1256 ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1257 LOG_API("Script::Run");
1258 ENTER_V8;
1259 i::Object* raw_result = NULL;
1260 {
1261 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001262 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1263 i::Handle<i::JSFunction> fun;
1264 if (obj->IsSharedFunctionInfo()) {
1265 i::Handle<i::SharedFunctionInfo>
1266 function_info(i::SharedFunctionInfo::cast(*obj));
1267 fun = i::Factory::NewFunctionFromSharedFunctionInfo(
1268 function_info, i::Top::global_context());
1269 } else {
1270 fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001271 }
1272 EXCEPTION_PREAMBLE();
1273 i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
1274 i::Handle<i::Object> result =
1275 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
1276 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1277 raw_result = *result;
1278 }
1279 i::Handle<i::Object> result(raw_result);
1280 return Utils::ToLocal(result);
1281}
1282
1283
Steve Block6ded16b2010-05-10 14:33:55 +01001284static i::Handle<i::SharedFunctionInfo> OpenScript(Script* script) {
1285 i::Handle<i::Object> obj = Utils::OpenHandle(script);
1286 i::Handle<i::SharedFunctionInfo> result;
1287 if (obj->IsSharedFunctionInfo()) {
1288 result =
1289 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
1290 } else {
1291 result =
1292 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared());
1293 }
1294 return result;
1295}
1296
1297
Steve Blocka7e24c12009-10-30 11:49:00 +00001298Local<Value> Script::Id() {
1299 ON_BAILOUT("v8::Script::Id()", return Local<Value>());
1300 LOG_API("Script::Id");
1301 i::Object* raw_id = NULL;
1302 {
1303 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001304 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1305 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001306 i::Handle<i::Object> id(script->id());
1307 raw_id = *id;
1308 }
1309 i::Handle<i::Object> id(raw_id);
1310 return Utils::ToLocal(id);
1311}
1312
1313
Steve Blockd0582a62009-12-15 09:54:21 +00001314void Script::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001315 ON_BAILOUT("v8::Script::SetData()", return);
1316 LOG_API("Script::SetData");
1317 {
1318 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001319 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001320 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
Steve Block6ded16b2010-05-10 14:33:55 +01001321 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001322 script->set_data(*raw_data);
1323 }
1324}
1325
1326
1327// --- E x c e p t i o n s ---
1328
1329
1330v8::TryCatch::TryCatch()
Steve Blockd0582a62009-12-15 09:54:21 +00001331 : next_(i::Top::try_catch_handler_address()),
Steve Blocka7e24c12009-10-30 11:49:00 +00001332 exception_(i::Heap::the_hole_value()),
1333 message_(i::Smi::FromInt(0)),
1334 is_verbose_(false),
1335 can_continue_(true),
1336 capture_message_(true),
Steve Blockd0582a62009-12-15 09:54:21 +00001337 rethrow_(false) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001338 i::Top::RegisterTryCatchHandler(this);
1339}
1340
1341
1342v8::TryCatch::~TryCatch() {
Steve Blockd0582a62009-12-15 09:54:21 +00001343 if (rethrow_) {
1344 v8::HandleScope scope;
1345 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
1346 i::Top::UnregisterTryCatchHandler(this);
1347 v8::ThrowException(exc);
1348 } else {
1349 i::Top::UnregisterTryCatchHandler(this);
1350 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001351}
1352
1353
1354bool v8::TryCatch::HasCaught() const {
1355 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1356}
1357
1358
1359bool v8::TryCatch::CanContinue() const {
1360 return can_continue_;
1361}
1362
1363
Steve Blockd0582a62009-12-15 09:54:21 +00001364v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1365 if (!HasCaught()) return v8::Local<v8::Value>();
1366 rethrow_ = true;
1367 return v8::Undefined();
1368}
1369
1370
Steve Blocka7e24c12009-10-30 11:49:00 +00001371v8::Local<Value> v8::TryCatch::Exception() const {
1372 if (HasCaught()) {
1373 // Check for out of memory exception.
1374 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1375 return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1376 } else {
1377 return v8::Local<Value>();
1378 }
1379}
1380
1381
1382v8::Local<Value> v8::TryCatch::StackTrace() const {
1383 if (HasCaught()) {
1384 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1385 if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1386 v8::HandleScope scope;
1387 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
1388 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
1389 if (!obj->HasProperty(*name))
1390 return v8::Local<Value>();
1391 return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
1392 } else {
1393 return v8::Local<Value>();
1394 }
1395}
1396
1397
1398v8::Local<v8::Message> v8::TryCatch::Message() const {
1399 if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1400 i::Object* message = reinterpret_cast<i::Object*>(message_);
1401 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1402 } else {
1403 return v8::Local<v8::Message>();
1404 }
1405}
1406
1407
1408void v8::TryCatch::Reset() {
1409 exception_ = i::Heap::the_hole_value();
1410 message_ = i::Smi::FromInt(0);
1411}
1412
1413
1414void v8::TryCatch::SetVerbose(bool value) {
1415 is_verbose_ = value;
1416}
1417
1418
1419void v8::TryCatch::SetCaptureMessage(bool value) {
1420 capture_message_ = value;
1421}
1422
1423
1424// --- M e s s a g e ---
1425
1426
1427Local<String> Message::Get() const {
1428 ON_BAILOUT("v8::Message::Get()", return Local<String>());
1429 ENTER_V8;
1430 HandleScope scope;
1431 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1432 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1433 Local<String> result = Utils::ToLocal(raw_result);
1434 return scope.Close(result);
1435}
1436
1437
1438v8::Handle<Value> Message::GetScriptResourceName() const {
1439 if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1440 return Local<String>();
1441 }
1442 ENTER_V8;
1443 HandleScope scope;
1444 i::Handle<i::JSObject> obj =
1445 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1446 // Return this.script.name.
1447 i::Handle<i::JSValue> script =
1448 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1449 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
1450 return scope.Close(Utils::ToLocal(resource_name));
1451}
1452
1453
1454v8::Handle<Value> Message::GetScriptData() const {
1455 if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
1456 return Local<Value>();
1457 }
1458 ENTER_V8;
1459 HandleScope scope;
1460 i::Handle<i::JSObject> obj =
1461 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1462 // Return this.script.data.
1463 i::Handle<i::JSValue> script =
1464 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1465 i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1466 return scope.Close(Utils::ToLocal(data));
1467}
1468
1469
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001470v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
1471 if (IsDeadCheck("v8::Message::GetStackTrace()")) {
1472 return Local<v8::StackTrace>();
1473 }
1474 ENTER_V8;
1475 HandleScope scope;
1476 i::Handle<i::JSObject> obj =
1477 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1478 i::Handle<i::Object> stackFramesObj = GetProperty(obj, "stackFrames");
1479 if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
1480 i::Handle<i::JSArray> stackTrace =
1481 i::Handle<i::JSArray>::cast(stackFramesObj);
1482 return scope.Close(Utils::StackTraceToLocal(stackTrace));
1483}
1484
1485
Steve Blocka7e24c12009-10-30 11:49:00 +00001486static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1487 i::Handle<i::Object> recv,
1488 int argc,
1489 i::Object** argv[],
1490 bool* has_pending_exception) {
1491 i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
1492 i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
1493 i::Handle<i::JSFunction> fun =
1494 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1495 i::Handle<i::Object> value =
1496 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1497 return value;
1498}
1499
1500
1501static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1502 i::Handle<i::Object> data,
1503 bool* has_pending_exception) {
1504 i::Object** argv[1] = { data.location() };
1505 return CallV8HeapFunction(name,
1506 i::Top::builtins(),
1507 1,
1508 argv,
1509 has_pending_exception);
1510}
1511
1512
1513int Message::GetLineNumber() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001514 ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001515 ENTER_V8;
1516 HandleScope scope;
1517 EXCEPTION_PREAMBLE();
1518 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1519 Utils::OpenHandle(this),
1520 &has_pending_exception);
1521 EXCEPTION_BAILOUT_CHECK(0);
1522 return static_cast<int>(result->Number());
1523}
1524
1525
1526int Message::GetStartPosition() const {
1527 if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1528 ENTER_V8;
1529 HandleScope scope;
1530
1531 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1532 return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1533}
1534
1535
1536int Message::GetEndPosition() const {
1537 if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1538 ENTER_V8;
1539 HandleScope scope;
1540 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1541 return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1542}
1543
1544
1545int Message::GetStartColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001546 if (IsDeadCheck("v8::Message::GetStartColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001547 ENTER_V8;
1548 HandleScope scope;
1549 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1550 EXCEPTION_PREAMBLE();
1551 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1552 "GetPositionInLine",
1553 data_obj,
1554 &has_pending_exception);
1555 EXCEPTION_BAILOUT_CHECK(0);
1556 return static_cast<int>(start_col_obj->Number());
1557}
1558
1559
1560int Message::GetEndColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001561 if (IsDeadCheck("v8::Message::GetEndColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001562 ENTER_V8;
1563 HandleScope scope;
1564 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1565 EXCEPTION_PREAMBLE();
1566 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1567 "GetPositionInLine",
1568 data_obj,
1569 &has_pending_exception);
1570 EXCEPTION_BAILOUT_CHECK(0);
1571 int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1572 int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1573 return static_cast<int>(start_col_obj->Number()) + (end - start);
1574}
1575
1576
1577Local<String> Message::GetSourceLine() const {
1578 ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
1579 ENTER_V8;
1580 HandleScope scope;
1581 EXCEPTION_PREAMBLE();
1582 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1583 Utils::OpenHandle(this),
1584 &has_pending_exception);
1585 EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1586 if (result->IsString()) {
1587 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1588 } else {
1589 return Local<String>();
1590 }
1591}
1592
1593
1594void Message::PrintCurrentStackTrace(FILE* out) {
1595 if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1596 ENTER_V8;
1597 i::Top::PrintCurrentStackTrace(out);
1598}
1599
1600
Kristian Monsen25f61362010-05-21 11:50:48 +01001601// --- S t a c k T r a c e ---
1602
1603Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
1604 if (IsDeadCheck("v8::StackTrace::GetFrame()")) return Local<StackFrame>();
1605 ENTER_V8;
1606 HandleScope scope;
1607 i::Handle<i::JSArray> self = Utils::OpenHandle(this);
1608 i::Handle<i::JSObject> obj(i::JSObject::cast(self->GetElement(index)));
1609 return scope.Close(Utils::StackFrameToLocal(obj));
1610}
1611
1612
1613int StackTrace::GetFrameCount() const {
1614 if (IsDeadCheck("v8::StackTrace::GetFrameCount()")) return -1;
1615 ENTER_V8;
1616 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
1617}
1618
1619
1620Local<Array> StackTrace::AsArray() {
1621 if (IsDeadCheck("v8::StackTrace::AsArray()")) Local<Array>();
1622 ENTER_V8;
1623 return Utils::ToLocal(Utils::OpenHandle(this));
1624}
1625
1626
1627Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
1628 StackTraceOptions options) {
1629 if (IsDeadCheck("v8::StackTrace::CurrentStackTrace()")) Local<StackTrace>();
1630 ENTER_V8;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001631 i::Handle<i::JSArray> stackTrace =
1632 i::Top::CaptureCurrentStackTrace(frame_limit, options);
1633 return Utils::StackTraceToLocal(stackTrace);
Kristian Monsen25f61362010-05-21 11:50:48 +01001634}
1635
1636
1637// --- S t a c k F r a m e ---
1638
1639int StackFrame::GetLineNumber() const {
1640 if (IsDeadCheck("v8::StackFrame::GetLineNumber()")) {
1641 return Message::kNoLineNumberInfo;
1642 }
1643 ENTER_V8;
1644 i::HandleScope scope;
1645 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1646 i::Handle<i::Object> line = GetProperty(self, "lineNumber");
1647 if (!line->IsSmi()) {
1648 return Message::kNoLineNumberInfo;
1649 }
1650 return i::Smi::cast(*line)->value();
1651}
1652
1653
1654int StackFrame::GetColumn() const {
1655 if (IsDeadCheck("v8::StackFrame::GetColumn()")) {
1656 return Message::kNoColumnInfo;
1657 }
1658 ENTER_V8;
1659 i::HandleScope scope;
1660 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1661 i::Handle<i::Object> column = GetProperty(self, "column");
1662 if (!column->IsSmi()) {
1663 return Message::kNoColumnInfo;
1664 }
1665 return i::Smi::cast(*column)->value();
1666}
1667
1668
1669Local<String> StackFrame::GetScriptName() const {
1670 if (IsDeadCheck("v8::StackFrame::GetScriptName()")) return Local<String>();
1671 ENTER_V8;
1672 HandleScope scope;
1673 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1674 i::Handle<i::Object> name = GetProperty(self, "scriptName");
1675 if (!name->IsString()) {
1676 return Local<String>();
1677 }
1678 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1679}
1680
1681
Ben Murdochf87a2032010-10-22 12:50:53 +01001682Local<String> StackFrame::GetScriptNameOrSourceURL() const {
1683 if (IsDeadCheck("v8::StackFrame::GetScriptNameOrSourceURL()")) {
1684 return Local<String>();
1685 }
1686 ENTER_V8;
1687 HandleScope scope;
1688 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1689 i::Handle<i::Object> name = GetProperty(self, "scriptNameOrSourceURL");
1690 if (!name->IsString()) {
1691 return Local<String>();
1692 }
1693 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1694}
1695
1696
Kristian Monsen25f61362010-05-21 11:50:48 +01001697Local<String> StackFrame::GetFunctionName() const {
1698 if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
1699 ENTER_V8;
1700 HandleScope scope;
1701 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1702 i::Handle<i::Object> name = GetProperty(self, "functionName");
1703 if (!name->IsString()) {
1704 return Local<String>();
1705 }
1706 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1707}
1708
1709
1710bool StackFrame::IsEval() const {
1711 if (IsDeadCheck("v8::StackFrame::IsEval()")) return false;
1712 ENTER_V8;
1713 i::HandleScope scope;
1714 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1715 i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
1716 return is_eval->IsTrue();
1717}
1718
1719
1720bool StackFrame::IsConstructor() const {
1721 if (IsDeadCheck("v8::StackFrame::IsConstructor()")) return false;
1722 ENTER_V8;
1723 i::HandleScope scope;
1724 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1725 i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
1726 return is_constructor->IsTrue();
1727}
1728
1729
Steve Blocka7e24c12009-10-30 11:49:00 +00001730// --- D a t a ---
1731
1732bool Value::IsUndefined() const {
1733 if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1734 return Utils::OpenHandle(this)->IsUndefined();
1735}
1736
1737
1738bool Value::IsNull() const {
1739 if (IsDeadCheck("v8::Value::IsNull()")) return false;
1740 return Utils::OpenHandle(this)->IsNull();
1741}
1742
1743
1744bool Value::IsTrue() const {
1745 if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1746 return Utils::OpenHandle(this)->IsTrue();
1747}
1748
1749
1750bool Value::IsFalse() const {
1751 if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1752 return Utils::OpenHandle(this)->IsFalse();
1753}
1754
1755
1756bool Value::IsFunction() const {
1757 if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1758 return Utils::OpenHandle(this)->IsJSFunction();
1759}
1760
1761
1762bool Value::FullIsString() const {
1763 if (IsDeadCheck("v8::Value::IsString()")) return false;
1764 bool result = Utils::OpenHandle(this)->IsString();
1765 ASSERT_EQ(result, QuickIsString());
1766 return result;
1767}
1768
1769
1770bool Value::IsArray() const {
1771 if (IsDeadCheck("v8::Value::IsArray()")) return false;
1772 return Utils::OpenHandle(this)->IsJSArray();
1773}
1774
1775
1776bool Value::IsObject() const {
1777 if (IsDeadCheck("v8::Value::IsObject()")) return false;
1778 return Utils::OpenHandle(this)->IsJSObject();
1779}
1780
1781
1782bool Value::IsNumber() const {
1783 if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1784 return Utils::OpenHandle(this)->IsNumber();
1785}
1786
1787
1788bool Value::IsBoolean() const {
1789 if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1790 return Utils::OpenHandle(this)->IsBoolean();
1791}
1792
1793
1794bool Value::IsExternal() const {
1795 if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1796 return Utils::OpenHandle(this)->IsProxy();
1797}
1798
1799
1800bool Value::IsInt32() const {
1801 if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1802 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1803 if (obj->IsSmi()) return true;
1804 if (obj->IsNumber()) {
1805 double value = obj->Number();
1806 return i::FastI2D(i::FastD2I(value)) == value;
1807 }
1808 return false;
1809}
1810
1811
Steve Block6ded16b2010-05-10 14:33:55 +01001812bool Value::IsUint32() const {
1813 if (IsDeadCheck("v8::Value::IsUint32()")) return false;
1814 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1815 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
1816 if (obj->IsNumber()) {
1817 double value = obj->Number();
1818 return i::FastUI2D(i::FastD2UI(value)) == value;
1819 }
1820 return false;
1821}
1822
1823
Steve Blocka7e24c12009-10-30 11:49:00 +00001824bool Value::IsDate() const {
1825 if (IsDeadCheck("v8::Value::IsDate()")) return false;
1826 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1827 return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1828}
1829
1830
Iain Merrick75681382010-08-19 15:07:18 +01001831bool Value::IsRegExp() const {
1832 if (IsDeadCheck("v8::Value::IsRegExp()")) return false;
1833 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1834 return obj->IsJSRegExp();
1835}
1836
1837
Steve Blocka7e24c12009-10-30 11:49:00 +00001838Local<String> Value::ToString() const {
1839 if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1840 LOG_API("ToString");
1841 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1842 i::Handle<i::Object> str;
1843 if (obj->IsString()) {
1844 str = obj;
1845 } else {
1846 ENTER_V8;
1847 EXCEPTION_PREAMBLE();
1848 str = i::Execution::ToString(obj, &has_pending_exception);
1849 EXCEPTION_BAILOUT_CHECK(Local<String>());
1850 }
1851 return Local<String>(ToApi<String>(str));
1852}
1853
1854
1855Local<String> Value::ToDetailString() const {
1856 if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1857 LOG_API("ToDetailString");
1858 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1859 i::Handle<i::Object> str;
1860 if (obj->IsString()) {
1861 str = obj;
1862 } else {
1863 ENTER_V8;
1864 EXCEPTION_PREAMBLE();
1865 str = i::Execution::ToDetailString(obj, &has_pending_exception);
1866 EXCEPTION_BAILOUT_CHECK(Local<String>());
1867 }
1868 return Local<String>(ToApi<String>(str));
1869}
1870
1871
1872Local<v8::Object> Value::ToObject() const {
1873 if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1874 LOG_API("ToObject");
1875 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1876 i::Handle<i::Object> val;
1877 if (obj->IsJSObject()) {
1878 val = obj;
1879 } else {
1880 ENTER_V8;
1881 EXCEPTION_PREAMBLE();
1882 val = i::Execution::ToObject(obj, &has_pending_exception);
1883 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1884 }
1885 return Local<v8::Object>(ToApi<Object>(val));
1886}
1887
1888
1889Local<Boolean> Value::ToBoolean() const {
1890 if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1891 LOG_API("ToBoolean");
1892 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1893 if (obj->IsBoolean()) {
1894 return Local<Boolean>(ToApi<Boolean>(obj));
1895 } else {
1896 ENTER_V8;
1897 i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1898 return Local<Boolean>(ToApi<Boolean>(val));
1899 }
1900}
1901
1902
1903Local<Number> Value::ToNumber() const {
1904 if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1905 LOG_API("ToNumber");
1906 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1907 i::Handle<i::Object> num;
1908 if (obj->IsNumber()) {
1909 num = obj;
1910 } else {
1911 ENTER_V8;
1912 EXCEPTION_PREAMBLE();
1913 num = i::Execution::ToNumber(obj, &has_pending_exception);
1914 EXCEPTION_BAILOUT_CHECK(Local<Number>());
1915 }
1916 return Local<Number>(ToApi<Number>(num));
1917}
1918
1919
1920Local<Integer> Value::ToInteger() const {
1921 if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1922 LOG_API("ToInteger");
1923 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1924 i::Handle<i::Object> num;
1925 if (obj->IsSmi()) {
1926 num = obj;
1927 } else {
1928 ENTER_V8;
1929 EXCEPTION_PREAMBLE();
1930 num = i::Execution::ToInteger(obj, &has_pending_exception);
1931 EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1932 }
1933 return Local<Integer>(ToApi<Integer>(num));
1934}
1935
1936
1937void External::CheckCast(v8::Value* that) {
1938 if (IsDeadCheck("v8::External::Cast()")) return;
1939 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1940 ApiCheck(obj->IsProxy(),
1941 "v8::External::Cast()",
1942 "Could not convert to external");
1943}
1944
1945
1946void v8::Object::CheckCast(Value* that) {
1947 if (IsDeadCheck("v8::Object::Cast()")) return;
1948 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1949 ApiCheck(obj->IsJSObject(),
1950 "v8::Object::Cast()",
1951 "Could not convert to object");
1952}
1953
1954
1955void v8::Function::CheckCast(Value* that) {
1956 if (IsDeadCheck("v8::Function::Cast()")) return;
1957 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1958 ApiCheck(obj->IsJSFunction(),
1959 "v8::Function::Cast()",
1960 "Could not convert to function");
1961}
1962
1963
1964void v8::String::CheckCast(v8::Value* that) {
1965 if (IsDeadCheck("v8::String::Cast()")) return;
1966 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1967 ApiCheck(obj->IsString(),
1968 "v8::String::Cast()",
1969 "Could not convert to string");
1970}
1971
1972
1973void v8::Number::CheckCast(v8::Value* that) {
1974 if (IsDeadCheck("v8::Number::Cast()")) return;
1975 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1976 ApiCheck(obj->IsNumber(),
1977 "v8::Number::Cast()",
1978 "Could not convert to number");
1979}
1980
1981
1982void v8::Integer::CheckCast(v8::Value* that) {
1983 if (IsDeadCheck("v8::Integer::Cast()")) return;
1984 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1985 ApiCheck(obj->IsNumber(),
1986 "v8::Integer::Cast()",
1987 "Could not convert to number");
1988}
1989
1990
1991void v8::Array::CheckCast(Value* that) {
1992 if (IsDeadCheck("v8::Array::Cast()")) return;
1993 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1994 ApiCheck(obj->IsJSArray(),
1995 "v8::Array::Cast()",
1996 "Could not convert to array");
1997}
1998
1999
2000void v8::Date::CheckCast(v8::Value* that) {
2001 if (IsDeadCheck("v8::Date::Cast()")) return;
2002 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2003 ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
2004 "v8::Date::Cast()",
2005 "Could not convert to date");
2006}
2007
2008
Ben Murdochf87a2032010-10-22 12:50:53 +01002009void v8::RegExp::CheckCast(v8::Value* that) {
2010 if (IsDeadCheck("v8::RegExp::Cast()")) return;
2011 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2012 ApiCheck(obj->IsJSRegExp(),
2013 "v8::RegExp::Cast()",
2014 "Could not convert to regular expression");
2015}
2016
2017
Steve Blocka7e24c12009-10-30 11:49:00 +00002018bool Value::BooleanValue() const {
2019 if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
2020 LOG_API("BooleanValue");
2021 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2022 if (obj->IsBoolean()) {
2023 return obj->IsTrue();
2024 } else {
2025 ENTER_V8;
2026 i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
2027 return value->IsTrue();
2028 }
2029}
2030
2031
2032double Value::NumberValue() const {
2033 if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
2034 LOG_API("NumberValue");
2035 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2036 i::Handle<i::Object> num;
2037 if (obj->IsNumber()) {
2038 num = obj;
2039 } else {
2040 ENTER_V8;
2041 EXCEPTION_PREAMBLE();
2042 num = i::Execution::ToNumber(obj, &has_pending_exception);
2043 EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
2044 }
2045 return num->Number();
2046}
2047
2048
2049int64_t Value::IntegerValue() const {
2050 if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
2051 LOG_API("IntegerValue");
2052 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2053 i::Handle<i::Object> num;
2054 if (obj->IsNumber()) {
2055 num = obj;
2056 } else {
2057 ENTER_V8;
2058 EXCEPTION_PREAMBLE();
2059 num = i::Execution::ToInteger(obj, &has_pending_exception);
2060 EXCEPTION_BAILOUT_CHECK(0);
2061 }
2062 if (num->IsSmi()) {
2063 return i::Smi::cast(*num)->value();
2064 } else {
2065 return static_cast<int64_t>(num->Number());
2066 }
2067}
2068
2069
2070Local<Int32> Value::ToInt32() const {
2071 if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
2072 LOG_API("ToInt32");
2073 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2074 i::Handle<i::Object> num;
2075 if (obj->IsSmi()) {
2076 num = obj;
2077 } else {
2078 ENTER_V8;
2079 EXCEPTION_PREAMBLE();
2080 num = i::Execution::ToInt32(obj, &has_pending_exception);
2081 EXCEPTION_BAILOUT_CHECK(Local<Int32>());
2082 }
2083 return Local<Int32>(ToApi<Int32>(num));
2084}
2085
2086
2087Local<Uint32> Value::ToUint32() const {
2088 if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
2089 LOG_API("ToUInt32");
2090 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2091 i::Handle<i::Object> num;
2092 if (obj->IsSmi()) {
2093 num = obj;
2094 } else {
2095 ENTER_V8;
2096 EXCEPTION_PREAMBLE();
2097 num = i::Execution::ToUint32(obj, &has_pending_exception);
2098 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2099 }
2100 return Local<Uint32>(ToApi<Uint32>(num));
2101}
2102
2103
2104Local<Uint32> Value::ToArrayIndex() const {
2105 if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
2106 LOG_API("ToArrayIndex");
2107 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2108 if (obj->IsSmi()) {
2109 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2110 return Local<Uint32>();
2111 }
2112 ENTER_V8;
2113 EXCEPTION_PREAMBLE();
2114 i::Handle<i::Object> string_obj =
2115 i::Execution::ToString(obj, &has_pending_exception);
2116 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2117 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2118 uint32_t index;
2119 if (str->AsArrayIndex(&index)) {
2120 i::Handle<i::Object> value;
2121 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2122 value = i::Handle<i::Object>(i::Smi::FromInt(index));
2123 } else {
2124 value = i::Factory::NewNumber(index);
2125 }
2126 return Utils::Uint32ToLocal(value);
2127 }
2128 return Local<Uint32>();
2129}
2130
2131
2132int32_t Value::Int32Value() const {
2133 if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
2134 LOG_API("Int32Value");
2135 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2136 if (obj->IsSmi()) {
2137 return i::Smi::cast(*obj)->value();
2138 } else {
2139 LOG_API("Int32Value (slow)");
2140 ENTER_V8;
2141 EXCEPTION_PREAMBLE();
2142 i::Handle<i::Object> num =
2143 i::Execution::ToInt32(obj, &has_pending_exception);
2144 EXCEPTION_BAILOUT_CHECK(0);
2145 if (num->IsSmi()) {
2146 return i::Smi::cast(*num)->value();
2147 } else {
2148 return static_cast<int32_t>(num->Number());
2149 }
2150 }
2151}
2152
2153
2154bool Value::Equals(Handle<Value> that) const {
2155 if (IsDeadCheck("v8::Value::Equals()")
2156 || EmptyCheck("v8::Value::Equals()", this)
2157 || EmptyCheck("v8::Value::Equals()", that)) {
2158 return false;
2159 }
2160 LOG_API("Equals");
2161 ENTER_V8;
2162 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2163 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2164 i::Object** args[1] = { other.location() };
2165 EXCEPTION_PREAMBLE();
2166 i::Handle<i::Object> result =
2167 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
2168 EXCEPTION_BAILOUT_CHECK(false);
2169 return *result == i::Smi::FromInt(i::EQUAL);
2170}
2171
2172
2173bool Value::StrictEquals(Handle<Value> that) const {
2174 if (IsDeadCheck("v8::Value::StrictEquals()")
2175 || EmptyCheck("v8::Value::StrictEquals()", this)
2176 || EmptyCheck("v8::Value::StrictEquals()", that)) {
2177 return false;
2178 }
2179 LOG_API("StrictEquals");
2180 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2181 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2182 // Must check HeapNumber first, since NaN !== NaN.
2183 if (obj->IsHeapNumber()) {
2184 if (!other->IsNumber()) return false;
2185 double x = obj->Number();
2186 double y = other->Number();
2187 // Must check explicitly for NaN:s on Windows, but -0 works fine.
2188 return x == y && !isnan(x) && !isnan(y);
2189 } else if (*obj == *other) { // Also covers Booleans.
2190 return true;
2191 } else if (obj->IsSmi()) {
2192 return other->IsNumber() && obj->Number() == other->Number();
2193 } else if (obj->IsString()) {
2194 return other->IsString() &&
2195 i::String::cast(*obj)->Equals(i::String::cast(*other));
2196 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2197 return other->IsUndefined() || other->IsUndetectableObject();
2198 } else {
2199 return false;
2200 }
2201}
2202
2203
2204uint32_t Value::Uint32Value() const {
2205 if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
2206 LOG_API("Uint32Value");
2207 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2208 if (obj->IsSmi()) {
2209 return i::Smi::cast(*obj)->value();
2210 } else {
2211 ENTER_V8;
2212 EXCEPTION_PREAMBLE();
2213 i::Handle<i::Object> num =
2214 i::Execution::ToUint32(obj, &has_pending_exception);
2215 EXCEPTION_BAILOUT_CHECK(0);
2216 if (num->IsSmi()) {
2217 return i::Smi::cast(*num)->value();
2218 } else {
2219 return static_cast<uint32_t>(num->Number());
2220 }
2221 }
2222}
2223
2224
2225bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
2226 v8::PropertyAttribute attribs) {
2227 ON_BAILOUT("v8::Object::Set()", return false);
2228 ENTER_V8;
2229 HandleScope scope;
2230 i::Handle<i::Object> self = Utils::OpenHandle(this);
2231 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2232 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2233 EXCEPTION_PREAMBLE();
2234 i::Handle<i::Object> obj = i::SetProperty(
2235 self,
2236 key_obj,
2237 value_obj,
2238 static_cast<PropertyAttributes>(attribs));
2239 has_pending_exception = obj.is_null();
2240 EXCEPTION_BAILOUT_CHECK(false);
2241 return true;
2242}
2243
2244
Steve Block6ded16b2010-05-10 14:33:55 +01002245bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
2246 ON_BAILOUT("v8::Object::Set()", return false);
2247 ENTER_V8;
2248 HandleScope scope;
2249 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2250 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2251 EXCEPTION_PREAMBLE();
2252 i::Handle<i::Object> obj = i::SetElement(
2253 self,
2254 index,
2255 value_obj);
2256 has_pending_exception = obj.is_null();
2257 EXCEPTION_BAILOUT_CHECK(false);
2258 return true;
2259}
2260
2261
Steve Blocka7e24c12009-10-30 11:49:00 +00002262bool v8::Object::ForceSet(v8::Handle<Value> key,
2263 v8::Handle<Value> value,
2264 v8::PropertyAttribute attribs) {
2265 ON_BAILOUT("v8::Object::ForceSet()", return false);
2266 ENTER_V8;
2267 HandleScope scope;
2268 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2269 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2270 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2271 EXCEPTION_PREAMBLE();
2272 i::Handle<i::Object> obj = i::ForceSetProperty(
2273 self,
2274 key_obj,
2275 value_obj,
2276 static_cast<PropertyAttributes>(attribs));
2277 has_pending_exception = obj.is_null();
2278 EXCEPTION_BAILOUT_CHECK(false);
2279 return true;
2280}
2281
2282
2283bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2284 ON_BAILOUT("v8::Object::ForceDelete()", return false);
2285 ENTER_V8;
2286 HandleScope scope;
2287 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2288 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2289 EXCEPTION_PREAMBLE();
2290 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2291 has_pending_exception = obj.is_null();
2292 EXCEPTION_BAILOUT_CHECK(false);
2293 return obj->IsTrue();
2294}
2295
2296
2297Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2298 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2299 ENTER_V8;
2300 i::Handle<i::Object> self = Utils::OpenHandle(this);
2301 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2302 EXCEPTION_PREAMBLE();
2303 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2304 has_pending_exception = result.is_null();
2305 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2306 return Utils::ToLocal(result);
2307}
2308
2309
Steve Block6ded16b2010-05-10 14:33:55 +01002310Local<Value> v8::Object::Get(uint32_t index) {
2311 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2312 ENTER_V8;
2313 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2314 EXCEPTION_PREAMBLE();
2315 i::Handle<i::Object> result = i::GetElement(self, index);
2316 has_pending_exception = result.is_null();
2317 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2318 return Utils::ToLocal(result);
2319}
2320
2321
Steve Blocka7e24c12009-10-30 11:49:00 +00002322Local<Value> v8::Object::GetPrototype() {
2323 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
2324 ENTER_V8;
2325 i::Handle<i::Object> self = Utils::OpenHandle(this);
2326 i::Handle<i::Object> result = i::GetPrototype(self);
2327 return Utils::ToLocal(result);
2328}
2329
2330
Andrei Popescu402d9372010-02-26 13:31:12 +00002331bool v8::Object::SetPrototype(Handle<Value> value) {
2332 ON_BAILOUT("v8::Object::SetPrototype()", return false);
2333 ENTER_V8;
2334 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2335 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2336 EXCEPTION_PREAMBLE();
2337 i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2338 has_pending_exception = result.is_null();
2339 EXCEPTION_BAILOUT_CHECK(false);
2340 return true;
2341}
2342
2343
Steve Blocka7e24c12009-10-30 11:49:00 +00002344Local<Object> v8::Object::FindInstanceInPrototypeChain(
2345 v8::Handle<FunctionTemplate> tmpl) {
2346 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
2347 return Local<v8::Object>());
2348 ENTER_V8;
2349 i::JSObject* object = *Utils::OpenHandle(this);
2350 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2351 while (!object->IsInstanceOf(tmpl_info)) {
2352 i::Object* prototype = object->GetPrototype();
2353 if (!prototype->IsJSObject()) return Local<Object>();
2354 object = i::JSObject::cast(prototype);
2355 }
2356 return Utils::ToLocal(i::Handle<i::JSObject>(object));
2357}
2358
2359
2360Local<Array> v8::Object::GetPropertyNames() {
2361 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
2362 ENTER_V8;
2363 v8::HandleScope scope;
2364 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2365 i::Handle<i::FixedArray> value =
2366 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2367 // Because we use caching to speed up enumeration it is important
2368 // to never change the result of the basic enumeration function so
2369 // we clone the result.
2370 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
2371 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
2372 return scope.Close(Utils::ToLocal(result));
2373}
2374
2375
2376Local<String> v8::Object::ObjectProtoToString() {
2377 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2378 ENTER_V8;
2379 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2380
2381 i::Handle<i::Object> name(self->class_name());
2382
2383 // Native implementation of Object.prototype.toString (v8natives.js):
2384 // var c = %ClassOf(this);
2385 // if (c === 'Arguments') c = 'Object';
2386 // return "[object " + c + "]";
2387
2388 if (!name->IsString()) {
2389 return v8::String::New("[object ]");
2390
2391 } else {
2392 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2393 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2394 return v8::String::New("[object Object]");
2395
2396 } else {
2397 const char* prefix = "[object ";
2398 Local<String> str = Utils::ToLocal(class_name);
2399 const char* postfix = "]";
2400
Steve Blockd0582a62009-12-15 09:54:21 +00002401 int prefix_len = i::StrLength(prefix);
2402 int str_len = str->Length();
2403 int postfix_len = i::StrLength(postfix);
Steve Blocka7e24c12009-10-30 11:49:00 +00002404
Steve Blockd0582a62009-12-15 09:54:21 +00002405 int buf_len = prefix_len + str_len + postfix_len;
Kristian Monsen25f61362010-05-21 11:50:48 +01002406 i::ScopedVector<char> buf(buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002407
2408 // Write prefix.
Kristian Monsen25f61362010-05-21 11:50:48 +01002409 char* ptr = buf.start();
Steve Blocka7e24c12009-10-30 11:49:00 +00002410 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2411 ptr += prefix_len;
2412
2413 // Write real content.
2414 str->WriteAscii(ptr, 0, str_len);
2415 ptr += str_len;
2416
2417 // Write postfix.
2418 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2419
2420 // Copy the buffer into a heap-allocated string and return it.
Kristian Monsen25f61362010-05-21 11:50:48 +01002421 Local<String> result = v8::String::New(buf.start(), buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002422 return result;
2423 }
2424 }
2425}
2426
2427
2428bool v8::Object::Delete(v8::Handle<String> key) {
2429 ON_BAILOUT("v8::Object::Delete()", return false);
2430 ENTER_V8;
2431 HandleScope scope;
2432 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2433 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2434 return i::DeleteProperty(self, key_obj)->IsTrue();
2435}
2436
2437
2438bool v8::Object::Has(v8::Handle<String> key) {
2439 ON_BAILOUT("v8::Object::Has()", return false);
2440 ENTER_V8;
2441 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2442 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2443 return self->HasProperty(*key_obj);
2444}
2445
2446
2447bool v8::Object::Delete(uint32_t index) {
2448 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2449 ENTER_V8;
2450 HandleScope scope;
2451 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2452 return i::DeleteElement(self, index)->IsTrue();
2453}
2454
2455
2456bool v8::Object::Has(uint32_t index) {
2457 ON_BAILOUT("v8::Object::HasProperty()", return false);
2458 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2459 return self->HasElement(index);
2460}
2461
2462
Leon Clarkef7060e22010-06-03 12:02:55 +01002463bool Object::SetAccessor(Handle<String> name,
2464 AccessorGetter getter,
2465 AccessorSetter setter,
2466 v8::Handle<Value> data,
2467 AccessControl settings,
2468 PropertyAttribute attributes) {
2469 ON_BAILOUT("v8::Object::SetAccessor()", return false);
2470 ENTER_V8;
2471 HandleScope scope;
2472 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name,
2473 getter, setter, data,
2474 settings, attributes);
2475 i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info);
2476 return !result.is_null() && !result->IsUndefined();
2477}
2478
2479
Steve Blocka7e24c12009-10-30 11:49:00 +00002480bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2481 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2482 return Utils::OpenHandle(this)->HasRealNamedProperty(
2483 *Utils::OpenHandle(*key));
2484}
2485
2486
2487bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2488 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2489 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2490}
2491
2492
2493bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2494 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2495 ENTER_V8;
2496 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2497 *Utils::OpenHandle(*key));
2498}
2499
2500
2501bool v8::Object::HasNamedLookupInterceptor() {
2502 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2503 return Utils::OpenHandle(this)->HasNamedInterceptor();
2504}
2505
2506
2507bool v8::Object::HasIndexedLookupInterceptor() {
2508 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2509 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2510}
2511
2512
2513Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2514 Handle<String> key) {
2515 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2516 return Local<Value>());
2517 ENTER_V8;
2518 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2519 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2520 i::LookupResult lookup;
2521 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002522 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002523 PropertyAttributes attributes;
2524 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2525 &lookup,
2526 *key_obj,
2527 &attributes));
2528 return Utils::ToLocal(result);
2529 }
2530 return Local<Value>(); // No real property was found in prototype chain.
2531}
2532
2533
2534Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2535 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
2536 ENTER_V8;
2537 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2538 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2539 i::LookupResult lookup;
2540 self_obj->LookupRealNamedProperty(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002541 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002542 PropertyAttributes attributes;
2543 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2544 &lookup,
2545 *key_obj,
2546 &attributes));
2547 return Utils::ToLocal(result);
2548 }
2549 return Local<Value>(); // No real property was found in prototype chain.
2550}
2551
2552
2553// Turns on access checks by copying the map and setting the check flag.
2554// Because the object gets a new map, existing inline cache caching
2555// the old map of this object will fail.
2556void v8::Object::TurnOnAccessCheck() {
2557 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2558 ENTER_V8;
2559 HandleScope scope;
2560 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2561
2562 i::Handle<i::Map> new_map =
2563 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2564 new_map->set_is_access_check_needed(true);
2565 obj->set_map(*new_map);
2566}
2567
2568
2569bool v8::Object::IsDirty() {
2570 return Utils::OpenHandle(this)->IsDirty();
2571}
2572
2573
2574Local<v8::Object> v8::Object::Clone() {
2575 ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2576 ENTER_V8;
2577 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2578 EXCEPTION_PREAMBLE();
2579 i::Handle<i::JSObject> result = i::Copy(self);
2580 has_pending_exception = result.is_null();
2581 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2582 return Utils::ToLocal(result);
2583}
2584
2585
2586int v8::Object::GetIdentityHash() {
2587 ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2588 ENTER_V8;
2589 HandleScope scope;
2590 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2591 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2592 i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
2593 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2594 int hash_value;
2595 if (hash->IsSmi()) {
2596 hash_value = i::Smi::cast(*hash)->value();
2597 } else {
2598 int attempts = 0;
2599 do {
2600 // Generate a random 32-bit hash value but limit range to fit
2601 // within a smi.
2602 hash_value = i::V8::Random() & i::Smi::kMaxValue;
2603 attempts++;
2604 } while (hash_value == 0 && attempts < 30);
2605 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
2606 i::SetProperty(hidden_props,
2607 hash_symbol,
2608 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2609 static_cast<PropertyAttributes>(None));
2610 }
2611 return hash_value;
2612}
2613
2614
2615bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2616 v8::Handle<v8::Value> value) {
2617 ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
2618 ENTER_V8;
2619 HandleScope scope;
2620 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2621 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2622 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2623 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2624 EXCEPTION_PREAMBLE();
2625 i::Handle<i::Object> obj = i::SetProperty(
2626 hidden_props,
2627 key_obj,
2628 value_obj,
2629 static_cast<PropertyAttributes>(None));
2630 has_pending_exception = obj.is_null();
2631 EXCEPTION_BAILOUT_CHECK(false);
2632 return true;
2633}
2634
2635
2636v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2637 ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2638 ENTER_V8;
2639 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2640 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2641 if (hidden_props->IsUndefined()) {
2642 return v8::Local<v8::Value>();
2643 }
2644 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2645 EXCEPTION_PREAMBLE();
2646 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2647 has_pending_exception = result.is_null();
2648 EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2649 if (result->IsUndefined()) {
2650 return v8::Local<v8::Value>();
2651 }
2652 return Utils::ToLocal(result);
2653}
2654
2655
2656bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2657 ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2658 ENTER_V8;
2659 HandleScope scope;
2660 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2661 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2662 if (hidden_props->IsUndefined()) {
2663 return true;
2664 }
2665 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2666 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2667 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2668}
2669
2670
2671void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2672 ON_BAILOUT("v8::SetElementsToPixelData()", return);
2673 ENTER_V8;
2674 HandleScope scope;
Steve Block3ce2e202009-11-05 08:53:23 +00002675 if (!ApiCheck(length <= i::PixelArray::kMaxLength,
Steve Blocka7e24c12009-10-30 11:49:00 +00002676 "v8::Object::SetIndexedPropertiesToPixelData()",
2677 "length exceeds max acceptable value")) {
2678 return;
2679 }
2680 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2681 if (!ApiCheck(!self->IsJSArray(),
2682 "v8::Object::SetIndexedPropertiesToPixelData()",
2683 "JSArray is not supported")) {
2684 return;
2685 }
2686 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002687 i::Handle<i::Map> slow_map =
2688 i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map()));
2689 self->set_map(*slow_map);
Steve Blocka7e24c12009-10-30 11:49:00 +00002690 self->set_elements(*pixels);
2691}
2692
2693
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002694bool v8::Object::HasIndexedPropertiesInPixelData() {
2695 ON_BAILOUT("v8::HasIndexedPropertiesInPixelData()", return false);
2696 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2697 return self->HasPixelElements();
2698}
2699
2700
2701uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
2702 ON_BAILOUT("v8::GetIndexedPropertiesPixelData()", return NULL);
2703 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2704 if (self->HasPixelElements()) {
2705 return i::PixelArray::cast(self->elements())->external_pointer();
2706 } else {
2707 return NULL;
2708 }
2709}
2710
2711
2712int v8::Object::GetIndexedPropertiesPixelDataLength() {
2713 ON_BAILOUT("v8::GetIndexedPropertiesPixelDataLength()", return -1);
2714 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2715 if (self->HasPixelElements()) {
2716 return i::PixelArray::cast(self->elements())->length();
2717 } else {
2718 return -1;
2719 }
2720}
2721
2722
Steve Block3ce2e202009-11-05 08:53:23 +00002723void v8::Object::SetIndexedPropertiesToExternalArrayData(
2724 void* data,
2725 ExternalArrayType array_type,
2726 int length) {
2727 ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
2728 ENTER_V8;
2729 HandleScope scope;
2730 if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
2731 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2732 "length exceeds max acceptable value")) {
2733 return;
2734 }
2735 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2736 if (!ApiCheck(!self->IsJSArray(),
2737 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2738 "JSArray is not supported")) {
2739 return;
2740 }
2741 i::Handle<i::ExternalArray> array =
2742 i::Factory::NewExternalArray(length, array_type, data);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002743 i::Handle<i::Map> slow_map =
2744 i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map()));
2745 self->set_map(*slow_map);
Steve Block3ce2e202009-11-05 08:53:23 +00002746 self->set_elements(*array);
2747}
2748
2749
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002750bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
2751 ON_BAILOUT("v8::HasIndexedPropertiesInExternalArrayData()", return false);
2752 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2753 return self->HasExternalArrayElements();
2754}
2755
2756
2757void* v8::Object::GetIndexedPropertiesExternalArrayData() {
2758 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayData()", return NULL);
2759 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2760 if (self->HasExternalArrayElements()) {
2761 return i::ExternalArray::cast(self->elements())->external_pointer();
2762 } else {
2763 return NULL;
2764 }
2765}
2766
2767
2768ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
2769 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataType()",
2770 return static_cast<ExternalArrayType>(-1));
2771 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2772 switch (self->elements()->map()->instance_type()) {
2773 case i::EXTERNAL_BYTE_ARRAY_TYPE:
2774 return kExternalByteArray;
2775 case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2776 return kExternalUnsignedByteArray;
2777 case i::EXTERNAL_SHORT_ARRAY_TYPE:
2778 return kExternalShortArray;
2779 case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2780 return kExternalUnsignedShortArray;
2781 case i::EXTERNAL_INT_ARRAY_TYPE:
2782 return kExternalIntArray;
2783 case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2784 return kExternalUnsignedIntArray;
2785 case i::EXTERNAL_FLOAT_ARRAY_TYPE:
2786 return kExternalFloatArray;
2787 default:
2788 return static_cast<ExternalArrayType>(-1);
2789 }
2790}
2791
2792
2793int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
2794 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataLength()", return 0);
2795 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2796 if (self->HasExternalArrayElements()) {
2797 return i::ExternalArray::cast(self->elements())->length();
2798 } else {
2799 return -1;
2800 }
2801}
2802
2803
Steve Blocka7e24c12009-10-30 11:49:00 +00002804Local<v8::Object> Function::NewInstance() const {
2805 return NewInstance(0, NULL);
2806}
2807
2808
2809Local<v8::Object> Function::NewInstance(int argc,
2810 v8::Handle<v8::Value> argv[]) const {
2811 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2812 LOG_API("Function::NewInstance");
2813 ENTER_V8;
2814 HandleScope scope;
2815 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2816 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2817 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2818 EXCEPTION_PREAMBLE();
2819 i::Handle<i::Object> returned =
2820 i::Execution::New(function, argc, args, &has_pending_exception);
2821 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2822 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2823}
2824
2825
2826Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2827 v8::Handle<v8::Value> argv[]) {
2828 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2829 LOG_API("Function::Call");
2830 ENTER_V8;
2831 i::Object* raw_result = NULL;
2832 {
2833 HandleScope scope;
2834 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2835 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2836 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2837 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2838 EXCEPTION_PREAMBLE();
2839 i::Handle<i::Object> returned =
2840 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2841 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2842 raw_result = *returned;
2843 }
2844 i::Handle<i::Object> result(raw_result);
2845 return Utils::ToLocal(result);
2846}
2847
2848
2849void Function::SetName(v8::Handle<v8::String> name) {
2850 ENTER_V8;
2851 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2852 func->shared()->set_name(*Utils::OpenHandle(*name));
2853}
2854
2855
2856Handle<Value> Function::GetName() const {
2857 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2858 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2859}
2860
2861
Andrei Popescu402d9372010-02-26 13:31:12 +00002862ScriptOrigin Function::GetScriptOrigin() const {
2863 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2864 if (func->shared()->script()->IsScript()) {
2865 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2866 v8::ScriptOrigin origin(
2867 Utils::ToLocal(i::Handle<i::Object>(script->name())),
2868 v8::Integer::New(script->line_offset()->value()),
2869 v8::Integer::New(script->column_offset()->value()));
2870 return origin;
2871 }
2872 return v8::ScriptOrigin(Handle<Value>());
2873}
2874
2875
2876const int Function::kLineOffsetNotFound = -1;
2877
2878
2879int Function::GetScriptLineNumber() const {
2880 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2881 if (func->shared()->script()->IsScript()) {
2882 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2883 return i::GetScriptLineNumber(script, func->shared()->start_position());
2884 }
2885 return kLineOffsetNotFound;
2886}
2887
2888
2889namespace {
2890
2891// Tracks string usage to help make better decisions when
2892// externalizing strings.
2893//
2894// Implementation note: internally this class only tracks fresh
2895// strings and keeps a single use counter for them.
2896class StringTracker {
2897 public:
2898 // Records that the given string's characters were copied to some
2899 // external buffer. If this happens often we should honor
2900 // externalization requests for the string.
2901 static void RecordWrite(i::Handle<i::String> string) {
2902 i::Address address = reinterpret_cast<i::Address>(*string);
2903 i::Address top = i::Heap::NewSpaceTop();
2904 if (IsFreshString(address, top)) {
2905 IncrementUseCount(top);
2906 }
2907 }
2908
2909 // Estimates freshness and use frequency of the given string based
2910 // on how close it is to the new space top and the recorded usage
2911 // history.
2912 static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
2913 i::Address address = reinterpret_cast<i::Address>(*string);
2914 i::Address top = i::Heap::NewSpaceTop();
2915 return IsFreshString(address, top) && IsUseCountLow(top);
2916 }
2917
2918 private:
2919 static inline bool IsFreshString(i::Address string, i::Address top) {
2920 return top - kFreshnessLimit <= string && string <= top;
2921 }
2922
2923 static inline bool IsUseCountLow(i::Address top) {
2924 if (last_top_ != top) return true;
2925 return use_count_ < kUseLimit;
2926 }
2927
2928 static inline void IncrementUseCount(i::Address top) {
2929 if (last_top_ != top) {
2930 use_count_ = 0;
2931 last_top_ = top;
2932 }
2933 ++use_count_;
2934 }
2935
2936 // How close to the new space top a fresh string has to be.
2937 static const int kFreshnessLimit = 1024;
2938
2939 // The number of uses required to consider a string useful.
2940 static const int kUseLimit = 32;
2941
2942 // Single use counter shared by all fresh strings.
2943 static int use_count_;
2944
2945 // Last new space top when the use count above was valid.
2946 static i::Address last_top_;
2947};
2948
2949int StringTracker::use_count_ = 0;
2950i::Address StringTracker::last_top_ = NULL;
2951
2952} // namespace
2953
2954
Steve Blocka7e24c12009-10-30 11:49:00 +00002955int String::Length() const {
2956 if (IsDeadCheck("v8::String::Length()")) return 0;
2957 return Utils::OpenHandle(this)->length();
2958}
2959
2960
2961int String::Utf8Length() const {
2962 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
2963 return Utils::OpenHandle(this)->Utf8Length();
2964}
2965
2966
Steve Block6ded16b2010-05-10 14:33:55 +01002967int String::WriteUtf8(char* buffer,
2968 int capacity,
2969 int* nchars_ref,
2970 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00002971 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
2972 LOG_API("String::WriteUtf8");
2973 ENTER_V8;
2974 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002975 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01002976 if (hints & HINT_MANY_WRITES_EXPECTED) {
2977 // Flatten the string for efficiency. This applies whether we are
2978 // using StringInputBuffer or Get(i) to access the characters.
2979 str->TryFlatten();
2980 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002981 write_input_buffer.Reset(0, *str);
2982 int len = str->length();
2983 // Encode the first K - 3 bytes directly into the buffer since we
2984 // know there's room for them. If no capacity is given we copy all
2985 // of them here.
2986 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
2987 int i;
2988 int pos = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01002989 int nchars = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002990 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
2991 i::uc32 c = write_input_buffer.GetNext();
2992 int written = unibrow::Utf8::Encode(buffer + pos, c);
2993 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01002994 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00002995 }
2996 if (i < len) {
2997 // For the last characters we need to check the length for each one
2998 // because they may be longer than the remaining space in the
2999 // buffer.
3000 char intermediate[unibrow::Utf8::kMaxEncodedSize];
3001 for (; i < len && pos < capacity; i++) {
3002 i::uc32 c = write_input_buffer.GetNext();
3003 int written = unibrow::Utf8::Encode(intermediate, c);
3004 if (pos + written <= capacity) {
3005 for (int j = 0; j < written; j++)
3006 buffer[pos + j] = intermediate[j];
3007 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01003008 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00003009 } else {
3010 // We've reached the end of the buffer
3011 break;
3012 }
3013 }
3014 }
Steve Block6ded16b2010-05-10 14:33:55 +01003015 if (nchars_ref != NULL) *nchars_ref = nchars;
Steve Blocka7e24c12009-10-30 11:49:00 +00003016 if (i == len && (capacity == -1 || pos < capacity))
3017 buffer[pos++] = '\0';
3018 return pos;
3019}
3020
3021
Steve Block6ded16b2010-05-10 14:33:55 +01003022int String::WriteAscii(char* buffer,
3023 int start,
3024 int length,
3025 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003026 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
3027 LOG_API("String::WriteAscii");
3028 ENTER_V8;
3029 ASSERT(start >= 0 && length >= -1);
3030 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003031 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003032 if (hints & HINT_MANY_WRITES_EXPECTED) {
3033 // Flatten the string for efficiency. This applies whether we are
3034 // using StringInputBuffer or Get(i) to access the characters.
3035 str->TryFlatten();
3036 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003037 int end = length;
3038 if ( (length == -1) || (length > str->length() - start) )
3039 end = str->length() - start;
3040 if (end < 0) return 0;
3041 write_input_buffer.Reset(start, *str);
3042 int i;
3043 for (i = 0; i < end; i++) {
3044 char c = static_cast<char>(write_input_buffer.GetNext());
3045 if (c == '\0') c = ' ';
3046 buffer[i] = c;
3047 }
3048 if (length == -1 || i < length)
3049 buffer[i] = '\0';
3050 return i;
3051}
3052
3053
Steve Block6ded16b2010-05-10 14:33:55 +01003054int String::Write(uint16_t* buffer,
3055 int start,
3056 int length,
3057 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003058 if (IsDeadCheck("v8::String::Write()")) return 0;
3059 LOG_API("String::Write");
3060 ENTER_V8;
3061 ASSERT(start >= 0 && length >= -1);
3062 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003063 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003064 if (hints & HINT_MANY_WRITES_EXPECTED) {
3065 // Flatten the string for efficiency. This applies whether we are
3066 // using StringInputBuffer or Get(i) to access the characters.
3067 str->TryFlatten();
3068 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003069 int end = length;
3070 if ( (length == -1) || (length > str->length() - start) )
3071 end = str->length() - start;
3072 if (end < 0) return 0;
3073 i::String::WriteToFlat(*str, buffer, start, end);
3074 if (length == -1 || end < length)
3075 buffer[end] = '\0';
3076 return end;
3077}
3078
3079
3080bool v8::String::IsExternal() const {
3081 EnsureInitialized("v8::String::IsExternal()");
3082 i::Handle<i::String> str = Utils::OpenHandle(this);
3083 return i::StringShape(*str).IsExternalTwoByte();
3084}
3085
3086
3087bool v8::String::IsExternalAscii() const {
3088 EnsureInitialized("v8::String::IsExternalAscii()");
3089 i::Handle<i::String> str = Utils::OpenHandle(this);
3090 return i::StringShape(*str).IsExternalAscii();
3091}
3092
3093
3094void v8::String::VerifyExternalStringResource(
3095 v8::String::ExternalStringResource* value) const {
3096 i::Handle<i::String> str = Utils::OpenHandle(this);
3097 v8::String::ExternalStringResource* expected;
3098 if (i::StringShape(*str).IsExternalTwoByte()) {
3099 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
3100 expected = reinterpret_cast<ExternalStringResource*>(resource);
3101 } else {
3102 expected = NULL;
3103 }
3104 CHECK_EQ(expected, value);
3105}
3106
3107
3108v8::String::ExternalAsciiStringResource*
3109 v8::String::GetExternalAsciiStringResource() const {
3110 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
3111 i::Handle<i::String> str = Utils::OpenHandle(this);
3112 if (i::StringShape(*str).IsExternalAscii()) {
3113 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
3114 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
3115 } else {
3116 return NULL;
3117 }
3118}
3119
3120
3121double Number::Value() const {
3122 if (IsDeadCheck("v8::Number::Value()")) return 0;
3123 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3124 return obj->Number();
3125}
3126
3127
3128bool Boolean::Value() const {
3129 if (IsDeadCheck("v8::Boolean::Value()")) return false;
3130 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3131 return obj->IsTrue();
3132}
3133
3134
3135int64_t Integer::Value() const {
3136 if (IsDeadCheck("v8::Integer::Value()")) return 0;
3137 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3138 if (obj->IsSmi()) {
3139 return i::Smi::cast(*obj)->value();
3140 } else {
3141 return static_cast<int64_t>(obj->Number());
3142 }
3143}
3144
3145
3146int32_t Int32::Value() const {
3147 if (IsDeadCheck("v8::Int32::Value()")) return 0;
3148 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3149 if (obj->IsSmi()) {
3150 return i::Smi::cast(*obj)->value();
3151 } else {
3152 return static_cast<int32_t>(obj->Number());
3153 }
3154}
3155
3156
Steve Block6ded16b2010-05-10 14:33:55 +01003157uint32_t Uint32::Value() const {
3158 if (IsDeadCheck("v8::Uint32::Value()")) return 0;
3159 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3160 if (obj->IsSmi()) {
3161 return i::Smi::cast(*obj)->value();
3162 } else {
3163 return static_cast<uint32_t>(obj->Number());
3164 }
3165}
3166
3167
Steve Blocka7e24c12009-10-30 11:49:00 +00003168int v8::Object::InternalFieldCount() {
3169 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
3170 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3171 return obj->GetInternalFieldCount();
3172}
3173
3174
3175Local<Value> v8::Object::CheckedGetInternalField(int index) {
3176 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
3177 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3178 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3179 "v8::Object::GetInternalField()",
3180 "Reading internal field out of bounds")) {
3181 return Local<Value>();
3182 }
3183 i::Handle<i::Object> value(obj->GetInternalField(index));
3184 Local<Value> result = Utils::ToLocal(value);
3185#ifdef DEBUG
3186 Local<Value> unchecked = UncheckedGetInternalField(index);
3187 ASSERT(unchecked.IsEmpty() || (unchecked == result));
3188#endif
3189 return result;
3190}
3191
3192
3193void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
3194 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
3195 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3196 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3197 "v8::Object::SetInternalField()",
3198 "Writing internal field out of bounds")) {
3199 return;
3200 }
3201 ENTER_V8;
3202 i::Handle<i::Object> val = Utils::OpenHandle(*value);
3203 obj->SetInternalField(index, *val);
3204}
3205
3206
3207void v8::Object::SetPointerInInternalField(int index, void* value) {
Steve Block6ded16b2010-05-10 14:33:55 +01003208 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003209 i::Object* as_object = reinterpret_cast<i::Object*>(value);
3210 if (as_object->IsSmi()) {
3211 Utils::OpenHandle(this)->SetInternalField(index, as_object);
3212 return;
3213 }
3214 HandleScope scope;
3215 i::Handle<i::Proxy> proxy =
3216 i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
3217 if (!proxy.is_null())
3218 Utils::OpenHandle(this)->SetInternalField(index, *proxy);
Steve Blocka7e24c12009-10-30 11:49:00 +00003219}
3220
3221
3222// --- E n v i r o n m e n t ---
3223
3224bool v8::V8::Initialize() {
3225 if (i::V8::IsRunning()) return true;
3226 ENTER_V8;
3227 HandleScope scope;
Steve Blockd0582a62009-12-15 09:54:21 +00003228 if (i::Snapshot::Initialize()) return true;
3229 return i::V8::Initialize(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00003230}
3231
3232
3233bool v8::V8::Dispose() {
3234 i::V8::TearDown();
3235 return true;
3236}
3237
3238
Steve Block3ce2e202009-11-05 08:53:23 +00003239HeapStatistics::HeapStatistics(): total_heap_size_(0), used_heap_size_(0) { }
3240
3241
3242void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
3243 heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
3244 heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
3245}
3246
3247
3248bool v8::V8::IdleNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003249 // Returning true tells the caller that it need not
3250 // continue to call IdleNotification.
3251 if (!i::V8::IsRunning()) return true;
Steve Block3ce2e202009-11-05 08:53:23 +00003252 return i::V8::IdleNotification();
Steve Blocka7e24c12009-10-30 11:49:00 +00003253}
3254
3255
3256void v8::V8::LowMemoryNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003257 if (!i::V8::IsRunning()) return;
3258 i::Heap::CollectAllGarbage(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00003259}
3260
3261
Steve Block6ded16b2010-05-10 14:33:55 +01003262int v8::V8::ContextDisposedNotification() {
3263 if (!i::V8::IsRunning()) return 0;
3264 return i::Heap::NotifyContextDisposed();
3265}
3266
3267
Steve Blocka7e24c12009-10-30 11:49:00 +00003268const char* v8::V8::GetVersion() {
3269 static v8::internal::EmbeddedVector<char, 128> buffer;
3270 v8::internal::Version::GetString(buffer);
3271 return buffer.start();
3272}
3273
3274
3275static i::Handle<i::FunctionTemplateInfo>
3276 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
3277 if (templ->constructor()->IsUndefined()) {
3278 Local<FunctionTemplate> constructor = FunctionTemplate::New();
3279 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
3280 templ->set_constructor(*Utils::OpenHandle(*constructor));
3281 }
3282 return i::Handle<i::FunctionTemplateInfo>(
3283 i::FunctionTemplateInfo::cast(templ->constructor()));
3284}
3285
3286
3287Persistent<Context> v8::Context::New(
3288 v8::ExtensionConfiguration* extensions,
3289 v8::Handle<ObjectTemplate> global_template,
3290 v8::Handle<Value> global_object) {
3291 EnsureInitialized("v8::Context::New()");
3292 LOG_API("Context::New");
3293 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
3294
3295 // Enter V8 via an ENTER_V8 scope.
3296 i::Handle<i::Context> env;
3297 {
3298 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003299 v8::Handle<ObjectTemplate> proxy_template = global_template;
3300 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
3301 i::Handle<i::FunctionTemplateInfo> global_constructor;
3302
3303 if (!global_template.IsEmpty()) {
3304 // Make sure that the global_template has a constructor.
3305 global_constructor =
3306 EnsureConstructor(Utils::OpenHandle(*global_template));
3307
3308 // Create a fresh template for the global proxy object.
3309 proxy_template = ObjectTemplate::New();
3310 proxy_constructor =
3311 EnsureConstructor(Utils::OpenHandle(*proxy_template));
3312
3313 // Set the global template to be the prototype template of
3314 // global proxy template.
3315 proxy_constructor->set_prototype_template(
3316 *Utils::OpenHandle(*global_template));
3317
3318 // Migrate security handlers from global_template to
3319 // proxy_template. Temporarily removing access check
3320 // information from the global template.
3321 if (!global_constructor->access_check_info()->IsUndefined()) {
3322 proxy_constructor->set_access_check_info(
3323 global_constructor->access_check_info());
3324 proxy_constructor->set_needs_access_check(
3325 global_constructor->needs_access_check());
3326 global_constructor->set_needs_access_check(false);
3327 global_constructor->set_access_check_info(i::Heap::undefined_value());
3328 }
3329 }
3330
3331 // Create the environment.
3332 env = i::Bootstrapper::CreateEnvironment(
3333 Utils::OpenHandle(*global_object),
3334 proxy_template,
3335 extensions);
3336
3337 // Restore the access check info on the global template.
3338 if (!global_template.IsEmpty()) {
3339 ASSERT(!global_constructor.is_null());
3340 ASSERT(!proxy_constructor.is_null());
3341 global_constructor->set_access_check_info(
3342 proxy_constructor->access_check_info());
3343 global_constructor->set_needs_access_check(
3344 proxy_constructor->needs_access_check());
3345 }
3346 }
3347 // Leave V8.
3348
3349 if (env.is_null())
3350 return Persistent<Context>();
3351 return Persistent<Context>(Utils::ToLocal(env));
3352}
3353
3354
3355void v8::Context::SetSecurityToken(Handle<Value> token) {
3356 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
3357 ENTER_V8;
3358 i::Handle<i::Context> env = Utils::OpenHandle(this);
3359 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
3360 env->set_security_token(*token_handle);
3361}
3362
3363
3364void v8::Context::UseDefaultSecurityToken() {
3365 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
3366 ENTER_V8;
3367 i::Handle<i::Context> env = Utils::OpenHandle(this);
3368 env->set_security_token(env->global());
3369}
3370
3371
3372Handle<Value> v8::Context::GetSecurityToken() {
3373 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
3374 i::Handle<i::Context> env = Utils::OpenHandle(this);
3375 i::Object* security_token = env->security_token();
3376 i::Handle<i::Object> token_handle(security_token);
3377 return Utils::ToLocal(token_handle);
3378}
3379
3380
3381bool Context::HasOutOfMemoryException() {
3382 i::Handle<i::Context> env = Utils::OpenHandle(this);
3383 return env->has_out_of_memory();
3384}
3385
3386
3387bool Context::InContext() {
3388 return i::Top::context() != NULL;
3389}
3390
3391
3392v8::Local<v8::Context> Context::GetEntered() {
3393 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
3394 i::Handle<i::Object> last = thread_local.LastEnteredContext();
3395 if (last.is_null()) return Local<Context>();
3396 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
3397 return Utils::ToLocal(context);
3398}
3399
3400
3401v8::Local<v8::Context> Context::GetCurrent() {
3402 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
Steve Block3ce2e202009-11-05 08:53:23 +00003403 i::Handle<i::Object> current = i::Top::global_context();
3404 if (current.is_null()) return Local<Context>();
3405 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
Steve Blocka7e24c12009-10-30 11:49:00 +00003406 return Utils::ToLocal(context);
3407}
3408
3409
3410v8::Local<v8::Context> Context::GetCalling() {
3411 if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
3412 i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
3413 if (calling.is_null()) return Local<Context>();
3414 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
3415 return Utils::ToLocal(context);
3416}
3417
3418
3419v8::Local<v8::Object> Context::Global() {
3420 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
3421 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3422 i::Handle<i::Context> context =
3423 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3424 i::Handle<i::Object> global(context->global_proxy());
3425 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
3426}
3427
3428
3429void Context::DetachGlobal() {
3430 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
3431 ENTER_V8;
3432 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3433 i::Handle<i::Context> context =
3434 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3435 i::Bootstrapper::DetachGlobal(context);
3436}
3437
3438
Andrei Popescu74b3c142010-03-29 12:03:09 +01003439void Context::ReattachGlobal(Handle<Object> global_object) {
3440 if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
3441 ENTER_V8;
3442 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3443 i::Handle<i::Context> context =
3444 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3445 i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
3446}
3447
3448
Steve Blocka7e24c12009-10-30 11:49:00 +00003449Local<v8::Object> ObjectTemplate::NewInstance() {
3450 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
3451 LOG_API("ObjectTemplate::NewInstance");
3452 ENTER_V8;
3453 EXCEPTION_PREAMBLE();
3454 i::Handle<i::Object> obj =
3455 i::Execution::InstantiateObject(Utils::OpenHandle(this),
3456 &has_pending_exception);
3457 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
3458 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3459}
3460
3461
3462Local<v8::Function> FunctionTemplate::GetFunction() {
3463 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
3464 return Local<v8::Function>());
3465 LOG_API("FunctionTemplate::GetFunction");
3466 ENTER_V8;
3467 EXCEPTION_PREAMBLE();
3468 i::Handle<i::Object> obj =
3469 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3470 &has_pending_exception);
3471 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
3472 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3473}
3474
3475
3476bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3477 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
3478 i::Object* obj = *Utils::OpenHandle(*value);
3479 return obj->IsInstanceOf(*Utils::OpenHandle(this));
3480}
3481
3482
3483static Local<External> ExternalNewImpl(void* data) {
3484 return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
3485}
3486
3487static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3488 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3489}
3490
3491
Steve Blocka7e24c12009-10-30 11:49:00 +00003492Local<Value> v8::External::Wrap(void* data) {
3493 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3494 LOG_API("External::Wrap");
3495 EnsureInitialized("v8::External::Wrap()");
3496 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003497 i::Object* as_object = reinterpret_cast<i::Object*>(data);
3498 if (as_object->IsSmi()) {
3499 return Utils::ToLocal(i::Handle<i::Object>(as_object));
Steve Blocka7e24c12009-10-30 11:49:00 +00003500 }
3501 return ExternalNewImpl(data);
3502}
3503
3504
Steve Block3ce2e202009-11-05 08:53:23 +00003505void* v8::Object::SlowGetPointerFromInternalField(int index) {
3506 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3507 i::Object* value = obj->GetInternalField(index);
3508 if (value->IsSmi()) {
3509 return value;
3510 } else if (value->IsProxy()) {
3511 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3512 } else {
3513 return NULL;
3514 }
3515}
3516
3517
Steve Blocka7e24c12009-10-30 11:49:00 +00003518void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3519 if (IsDeadCheck("v8::External::Unwrap()")) return 0;
3520 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3521 void* result;
3522 if (obj->IsSmi()) {
3523 // The external value was an aligned pointer.
Steve Block3ce2e202009-11-05 08:53:23 +00003524 result = *obj;
Steve Blocka7e24c12009-10-30 11:49:00 +00003525 } else if (obj->IsProxy()) {
3526 result = ExternalValueImpl(obj);
3527 } else {
3528 result = NULL;
3529 }
3530 ASSERT_EQ(result, QuickUnwrap(wrapper));
3531 return result;
3532}
3533
3534
3535Local<External> v8::External::New(void* data) {
3536 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3537 LOG_API("External::New");
3538 EnsureInitialized("v8::External::New()");
3539 ENTER_V8;
3540 return ExternalNewImpl(data);
3541}
3542
3543
3544void* External::Value() const {
3545 if (IsDeadCheck("v8::External::Value()")) return 0;
3546 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3547 return ExternalValueImpl(obj);
3548}
3549
3550
3551Local<String> v8::String::Empty() {
3552 EnsureInitialized("v8::String::Empty()");
3553 LOG_API("String::Empty()");
3554 return Utils::ToLocal(i::Factory::empty_symbol());
3555}
3556
3557
3558Local<String> v8::String::New(const char* data, int length) {
3559 EnsureInitialized("v8::String::New()");
3560 LOG_API("String::New(char)");
3561 if (length == 0) return Empty();
3562 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003563 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003564 i::Handle<i::String> result =
3565 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3566 return Utils::ToLocal(result);
3567}
3568
3569
Steve Block3ce2e202009-11-05 08:53:23 +00003570Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3571 EnsureInitialized("v8::String::New()");
3572 LOG_API("String::New(char)");
3573 ENTER_V8;
3574 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3575 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3576 i::Handle<i::String> result = i::Factory::NewConsString(left_string,
3577 right_string);
3578 return Utils::ToLocal(result);
3579}
3580
3581
Steve Blocka7e24c12009-10-30 11:49:00 +00003582Local<String> v8::String::NewUndetectable(const char* data, int length) {
3583 EnsureInitialized("v8::String::NewUndetectable()");
3584 LOG_API("String::NewUndetectable(char)");
3585 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003586 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003587 i::Handle<i::String> result =
3588 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3589 result->MarkAsUndetectable();
3590 return Utils::ToLocal(result);
3591}
3592
3593
3594static int TwoByteStringLength(const uint16_t* data) {
3595 int length = 0;
3596 while (data[length] != '\0') length++;
3597 return length;
3598}
3599
3600
3601Local<String> v8::String::New(const uint16_t* data, int length) {
3602 EnsureInitialized("v8::String::New()");
3603 LOG_API("String::New(uint16_)");
3604 if (length == 0) return Empty();
3605 ENTER_V8;
3606 if (length == -1) length = TwoByteStringLength(data);
3607 i::Handle<i::String> result =
3608 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3609 return Utils::ToLocal(result);
3610}
3611
3612
3613Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
3614 EnsureInitialized("v8::String::NewUndetectable()");
3615 LOG_API("String::NewUndetectable(uint16_)");
3616 ENTER_V8;
3617 if (length == -1) length = TwoByteStringLength(data);
3618 i::Handle<i::String> result =
3619 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3620 result->MarkAsUndetectable();
3621 return Utils::ToLocal(result);
3622}
3623
3624
3625i::Handle<i::String> NewExternalStringHandle(
3626 v8::String::ExternalStringResource* resource) {
3627 i::Handle<i::String> result =
3628 i::Factory::NewExternalStringFromTwoByte(resource);
3629 return result;
3630}
3631
3632
3633i::Handle<i::String> NewExternalAsciiStringHandle(
3634 v8::String::ExternalAsciiStringResource* resource) {
3635 i::Handle<i::String> result =
3636 i::Factory::NewExternalStringFromAscii(resource);
3637 return result;
3638}
3639
3640
Steve Blocka7e24c12009-10-30 11:49:00 +00003641Local<String> v8::String::NewExternal(
3642 v8::String::ExternalStringResource* resource) {
3643 EnsureInitialized("v8::String::NewExternal()");
3644 LOG_API("String::NewExternal");
3645 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003646 i::Handle<i::String> result = NewExternalStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003647 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003648 return Utils::ToLocal(result);
3649}
3650
3651
3652bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3653 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3654 if (this->IsExternal()) return false; // Already an external string.
3655 ENTER_V8;
3656 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003657 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003658 bool result = obj->MakeExternal(resource);
3659 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003660 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003661 }
3662 return result;
3663}
3664
3665
3666Local<String> v8::String::NewExternal(
3667 v8::String::ExternalAsciiStringResource* resource) {
3668 EnsureInitialized("v8::String::NewExternal()");
3669 LOG_API("String::NewExternal");
3670 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003671 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003672 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003673 return Utils::ToLocal(result);
3674}
3675
3676
3677bool v8::String::MakeExternal(
3678 v8::String::ExternalAsciiStringResource* resource) {
3679 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3680 if (this->IsExternal()) return false; // Already an external string.
3681 ENTER_V8;
3682 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003683 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003684 bool result = obj->MakeExternal(resource);
3685 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003686 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003687 }
3688 return result;
3689}
3690
3691
3692bool v8::String::CanMakeExternal() {
3693 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3694 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003695 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003696 int size = obj->Size(); // Byte size of the original string.
3697 if (size < i::ExternalString::kSize)
3698 return false;
3699 i::StringShape shape(*obj);
3700 return !shape.IsExternal();
3701}
3702
3703
3704Local<v8::Object> v8::Object::New() {
3705 EnsureInitialized("v8::Object::New()");
3706 LOG_API("Object::New");
3707 ENTER_V8;
3708 i::Handle<i::JSObject> obj =
3709 i::Factory::NewJSObject(i::Top::object_function());
3710 return Utils::ToLocal(obj);
3711}
3712
3713
3714Local<v8::Value> v8::Date::New(double time) {
3715 EnsureInitialized("v8::Date::New()");
3716 LOG_API("Date::New");
Steve Blockd0582a62009-12-15 09:54:21 +00003717 if (isnan(time)) {
3718 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3719 time = i::OS::nan_value();
3720 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003721 ENTER_V8;
3722 EXCEPTION_PREAMBLE();
3723 i::Handle<i::Object> obj =
3724 i::Execution::NewDate(time, &has_pending_exception);
3725 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3726 return Utils::ToLocal(obj);
3727}
3728
3729
3730double v8::Date::NumberValue() const {
3731 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3732 LOG_API("Date::NumberValue");
3733 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3734 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3735 return jsvalue->value()->Number();
3736}
3737
3738
Ben Murdochf87a2032010-10-22 12:50:53 +01003739static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
3740 char flags_buf[3];
3741 int num_flags = 0;
3742 if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
3743 if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
3744 if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
3745 ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
3746 return i::Factory::LookupSymbol(
3747 i::Vector<const char>(flags_buf, num_flags));
3748}
3749
3750
3751Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
3752 Flags flags) {
3753 EnsureInitialized("v8::RegExp::New()");
3754 LOG_API("RegExp::New");
3755 ENTER_V8;
3756 EXCEPTION_PREAMBLE();
3757 i::Handle<i::JSRegExp> obj = i::Execution::NewJSRegExp(
3758 Utils::OpenHandle(*pattern),
3759 RegExpFlagsToString(flags),
3760 &has_pending_exception);
3761 EXCEPTION_BAILOUT_CHECK(Local<v8::RegExp>());
3762 return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
3763}
3764
3765
3766Local<v8::String> v8::RegExp::GetSource() const {
3767 if (IsDeadCheck("v8::RegExp::GetSource()")) return Local<v8::String>();
3768 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
3769 return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
3770}
3771
3772
3773// Assert that the static flags cast in GetFlags is valid.
3774#define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \
3775 STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \
3776 static_cast<int>(i::JSRegExp::internal_flag))
3777REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
3778REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
3779REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
3780REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
3781#undef REGEXP_FLAG_ASSERT_EQ
3782
3783v8::RegExp::Flags v8::RegExp::GetFlags() const {
3784 if (IsDeadCheck("v8::RegExp::GetFlags()")) return v8::RegExp::kNone;
3785 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
3786 return static_cast<RegExp::Flags>(obj->GetFlags().value());
3787}
3788
3789
Steve Blocka7e24c12009-10-30 11:49:00 +00003790Local<v8::Array> v8::Array::New(int length) {
3791 EnsureInitialized("v8::Array::New()");
3792 LOG_API("Array::New");
3793 ENTER_V8;
3794 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3795 return Utils::ToLocal(obj);
3796}
3797
3798
3799uint32_t v8::Array::Length() const {
3800 if (IsDeadCheck("v8::Array::Length()")) return 0;
3801 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3802 i::Object* length = obj->length();
3803 if (length->IsSmi()) {
3804 return i::Smi::cast(length)->value();
3805 } else {
3806 return static_cast<uint32_t>(length->Number());
3807 }
3808}
3809
3810
3811Local<Object> Array::CloneElementAt(uint32_t index) {
3812 ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3813 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3814 if (!self->HasFastElements()) {
3815 return Local<Object>();
3816 }
3817 i::FixedArray* elms = i::FixedArray::cast(self->elements());
3818 i::Object* paragon = elms->get(index);
3819 if (!paragon->IsJSObject()) {
3820 return Local<Object>();
3821 }
3822 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3823 EXCEPTION_PREAMBLE();
Steve Block6ded16b2010-05-10 14:33:55 +01003824 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003825 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3826 has_pending_exception = result.is_null();
3827 EXCEPTION_BAILOUT_CHECK(Local<Object>());
3828 return Utils::ToLocal(result);
3829}
3830
3831
3832Local<String> v8::String::NewSymbol(const char* data, int length) {
3833 EnsureInitialized("v8::String::NewSymbol()");
3834 LOG_API("String::NewSymbol(char)");
3835 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003836 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003837 i::Handle<i::String> result =
3838 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3839 return Utils::ToLocal(result);
3840}
3841
3842
3843Local<Number> v8::Number::New(double value) {
3844 EnsureInitialized("v8::Number::New()");
Steve Blockd0582a62009-12-15 09:54:21 +00003845 if (isnan(value)) {
3846 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3847 value = i::OS::nan_value();
3848 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003849 ENTER_V8;
3850 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3851 return Utils::NumberToLocal(result);
3852}
3853
3854
3855Local<Integer> v8::Integer::New(int32_t value) {
3856 EnsureInitialized("v8::Integer::New()");
3857 if (i::Smi::IsValid(value)) {
3858 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3859 }
3860 ENTER_V8;
3861 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3862 return Utils::IntegerToLocal(result);
3863}
3864
3865
Steve Block3ce2e202009-11-05 08:53:23 +00003866Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
3867 bool fits_into_int32_t = (value & (1 << 31)) == 0;
3868 if (fits_into_int32_t) {
3869 return Integer::New(static_cast<int32_t>(value));
3870 }
3871 ENTER_V8;
3872 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3873 return Utils::IntegerToLocal(result);
3874}
3875
3876
Steve Blocka7e24c12009-10-30 11:49:00 +00003877void V8::IgnoreOutOfMemoryException() {
3878 thread_local.set_ignore_out_of_memory(true);
3879}
3880
3881
3882bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
3883 EnsureInitialized("v8::V8::AddMessageListener()");
3884 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
3885 ENTER_V8;
3886 HandleScope scope;
3887 NeanderArray listeners(i::Factory::message_listeners());
3888 NeanderObject obj(2);
3889 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
3890 obj.set(1, data.IsEmpty() ?
3891 i::Heap::undefined_value() :
3892 *Utils::OpenHandle(*data));
3893 listeners.add(obj.value());
3894 return true;
3895}
3896
3897
3898void V8::RemoveMessageListeners(MessageCallback that) {
3899 EnsureInitialized("v8::V8::RemoveMessageListener()");
3900 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
3901 ENTER_V8;
3902 HandleScope scope;
3903 NeanderArray listeners(i::Factory::message_listeners());
3904 for (int i = 0; i < listeners.length(); i++) {
3905 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
3906
3907 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
3908 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
3909 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
3910 listeners.set(i, i::Heap::undefined_value());
3911 }
3912 }
3913}
3914
3915
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003916void V8::SetCaptureStackTraceForUncaughtExceptions(
3917 bool capture,
3918 int frame_limit,
3919 StackTrace::StackTraceOptions options) {
3920 i::Top::SetCaptureStackTraceForUncaughtExceptions(
3921 capture,
3922 frame_limit,
3923 options);
3924}
3925
3926
Steve Blocka7e24c12009-10-30 11:49:00 +00003927void V8::SetCounterFunction(CounterLookupCallback callback) {
3928 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
3929 i::StatsTable::SetCounterFunction(callback);
3930}
3931
3932void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
3933 if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
3934 i::StatsTable::SetCreateHistogramFunction(callback);
3935}
3936
3937void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
3938 if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
3939 i::StatsTable::SetAddHistogramSampleFunction(callback);
3940}
3941
3942void V8::EnableSlidingStateWindow() {
3943 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
3944 i::Logger::EnableSlidingStateWindow();
3945}
3946
3947
3948void V8::SetFailedAccessCheckCallbackFunction(
3949 FailedAccessCheckCallback callback) {
3950 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
3951 i::Top::SetFailedAccessCheckCallback(callback);
3952}
3953
3954
3955void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
3956 if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
3957 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
3958 i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
3959}
3960
3961
3962int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
3963 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
3964 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
3965}
3966
3967
3968void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
3969 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
3970 i::Heap::SetGlobalGCPrologueCallback(callback);
3971}
3972
3973
3974void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
3975 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
3976 i::Heap::SetGlobalGCEpilogueCallback(callback);
3977}
3978
3979
Steve Block6ded16b2010-05-10 14:33:55 +01003980void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
3981 if (IsDeadCheck("v8::V8::AddGCPrologueCallback()")) return;
3982 i::Heap::AddGCPrologueCallback(callback, gc_type);
3983}
3984
3985
3986void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
3987 if (IsDeadCheck("v8::V8::RemoveGCPrologueCallback()")) return;
3988 i::Heap::RemoveGCPrologueCallback(callback);
3989}
3990
3991
3992void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
3993 if (IsDeadCheck("v8::V8::AddGCEpilogueCallback()")) return;
3994 i::Heap::AddGCEpilogueCallback(callback, gc_type);
3995}
3996
3997
3998void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
3999 if (IsDeadCheck("v8::V8::RemoveGCEpilogueCallback()")) return;
4000 i::Heap::RemoveGCEpilogueCallback(callback);
4001}
4002
4003
Iain Merrick9ac36c92010-09-13 15:29:50 +01004004void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
4005 ObjectSpace space,
4006 AllocationAction action) {
4007 if (IsDeadCheck("v8::V8::AddMemoryAllocationCallback()")) return;
4008 i::MemoryAllocator::AddMemoryAllocationCallback(callback,
4009 space,
4010 action);
4011}
4012
4013
4014void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
4015 if (IsDeadCheck("v8::V8::RemoveMemoryAllocationCallback()")) return;
4016 i::MemoryAllocator::RemoveMemoryAllocationCallback(callback);
4017}
4018
4019
Steve Blocka7e24c12009-10-30 11:49:00 +00004020void V8::PauseProfiler() {
4021#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004022 PauseProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00004023#endif
4024}
4025
4026
4027void V8::ResumeProfiler() {
4028#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004029 ResumeProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00004030#endif
4031}
4032
4033
4034bool V8::IsProfilerPaused() {
4035#ifdef ENABLE_LOGGING_AND_PROFILING
4036 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
4037#else
4038 return true;
4039#endif
4040}
4041
4042
Andrei Popescu402d9372010-02-26 13:31:12 +00004043void V8::ResumeProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004044#ifdef ENABLE_LOGGING_AND_PROFILING
4045 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
4046 // Snapshot mode: resume modules, perform GC, then pause only
4047 // those modules which haven't been started prior to making a
4048 // snapshot.
4049
Steve Block6ded16b2010-05-10 14:33:55 +01004050 // Make a GC prior to taking a snapshot.
4051 i::Heap::CollectAllGarbage(false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004052 // Reset snapshot flag and CPU module flags.
4053 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
4054 const int current_flags = i::Logger::GetActiveProfilerModules();
Andrei Popescu402d9372010-02-26 13:31:12 +00004055 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004056 i::Heap::CollectAllGarbage(false);
Andrei Popescu402d9372010-02-26 13:31:12 +00004057 i::Logger::PauseProfiler(~current_flags & flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004058 } else {
Andrei Popescu402d9372010-02-26 13:31:12 +00004059 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004060 }
4061#endif
4062}
4063
4064
Andrei Popescu402d9372010-02-26 13:31:12 +00004065void V8::PauseProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004066#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004067 i::Logger::PauseProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004068#endif
4069}
4070
4071
4072int V8::GetActiveProfilerModules() {
4073#ifdef ENABLE_LOGGING_AND_PROFILING
4074 return i::Logger::GetActiveProfilerModules();
4075#else
4076 return PROFILER_MODULE_NONE;
4077#endif
4078}
4079
4080
4081int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
4082#ifdef ENABLE_LOGGING_AND_PROFILING
Steve Block6ded16b2010-05-10 14:33:55 +01004083 ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
Steve Blocka7e24c12009-10-30 11:49:00 +00004084 return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
4085#endif
4086 return 0;
4087}
4088
4089
4090int V8::GetCurrentThreadId() {
4091 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
4092 EnsureInitialized("V8::GetCurrentThreadId()");
4093 return i::Top::thread_id();
4094}
4095
4096
4097void V8::TerminateExecution(int thread_id) {
4098 if (!i::V8::IsRunning()) return;
4099 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
4100 // If the thread_id identifies the current thread just terminate
4101 // execution right away. Otherwise, ask the thread manager to
4102 // terminate the thread with the given id if any.
4103 if (thread_id == i::Top::thread_id()) {
4104 i::StackGuard::TerminateExecution();
4105 } else {
4106 i::ThreadManager::TerminateExecution(thread_id);
4107 }
4108}
4109
4110
4111void V8::TerminateExecution() {
4112 if (!i::V8::IsRunning()) return;
4113 i::StackGuard::TerminateExecution();
4114}
4115
4116
Steve Block6ded16b2010-05-10 14:33:55 +01004117bool V8::IsExecutionTerminating() {
4118 if (!i::V8::IsRunning()) return false;
4119 if (i::Top::has_scheduled_exception()) {
4120 return i::Top::scheduled_exception() == i::Heap::termination_exception();
4121 }
4122 return false;
4123}
4124
4125
Steve Blocka7e24c12009-10-30 11:49:00 +00004126String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
4127 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
4128 if (obj.IsEmpty()) {
4129 str_ = NULL;
4130 length_ = 0;
4131 return;
4132 }
4133 ENTER_V8;
4134 HandleScope scope;
4135 TryCatch try_catch;
4136 Handle<String> str = obj->ToString();
4137 if (str.IsEmpty()) {
4138 str_ = NULL;
4139 length_ = 0;
4140 } else {
4141 length_ = str->Utf8Length();
4142 str_ = i::NewArray<char>(length_ + 1);
4143 str->WriteUtf8(str_);
4144 }
4145}
4146
4147
4148String::Utf8Value::~Utf8Value() {
4149 i::DeleteArray(str_);
4150}
4151
4152
4153String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
4154 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
4155 if (obj.IsEmpty()) {
4156 str_ = NULL;
4157 length_ = 0;
4158 return;
4159 }
4160 ENTER_V8;
4161 HandleScope scope;
4162 TryCatch try_catch;
4163 Handle<String> str = obj->ToString();
4164 if (str.IsEmpty()) {
4165 str_ = NULL;
4166 length_ = 0;
4167 } else {
4168 length_ = str->Length();
4169 str_ = i::NewArray<char>(length_ + 1);
4170 str->WriteAscii(str_);
4171 }
4172}
4173
4174
4175String::AsciiValue::~AsciiValue() {
4176 i::DeleteArray(str_);
4177}
4178
4179
4180String::Value::Value(v8::Handle<v8::Value> obj) {
4181 EnsureInitialized("v8::String::Value::Value()");
4182 if (obj.IsEmpty()) {
4183 str_ = NULL;
4184 length_ = 0;
4185 return;
4186 }
4187 ENTER_V8;
4188 HandleScope scope;
4189 TryCatch try_catch;
4190 Handle<String> str = obj->ToString();
4191 if (str.IsEmpty()) {
4192 str_ = NULL;
4193 length_ = 0;
4194 } else {
4195 length_ = str->Length();
4196 str_ = i::NewArray<uint16_t>(length_ + 1);
4197 str->Write(str_);
4198 }
4199}
4200
4201
4202String::Value::~Value() {
4203 i::DeleteArray(str_);
4204}
4205
4206Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
4207 LOG_API("RangeError");
4208 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
4209 ENTER_V8;
4210 i::Object* error;
4211 {
4212 HandleScope scope;
4213 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4214 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
4215 error = *result;
4216 }
4217 i::Handle<i::Object> result(error);
4218 return Utils::ToLocal(result);
4219}
4220
4221Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
4222 LOG_API("ReferenceError");
4223 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
4224 ENTER_V8;
4225 i::Object* error;
4226 {
4227 HandleScope scope;
4228 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4229 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
4230 error = *result;
4231 }
4232 i::Handle<i::Object> result(error);
4233 return Utils::ToLocal(result);
4234}
4235
4236Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
4237 LOG_API("SyntaxError");
4238 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
4239 ENTER_V8;
4240 i::Object* error;
4241 {
4242 HandleScope scope;
4243 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4244 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
4245 error = *result;
4246 }
4247 i::Handle<i::Object> result(error);
4248 return Utils::ToLocal(result);
4249}
4250
4251Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
4252 LOG_API("TypeError");
4253 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
4254 ENTER_V8;
4255 i::Object* error;
4256 {
4257 HandleScope scope;
4258 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4259 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
4260 error = *result;
4261 }
4262 i::Handle<i::Object> result(error);
4263 return Utils::ToLocal(result);
4264}
4265
4266Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
4267 LOG_API("Error");
4268 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
4269 ENTER_V8;
4270 i::Object* error;
4271 {
4272 HandleScope scope;
4273 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4274 i::Handle<i::Object> result = i::Factory::NewError(message);
4275 error = *result;
4276 }
4277 i::Handle<i::Object> result(error);
4278 return Utils::ToLocal(result);
4279}
4280
4281
4282// --- D e b u g S u p p o r t ---
4283
4284#ifdef ENABLE_DEBUGGER_SUPPORT
Leon Clarkef7060e22010-06-03 12:02:55 +01004285
4286static v8::Debug::EventCallback event_callback = NULL;
4287
4288static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) {
4289 if (event_callback) {
4290 event_callback(event_details.GetEvent(),
4291 event_details.GetExecutionState(),
4292 event_details.GetEventData(),
4293 event_details.GetCallbackData());
4294 }
4295}
4296
4297
Steve Blocka7e24c12009-10-30 11:49:00 +00004298bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
4299 EnsureInitialized("v8::Debug::SetDebugEventListener()");
4300 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4301 ENTER_V8;
Leon Clarkef7060e22010-06-03 12:02:55 +01004302
4303 event_callback = that;
4304
4305 HandleScope scope;
4306 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4307 if (that != NULL) {
4308 proxy = i::Factory::NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
4309 }
4310 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4311 return true;
4312}
4313
4314
4315bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
4316 EnsureInitialized("v8::Debug::SetDebugEventListener2()");
4317 ON_BAILOUT("v8::Debug::SetDebugEventListener2()", return false);
4318 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004319 HandleScope scope;
4320 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4321 if (that != NULL) {
4322 proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
4323 }
4324 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4325 return true;
4326}
4327
4328
4329bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
4330 Handle<Value> data) {
4331 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4332 ENTER_V8;
4333 i::Debugger::SetEventListener(Utils::OpenHandle(*that),
4334 Utils::OpenHandle(*data));
4335 return true;
4336}
4337
4338
4339void Debug::DebugBreak() {
4340 if (!i::V8::IsRunning()) return;
4341 i::StackGuard::DebugBreak();
4342}
4343
4344
Ben Murdochf87a2032010-10-22 12:50:53 +01004345void Debug::CancelDebugBreak() {
4346 i::StackGuard::Continue(i::DEBUGBREAK);
4347}
4348
4349
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004350void Debug::DebugBreakForCommand(ClientData* data) {
4351 if (!i::V8::IsRunning()) return;
4352 i::Debugger::EnqueueDebugCommand(data);
4353}
4354
4355
Steve Blocka7e24c12009-10-30 11:49:00 +00004356static v8::Debug::MessageHandler message_handler = NULL;
4357
4358static void MessageHandlerWrapper(const v8::Debug::Message& message) {
4359 if (message_handler) {
4360 v8::String::Value json(message.GetJSON());
4361 message_handler(*json, json.length(), message.GetClientData());
4362 }
4363}
4364
4365
4366void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
4367 bool message_handler_thread) {
4368 EnsureInitialized("v8::Debug::SetMessageHandler");
4369 ENTER_V8;
4370 // Message handler thread not supported any more. Parameter temporally left in
4371 // the API for client compatability reasons.
4372 CHECK(!message_handler_thread);
4373
4374 // TODO(sgjesse) support the old message handler API through a simple wrapper.
4375 message_handler = handler;
4376 if (message_handler != NULL) {
4377 i::Debugger::SetMessageHandler(MessageHandlerWrapper);
4378 } else {
4379 i::Debugger::SetMessageHandler(NULL);
4380 }
4381}
4382
4383
4384void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
4385 EnsureInitialized("v8::Debug::SetMessageHandler");
4386 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004387 i::Debugger::SetMessageHandler(handler);
4388}
4389
4390
4391void Debug::SendCommand(const uint16_t* command, int length,
4392 ClientData* client_data) {
4393 if (!i::V8::IsRunning()) return;
4394 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
4395 client_data);
4396}
4397
4398
4399void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
4400 int period) {
4401 EnsureInitialized("v8::Debug::SetHostDispatchHandler");
4402 ENTER_V8;
4403 i::Debugger::SetHostDispatchHandler(handler, period);
4404}
4405
4406
Steve Blockd0582a62009-12-15 09:54:21 +00004407void Debug::SetDebugMessageDispatchHandler(
Leon Clarkee46be812010-01-19 14:06:41 +00004408 DebugMessageDispatchHandler handler, bool provide_locker) {
Steve Blockd0582a62009-12-15 09:54:21 +00004409 EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
4410 ENTER_V8;
Leon Clarkee46be812010-01-19 14:06:41 +00004411 i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
Steve Blockd0582a62009-12-15 09:54:21 +00004412}
4413
4414
Steve Blocka7e24c12009-10-30 11:49:00 +00004415Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
4416 v8::Handle<v8::Value> data) {
4417 if (!i::V8::IsRunning()) return Local<Value>();
4418 ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
4419 ENTER_V8;
4420 i::Handle<i::Object> result;
4421 EXCEPTION_PREAMBLE();
4422 if (data.IsEmpty()) {
4423 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4424 i::Factory::undefined_value(),
4425 &has_pending_exception);
4426 } else {
4427 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4428 Utils::OpenHandle(*data),
4429 &has_pending_exception);
4430 }
4431 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4432 return Utils::ToLocal(result);
4433}
4434
4435
4436Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
4437 if (!i::V8::IsRunning()) return Local<Value>();
4438 ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
4439 ENTER_V8;
4440 v8::HandleScope scope;
4441 i::Debug::Load();
4442 i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
4443 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
4444 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
4445 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
4446 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
4447 const int kArgc = 1;
4448 v8::Handle<v8::Value> argv[kArgc] = { obj };
4449 EXCEPTION_PREAMBLE();
4450 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
4451 kArgc,
4452 argv);
4453 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4454 return scope.Close(result);
4455}
4456
4457
Leon Clarkee46be812010-01-19 14:06:41 +00004458bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
4459 return i::Debugger::StartAgent(name, port, wait_for_connection);
Steve Blocka7e24c12009-10-30 11:49:00 +00004460}
Leon Clarkee46be812010-01-19 14:06:41 +00004461
4462void Debug::ProcessDebugMessages() {
4463 i::Execution::ProcessDebugMesssages(true);
4464}
4465
Steve Block6ded16b2010-05-10 14:33:55 +01004466Local<Context> Debug::GetDebugContext() {
4467 EnsureInitialized("v8::Debug::GetDebugContext()");
4468 ENTER_V8;
4469 return Utils::ToLocal(i::Debugger::GetDebugContext());
4470}
4471
Steve Blocka7e24c12009-10-30 11:49:00 +00004472#endif // ENABLE_DEBUGGER_SUPPORT
4473
Steve Block6ded16b2010-05-10 14:33:55 +01004474
4475#ifdef ENABLE_LOGGING_AND_PROFILING
4476
4477Handle<String> CpuProfileNode::GetFunctionName() const {
4478 IsDeadCheck("v8::CpuProfileNode::GetFunctionName");
4479 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4480 const i::CodeEntry* entry = node->entry();
4481 if (!entry->has_name_prefix()) {
4482 return Handle<String>(ToApi<String>(
4483 i::Factory::LookupAsciiSymbol(entry->name())));
4484 } else {
4485 return Handle<String>(ToApi<String>(i::Factory::NewConsString(
4486 i::Factory::LookupAsciiSymbol(entry->name_prefix()),
4487 i::Factory::LookupAsciiSymbol(entry->name()))));
4488 }
4489}
4490
4491
4492Handle<String> CpuProfileNode::GetScriptResourceName() const {
4493 IsDeadCheck("v8::CpuProfileNode::GetScriptResourceName");
4494 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4495 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4496 node->entry()->resource_name())));
4497}
4498
4499
4500int CpuProfileNode::GetLineNumber() const {
4501 IsDeadCheck("v8::CpuProfileNode::GetLineNumber");
4502 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
4503}
4504
4505
4506double CpuProfileNode::GetTotalTime() const {
4507 IsDeadCheck("v8::CpuProfileNode::GetTotalTime");
4508 return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis();
4509}
4510
4511
4512double CpuProfileNode::GetSelfTime() const {
4513 IsDeadCheck("v8::CpuProfileNode::GetSelfTime");
4514 return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis();
4515}
4516
4517
4518double CpuProfileNode::GetTotalSamplesCount() const {
4519 IsDeadCheck("v8::CpuProfileNode::GetTotalSamplesCount");
4520 return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
4521}
4522
4523
4524double CpuProfileNode::GetSelfSamplesCount() const {
4525 IsDeadCheck("v8::CpuProfileNode::GetSelfSamplesCount");
4526 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
4527}
4528
4529
4530unsigned CpuProfileNode::GetCallUid() const {
4531 IsDeadCheck("v8::CpuProfileNode::GetCallUid");
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004532 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
Steve Block6ded16b2010-05-10 14:33:55 +01004533}
4534
4535
4536int CpuProfileNode::GetChildrenCount() const {
4537 IsDeadCheck("v8::CpuProfileNode::GetChildrenCount");
4538 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
4539}
4540
4541
4542const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
4543 IsDeadCheck("v8::CpuProfileNode::GetChild");
4544 const i::ProfileNode* child =
4545 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
4546 return reinterpret_cast<const CpuProfileNode*>(child);
4547}
4548
4549
4550unsigned CpuProfile::GetUid() const {
4551 IsDeadCheck("v8::CpuProfile::GetUid");
4552 return reinterpret_cast<const i::CpuProfile*>(this)->uid();
4553}
4554
4555
4556Handle<String> CpuProfile::GetTitle() const {
4557 IsDeadCheck("v8::CpuProfile::GetTitle");
4558 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4559 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4560 profile->title())));
4561}
4562
4563
4564const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
4565 IsDeadCheck("v8::CpuProfile::GetBottomUpRoot");
4566 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4567 return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
4568}
4569
4570
4571const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
4572 IsDeadCheck("v8::CpuProfile::GetTopDownRoot");
4573 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4574 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
4575}
4576
4577
4578int CpuProfiler::GetProfilesCount() {
4579 IsDeadCheck("v8::CpuProfiler::GetProfilesCount");
4580 return i::CpuProfiler::GetProfilesCount();
4581}
4582
4583
Leon Clarkef7060e22010-06-03 12:02:55 +01004584const CpuProfile* CpuProfiler::GetProfile(int index,
4585 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004586 IsDeadCheck("v8::CpuProfiler::GetProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004587 return reinterpret_cast<const CpuProfile*>(
4588 i::CpuProfiler::GetProfile(
4589 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4590 index));
Steve Block6ded16b2010-05-10 14:33:55 +01004591}
4592
4593
Leon Clarkef7060e22010-06-03 12:02:55 +01004594const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
4595 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004596 IsDeadCheck("v8::CpuProfiler::FindProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004597 return reinterpret_cast<const CpuProfile*>(
4598 i::CpuProfiler::FindProfile(
4599 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4600 uid));
Steve Block6ded16b2010-05-10 14:33:55 +01004601}
4602
4603
4604void CpuProfiler::StartProfiling(Handle<String> title) {
4605 IsDeadCheck("v8::CpuProfiler::StartProfiling");
4606 i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
4607}
4608
4609
Leon Clarkef7060e22010-06-03 12:02:55 +01004610const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
4611 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004612 IsDeadCheck("v8::CpuProfiler::StopProfiling");
4613 return reinterpret_cast<const CpuProfile*>(
Leon Clarkef7060e22010-06-03 12:02:55 +01004614 i::CpuProfiler::StopProfiling(
4615 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4616 *Utils::OpenHandle(*title)));
Steve Block6ded16b2010-05-10 14:33:55 +01004617}
4618
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004619
Iain Merrick75681382010-08-19 15:07:18 +01004620static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
4621 return const_cast<i::HeapGraphEdge*>(
4622 reinterpret_cast<const i::HeapGraphEdge*>(edge));
4623}
4624
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004625HeapGraphEdge::Type HeapGraphEdge::GetType() const {
4626 IsDeadCheck("v8::HeapGraphEdge::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004627 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004628}
4629
4630
4631Handle<Value> HeapGraphEdge::GetName() const {
4632 IsDeadCheck("v8::HeapGraphEdge::GetName");
Iain Merrick75681382010-08-19 15:07:18 +01004633 i::HeapGraphEdge* edge = ToInternal(this);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004634 switch (edge->type()) {
Iain Merrick75681382010-08-19 15:07:18 +01004635 case i::HeapGraphEdge::kContextVariable:
4636 case i::HeapGraphEdge::kInternal:
4637 case i::HeapGraphEdge::kProperty:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004638 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4639 edge->name())));
Iain Merrick75681382010-08-19 15:07:18 +01004640 case i::HeapGraphEdge::kElement:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004641 return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt(
4642 edge->index())));
4643 default: UNREACHABLE();
4644 }
4645 return ImplementationUtilities::Undefined();
4646}
4647
4648
4649const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
4650 IsDeadCheck("v8::HeapGraphEdge::GetFromNode");
Iain Merrick75681382010-08-19 15:07:18 +01004651 const i::HeapEntry* from = ToInternal(this)->From();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004652 return reinterpret_cast<const HeapGraphNode*>(from);
4653}
4654
4655
4656const HeapGraphNode* HeapGraphEdge::GetToNode() const {
4657 IsDeadCheck("v8::HeapGraphEdge::GetToNode");
Iain Merrick75681382010-08-19 15:07:18 +01004658 const i::HeapEntry* to = ToInternal(this)->to();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004659 return reinterpret_cast<const HeapGraphNode*>(to);
4660}
4661
4662
Iain Merrick75681382010-08-19 15:07:18 +01004663static i::HeapGraphPath* ToInternal(const HeapGraphPath* path) {
4664 return const_cast<i::HeapGraphPath*>(
4665 reinterpret_cast<const i::HeapGraphPath*>(path));
4666}
4667
4668
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004669int HeapGraphPath::GetEdgesCount() const {
Iain Merrick75681382010-08-19 15:07:18 +01004670 return ToInternal(this)->path()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004671}
4672
4673
4674const HeapGraphEdge* HeapGraphPath::GetEdge(int index) const {
4675 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004676 ToInternal(this)->path()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004677}
4678
4679
4680const HeapGraphNode* HeapGraphPath::GetFromNode() const {
4681 return GetEdgesCount() > 0 ? GetEdge(0)->GetFromNode() : NULL;
4682}
4683
4684
4685const HeapGraphNode* HeapGraphPath::GetToNode() const {
4686 const int count = GetEdgesCount();
4687 return count > 0 ? GetEdge(count - 1)->GetToNode() : NULL;
4688}
4689
4690
Iain Merrick75681382010-08-19 15:07:18 +01004691static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
4692 return const_cast<i::HeapEntry*>(
4693 reinterpret_cast<const i::HeapEntry*>(entry));
4694}
4695
4696
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004697HeapGraphNode::Type HeapGraphNode::GetType() const {
4698 IsDeadCheck("v8::HeapGraphNode::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004699 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004700}
4701
4702
4703Handle<String> HeapGraphNode::GetName() const {
4704 IsDeadCheck("v8::HeapGraphNode::GetName");
4705 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004706 ToInternal(this)->name())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004707}
4708
4709
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004710uint64_t HeapGraphNode::GetId() const {
4711 IsDeadCheck("v8::HeapGraphNode::GetId");
Steve Block791712a2010-08-27 10:21:07 +01004712 ASSERT(ToInternal(this)->snapshot()->type() != i::HeapSnapshot::kAggregated);
Iain Merrick75681382010-08-19 15:07:18 +01004713 return ToInternal(this)->id();
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004714}
4715
4716
Steve Block791712a2010-08-27 10:21:07 +01004717int HeapGraphNode::GetInstancesCount() const {
4718 IsDeadCheck("v8::HeapGraphNode::GetInstancesCount");
4719 ASSERT(ToInternal(this)->snapshot()->type() == i::HeapSnapshot::kAggregated);
4720 return static_cast<int>(ToInternal(this)->id());
4721}
4722
4723
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004724int HeapGraphNode::GetSelfSize() const {
4725 IsDeadCheck("v8::HeapGraphNode::GetSelfSize");
Iain Merrick75681382010-08-19 15:07:18 +01004726 return ToInternal(this)->self_size();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004727}
4728
4729
Iain Merrick75681382010-08-19 15:07:18 +01004730int HeapGraphNode::GetReachableSize() const {
4731 IsDeadCheck("v8::HeapSnapshot::GetReachableSize");
4732 return ToInternal(this)->ReachableSize();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004733}
4734
4735
Iain Merrick75681382010-08-19 15:07:18 +01004736int HeapGraphNode::GetRetainedSize() const {
4737 IsDeadCheck("v8::HeapSnapshot::GetRetainedSize");
4738 return ToInternal(this)->RetainedSize();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004739}
4740
4741
4742int HeapGraphNode::GetChildrenCount() const {
4743 IsDeadCheck("v8::HeapSnapshot::GetChildrenCount");
Iain Merrick75681382010-08-19 15:07:18 +01004744 return ToInternal(this)->children().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004745}
4746
4747
4748const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
4749 IsDeadCheck("v8::HeapSnapshot::GetChild");
4750 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004751 &ToInternal(this)->children()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004752}
4753
4754
4755int HeapGraphNode::GetRetainersCount() const {
4756 IsDeadCheck("v8::HeapSnapshot::GetRetainersCount");
Iain Merrick75681382010-08-19 15:07:18 +01004757 return ToInternal(this)->retainers().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004758}
4759
4760
4761const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const {
4762 IsDeadCheck("v8::HeapSnapshot::GetRetainer");
4763 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004764 ToInternal(this)->retainers()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004765}
4766
4767
4768int HeapGraphNode::GetRetainingPathsCount() const {
4769 IsDeadCheck("v8::HeapSnapshot::GetRetainingPathsCount");
Iain Merrick75681382010-08-19 15:07:18 +01004770 return ToInternal(this)->GetRetainingPaths()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004771}
4772
4773
4774const HeapGraphPath* HeapGraphNode::GetRetainingPath(int index) const {
4775 IsDeadCheck("v8::HeapSnapshot::GetRetainingPath");
4776 return reinterpret_cast<const HeapGraphPath*>(
Iain Merrick75681382010-08-19 15:07:18 +01004777 ToInternal(this)->GetRetainingPaths()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004778}
4779
4780
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004781const HeapGraphNode* HeapSnapshotsDiff::GetAdditionsRoot() const {
4782 IsDeadCheck("v8::HeapSnapshotsDiff::GetAdditionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004783 i::HeapSnapshotsDiff* diff =
4784 const_cast<i::HeapSnapshotsDiff*>(
4785 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004786 return reinterpret_cast<const HeapGraphNode*>(diff->additions_root());
4787}
4788
4789
4790const HeapGraphNode* HeapSnapshotsDiff::GetDeletionsRoot() const {
4791 IsDeadCheck("v8::HeapSnapshotsDiff::GetDeletionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004792 i::HeapSnapshotsDiff* diff =
4793 const_cast<i::HeapSnapshotsDiff*>(
4794 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004795 return reinterpret_cast<const HeapGraphNode*>(diff->deletions_root());
4796}
4797
4798
Iain Merrick75681382010-08-19 15:07:18 +01004799static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
4800 return const_cast<i::HeapSnapshot*>(
4801 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
4802}
4803
4804
Steve Block791712a2010-08-27 10:21:07 +01004805HeapSnapshot::Type HeapSnapshot::GetType() const {
4806 IsDeadCheck("v8::HeapSnapshot::GetType");
4807 return static_cast<HeapSnapshot::Type>(ToInternal(this)->type());
4808}
4809
4810
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004811unsigned HeapSnapshot::GetUid() const {
4812 IsDeadCheck("v8::HeapSnapshot::GetUid");
Iain Merrick75681382010-08-19 15:07:18 +01004813 return ToInternal(this)->uid();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004814}
4815
4816
4817Handle<String> HeapSnapshot::GetTitle() const {
4818 IsDeadCheck("v8::HeapSnapshot::GetTitle");
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004819 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004820 ToInternal(this)->title())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004821}
4822
4823
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004824const HeapGraphNode* HeapSnapshot::GetRoot() const {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004825 IsDeadCheck("v8::HeapSnapshot::GetHead");
Iain Merrick75681382010-08-19 15:07:18 +01004826 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004827}
4828
4829
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004830const HeapSnapshotsDiff* HeapSnapshot::CompareWith(
4831 const HeapSnapshot* snapshot) const {
4832 IsDeadCheck("v8::HeapSnapshot::CompareWith");
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004833 return reinterpret_cast<const HeapSnapshotsDiff*>(
Iain Merrick75681382010-08-19 15:07:18 +01004834 ToInternal(this)->CompareWith(ToInternal(snapshot)));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004835}
4836
4837
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004838void HeapSnapshot::Serialize(OutputStream* stream,
4839 HeapSnapshot::SerializationFormat format) const {
4840 IsDeadCheck("v8::HeapSnapshot::Serialize");
4841 ApiCheck(format == kJSON,
4842 "v8::HeapSnapshot::Serialize",
4843 "Unknown serialization format");
4844 ApiCheck(stream->GetOutputEncoding() == OutputStream::kAscii,
4845 "v8::HeapSnapshot::Serialize",
4846 "Unsupported output encoding");
4847 ApiCheck(stream->GetChunkSize() > 0,
4848 "v8::HeapSnapshot::Serialize",
4849 "Invalid stream chunk size");
4850 i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
4851 serializer.Serialize(stream);
4852}
4853
4854
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004855int HeapProfiler::GetSnapshotsCount() {
4856 IsDeadCheck("v8::HeapProfiler::GetSnapshotsCount");
4857 return i::HeapProfiler::GetSnapshotsCount();
4858}
4859
4860
4861const HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
4862 IsDeadCheck("v8::HeapProfiler::GetSnapshot");
4863 return reinterpret_cast<const HeapSnapshot*>(
4864 i::HeapProfiler::GetSnapshot(index));
4865}
4866
4867
4868const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
4869 IsDeadCheck("v8::HeapProfiler::FindSnapshot");
4870 return reinterpret_cast<const HeapSnapshot*>(
4871 i::HeapProfiler::FindSnapshot(uid));
4872}
4873
4874
Steve Block791712a2010-08-27 10:21:07 +01004875const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title,
4876 HeapSnapshot::Type type) {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004877 IsDeadCheck("v8::HeapProfiler::TakeSnapshot");
Steve Block791712a2010-08-27 10:21:07 +01004878 i::HeapSnapshot::Type internal_type = i::HeapSnapshot::kFull;
4879 switch (type) {
4880 case HeapSnapshot::kFull:
4881 internal_type = i::HeapSnapshot::kFull;
4882 break;
4883 case HeapSnapshot::kAggregated:
4884 internal_type = i::HeapSnapshot::kAggregated;
4885 break;
4886 default:
4887 UNREACHABLE();
4888 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004889 return reinterpret_cast<const HeapSnapshot*>(
Steve Block791712a2010-08-27 10:21:07 +01004890 i::HeapProfiler::TakeSnapshot(*Utils::OpenHandle(*title), internal_type));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004891}
4892
Steve Block6ded16b2010-05-10 14:33:55 +01004893#endif // ENABLE_LOGGING_AND_PROFILING
4894
4895
Steve Blocka7e24c12009-10-30 11:49:00 +00004896namespace internal {
4897
4898
4899HandleScopeImplementer* HandleScopeImplementer::instance() {
4900 return &thread_local;
4901}
4902
4903
4904void HandleScopeImplementer::FreeThreadResources() {
4905 thread_local.Free();
4906}
4907
4908
4909char* HandleScopeImplementer::ArchiveThread(char* storage) {
4910 return thread_local.ArchiveThreadHelper(storage);
4911}
4912
4913
4914char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
4915 v8::ImplementationUtilities::HandleScopeData* current =
4916 v8::ImplementationUtilities::CurrentHandleScope();
4917 handle_scope_data_ = *current;
4918 memcpy(storage, this, sizeof(*this));
4919
4920 ResetAfterArchive();
4921 current->Initialize();
4922
4923 return storage + ArchiveSpacePerThread();
4924}
4925
4926
4927int HandleScopeImplementer::ArchiveSpacePerThread() {
4928 return sizeof(thread_local);
4929}
4930
4931
4932char* HandleScopeImplementer::RestoreThread(char* storage) {
4933 return thread_local.RestoreThreadHelper(storage);
4934}
4935
4936
4937char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
4938 memcpy(this, storage, sizeof(*this));
4939 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
4940 return storage + ArchiveSpacePerThread();
4941}
4942
4943
4944void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
4945 // Iterate over all handles in the blocks except for the last.
4946 for (int i = blocks()->length() - 2; i >= 0; --i) {
4947 Object** block = blocks()->at(i);
4948 v->VisitPointers(block, &block[kHandleBlockSize]);
4949 }
4950
4951 // Iterate over live handles in the last block (if any).
4952 if (!blocks()->is_empty()) {
4953 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
4954 }
4955
4956 if (!saved_contexts_.is_empty()) {
4957 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
4958 v->VisitPointers(start, start + saved_contexts_.length());
4959 }
4960}
4961
4962
4963void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
4964 v8::ImplementationUtilities::HandleScopeData* current =
4965 v8::ImplementationUtilities::CurrentHandleScope();
4966 thread_local.handle_scope_data_ = *current;
4967 thread_local.IterateThis(v);
4968}
4969
4970
4971char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
4972 HandleScopeImplementer* thread_local =
4973 reinterpret_cast<HandleScopeImplementer*>(storage);
4974 thread_local->IterateThis(v);
4975 return storage + ArchiveSpacePerThread();
4976}
4977
4978} } // namespace v8::internal