blob: 555af843168431b33f6891d9e0981c233160483b [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"
Ben Murdochb0fe1622011-05-05 13:52:32 +010036#include "deoptimizer.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000037#include "execution.h"
38#include "global-handles.h"
Kristian Monsen9dcf7e22010-06-28 14:14:28 +010039#include "heap-profiler.h"
Steve Block6ded16b2010-05-10 14:33:55 +010040#include "messages.h"
Ben Murdochf87a2032010-10-22 12:50:53 +010041#include "parser.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000042#include "platform.h"
Steve Block6ded16b2010-05-10 14:33:55 +010043#include "profile-generator-inl.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010044#include "runtime-profiler.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000045#include "serialize.h"
46#include "snapshot.h"
Steve Block6ded16b2010-05-10 14:33:55 +010047#include "top.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000048#include "v8threads.h"
49#include "version.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010050#include "vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000051
Steve Block6ded16b2010-05-10 14:33:55 +010052#include "../include/v8-profiler.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010053#include "../include/v8-testing.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000054
55#define LOG_API(expr) LOG(ApiEntryCall(expr))
56
Leon Clarkef7060e22010-06-03 12:02:55 +010057#ifdef ENABLE_VMSTATE_TRACKING
Ben Murdochb0fe1622011-05-05 13:52:32 +010058#define ENTER_V8 ASSERT(i::V8::IsRunning()); i::VMState __state__(i::OTHER)
Steve Blocka7e24c12009-10-30 11:49:00 +000059#define LEAVE_V8 i::VMState __state__(i::EXTERNAL)
60#else
61#define ENTER_V8 ((void) 0)
62#define LEAVE_V8 ((void) 0)
63#endif
64
65namespace v8 {
66
Leon Clarkef7060e22010-06-03 12:02:55 +010067#define ON_BAILOUT(location, code) \
68 if (IsDeadCheck(location) || v8::V8::IsExecutionTerminating()) { \
69 code; \
70 UNREACHABLE(); \
Steve Blocka7e24c12009-10-30 11:49:00 +000071 }
72
73
74#define EXCEPTION_PREAMBLE() \
75 thread_local.IncrementCallDepth(); \
76 ASSERT(!i::Top::external_caught_exception()); \
77 bool has_pending_exception = false
78
79
80#define EXCEPTION_BAILOUT_CHECK(value) \
81 do { \
82 thread_local.DecrementCallDepth(); \
83 if (has_pending_exception) { \
84 if (thread_local.CallDepthIsZero() && i::Top::is_out_of_memory()) { \
85 if (!thread_local.ignore_out_of_memory()) \
86 i::V8::FatalProcessOutOfMemory(NULL); \
87 } \
88 bool call_depth_is_zero = thread_local.CallDepthIsZero(); \
89 i::Top::OptionalRescheduleException(call_depth_is_zero); \
90 return value; \
91 } \
92 } while (false)
93
94
95#define API_ENTRY_CHECK(msg) \
96 do { \
97 if (v8::Locker::IsActive()) { \
98 ApiCheck(i::ThreadManager::IsLockedByCurrentThread(), \
99 msg, \
100 "Entering the V8 API without proper locking in place"); \
101 } \
102 } while (false)
103
Ben Murdochb0fe1622011-05-05 13:52:32 +0100104
Steve Blocka7e24c12009-10-30 11:49:00 +0000105// --- 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 ---
106
107
108static i::HandleScopeImplementer thread_local;
109
110
111// --- E x c e p t i o n B e h a v i o r ---
112
113
114static FatalErrorCallback exception_behavior = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000115
116static void DefaultFatalErrorHandler(const char* location,
117 const char* message) {
Steve Block1e0659c2011-05-24 12:43:12 +0100118#ifdef ENABLE_VMSTATE_TRACKING
119 i::VMState __state__(i::OTHER);
120#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000121 API_Fatal(location, message);
122}
123
124
Steve Blocka7e24c12009-10-30 11:49:00 +0000125static FatalErrorCallback& GetFatalErrorHandler() {
126 if (exception_behavior == NULL) {
127 exception_behavior = DefaultFatalErrorHandler;
128 }
129 return exception_behavior;
130}
131
132
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800133void i::FatalProcessOutOfMemory(const char* location) {
134 i::V8::FatalProcessOutOfMemory(location, false);
135}
136
Steve Blocka7e24c12009-10-30 11:49:00 +0000137
138// When V8 cannot allocated memory FatalProcessOutOfMemory is called.
139// The default fatal error handler is called and execution is stopped.
Ben Murdochbb769b22010-08-11 14:56:33 +0100140void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
Steve Blockd0582a62009-12-15 09:54:21 +0000141 i::HeapStats heap_stats;
142 int start_marker;
143 heap_stats.start_marker = &start_marker;
144 int new_space_size;
145 heap_stats.new_space_size = &new_space_size;
146 int new_space_capacity;
147 heap_stats.new_space_capacity = &new_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100148 intptr_t old_pointer_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000149 heap_stats.old_pointer_space_size = &old_pointer_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100150 intptr_t old_pointer_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000151 heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100152 intptr_t old_data_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000153 heap_stats.old_data_space_size = &old_data_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100154 intptr_t old_data_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000155 heap_stats.old_data_space_capacity = &old_data_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100156 intptr_t code_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000157 heap_stats.code_space_size = &code_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100158 intptr_t code_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000159 heap_stats.code_space_capacity = &code_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100160 intptr_t map_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000161 heap_stats.map_space_size = &map_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100162 intptr_t map_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000163 heap_stats.map_space_capacity = &map_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100164 intptr_t cell_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000165 heap_stats.cell_space_size = &cell_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100166 intptr_t cell_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000167 heap_stats.cell_space_capacity = &cell_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100168 intptr_t lo_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000169 heap_stats.lo_space_size = &lo_space_size;
170 int global_handle_count;
171 heap_stats.global_handle_count = &global_handle_count;
172 int weak_global_handle_count;
173 heap_stats.weak_global_handle_count = &weak_global_handle_count;
174 int pending_global_handle_count;
175 heap_stats.pending_global_handle_count = &pending_global_handle_count;
176 int near_death_global_handle_count;
177 heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
178 int destroyed_global_handle_count;
179 heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count;
Ben Murdochf87a2032010-10-22 12:50:53 +0100180 intptr_t memory_allocator_size;
Ben Murdochbb769b22010-08-11 14:56:33 +0100181 heap_stats.memory_allocator_size = &memory_allocator_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100182 intptr_t memory_allocator_capacity;
Ben Murdochbb769b22010-08-11 14:56:33 +0100183 heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
184 int objects_per_type[LAST_TYPE + 1] = {0};
185 heap_stats.objects_per_type = objects_per_type;
186 int size_per_type[LAST_TYPE + 1] = {0};
187 heap_stats.size_per_type = size_per_type;
Iain Merrick75681382010-08-19 15:07:18 +0100188 int os_error;
189 heap_stats.os_error = &os_error;
Steve Blockd0582a62009-12-15 09:54:21 +0000190 int end_marker;
191 heap_stats.end_marker = &end_marker;
Ben Murdochbb769b22010-08-11 14:56:33 +0100192 i::Heap::RecordStats(&heap_stats, take_snapshot);
Steve Blocka7e24c12009-10-30 11:49:00 +0000193 i::V8::SetFatalError();
194 FatalErrorCallback callback = GetFatalErrorHandler();
195 {
196 LEAVE_V8;
197 callback(location, "Allocation failed - process out of memory");
198 }
199 // If the callback returns, we stop execution.
200 UNREACHABLE();
201}
202
203
204void V8::SetFatalErrorHandler(FatalErrorCallback that) {
205 exception_behavior = that;
206}
207
208
209bool Utils::ReportApiFailure(const char* location, const char* message) {
210 FatalErrorCallback callback = GetFatalErrorHandler();
211 callback(location, message);
212 i::V8::SetFatalError();
213 return false;
214}
215
216
217bool V8::IsDead() {
218 return i::V8::IsDead();
219}
220
221
222static inline bool ApiCheck(bool condition,
223 const char* location,
224 const char* message) {
225 return condition ? true : Utils::ReportApiFailure(location, message);
226}
227
228
229static bool ReportV8Dead(const char* location) {
230 FatalErrorCallback callback = GetFatalErrorHandler();
231 callback(location, "V8 is no longer usable");
232 return true;
233}
234
235
236static bool ReportEmptyHandle(const char* location) {
237 FatalErrorCallback callback = GetFatalErrorHandler();
238 callback(location, "Reading from empty handle");
239 return true;
240}
241
242
243/**
244 * IsDeadCheck checks that the vm is usable. If, for instance, the vm has been
245 * out of memory at some point this check will fail. It should be called on
246 * entry to all methods that touch anything in the heap, except destructors
247 * which you sometimes can't avoid calling after the vm has crashed. Functions
248 * that call EnsureInitialized or ON_BAILOUT don't have to also call
249 * IsDeadCheck. ON_BAILOUT has the advantage over EnsureInitialized that you
250 * can arrange to return if the VM is dead. This is needed to ensure that no VM
251 * heap allocations are attempted on a dead VM. EnsureInitialized has the
252 * advantage over ON_BAILOUT that it actually initializes the VM if this has not
253 * yet been done.
254 */
255static inline bool IsDeadCheck(const char* location) {
256 return !i::V8::IsRunning()
257 && i::V8::IsDead() ? ReportV8Dead(location) : false;
258}
259
260
261static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
262 return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
263}
264
265
266static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
267 return (obj == 0) ? ReportEmptyHandle(location) : false;
268}
269
270// --- S t a t i c s ---
271
272
273static i::StringInputBuffer write_input_buffer;
274
275
276static inline bool EnsureInitialized(const char* location) {
277 if (i::V8::IsRunning()) {
278 return true;
279 }
280 if (IsDeadCheck(location)) {
281 return false;
282 }
283 return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
284}
285
286
287ImplementationUtilities::HandleScopeData*
288 ImplementationUtilities::CurrentHandleScope() {
289 return &i::HandleScope::current_;
290}
291
292
293#ifdef DEBUG
294void ImplementationUtilities::ZapHandleRange(i::Object** begin,
295 i::Object** end) {
296 i::HandleScope::ZapRange(begin, end);
297}
298#endif
299
300
301v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
302 if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
303 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
304}
305
306
307v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
308 if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
309 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
310}
311
312
313v8::Handle<v8::Boolean> ImplementationUtilities::True() {
314 if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
315 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
316}
317
318
319v8::Handle<v8::Boolean> ImplementationUtilities::False() {
320 if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
321 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
322}
323
324
325void V8::SetFlagsFromString(const char* str, int length) {
326 i::FlagList::SetFlagsFromString(str, length);
327}
328
329
330void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
331 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
332}
333
334
335v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
336 if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
337 ENTER_V8;
338 // If we're passed an empty handle, we throw an undefined exception
339 // to deal more gracefully with out of memory situations.
340 if (value.IsEmpty()) {
341 i::Top::ScheduleThrow(i::Heap::undefined_value());
342 } else {
343 i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
344 }
345 return v8::Undefined();
346}
347
348
349RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
350
351
352RegisteredExtension::RegisteredExtension(Extension* extension)
353 : extension_(extension), state_(UNVISITED) { }
354
355
356void RegisteredExtension::Register(RegisteredExtension* that) {
357 that->next_ = RegisteredExtension::first_extension_;
358 RegisteredExtension::first_extension_ = that;
359}
360
361
362void RegisterExtension(Extension* that) {
363 RegisteredExtension* extension = new RegisteredExtension(that);
364 RegisteredExtension::Register(extension);
365}
366
367
368Extension::Extension(const char* name,
369 const char* source,
370 int dep_count,
371 const char** deps)
372 : name_(name),
373 source_(source),
374 dep_count_(dep_count),
375 deps_(deps),
376 auto_enable_(false) { }
377
378
379v8::Handle<Primitive> Undefined() {
380 LOG_API("Undefined");
381 return ImplementationUtilities::Undefined();
382}
383
384
385v8::Handle<Primitive> Null() {
386 LOG_API("Null");
387 return ImplementationUtilities::Null();
388}
389
390
391v8::Handle<Boolean> True() {
392 LOG_API("True");
393 return ImplementationUtilities::True();
394}
395
396
397v8::Handle<Boolean> False() {
398 LOG_API("False");
399 return ImplementationUtilities::False();
400}
401
402
403ResourceConstraints::ResourceConstraints()
404 : max_young_space_size_(0),
405 max_old_space_size_(0),
Russell Brenner90bac252010-11-18 13:33:46 -0800406 max_executable_size_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +0000407 stack_limit_(NULL) { }
408
409
410bool SetResourceConstraints(ResourceConstraints* constraints) {
Steve Block3ce2e202009-11-05 08:53:23 +0000411 int young_space_size = constraints->max_young_space_size();
Steve Blocka7e24c12009-10-30 11:49:00 +0000412 int old_gen_size = constraints->max_old_space_size();
Russell Brenner90bac252010-11-18 13:33:46 -0800413 int max_executable_size = constraints->max_executable_size();
414 if (young_space_size != 0 || old_gen_size != 0 || max_executable_size != 0) {
415 bool result = i::Heap::ConfigureHeap(young_space_size / 2,
416 old_gen_size,
417 max_executable_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000418 if (!result) return false;
419 }
420 if (constraints->stack_limit() != NULL) {
421 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
422 i::StackGuard::SetStackLimit(limit);
423 }
424 return true;
425}
426
427
428i::Object** V8::GlobalizeReference(i::Object** obj) {
429 if (IsDeadCheck("V8::Persistent::New")) return NULL;
430 LOG_API("Persistent::New");
431 i::Handle<i::Object> result =
432 i::GlobalHandles::Create(*obj);
433 return result.location();
434}
435
436
437void V8::MakeWeak(i::Object** object, void* parameters,
438 WeakReferenceCallback callback) {
439 LOG_API("MakeWeak");
440 i::GlobalHandles::MakeWeak(object, parameters, callback);
441}
442
443
444void V8::ClearWeak(i::Object** obj) {
445 LOG_API("ClearWeak");
446 i::GlobalHandles::ClearWeakness(obj);
447}
448
449
450bool V8::IsGlobalNearDeath(i::Object** obj) {
451 LOG_API("IsGlobalNearDeath");
452 if (!i::V8::IsRunning()) return false;
453 return i::GlobalHandles::IsNearDeath(obj);
454}
455
456
457bool V8::IsGlobalWeak(i::Object** obj) {
458 LOG_API("IsGlobalWeak");
459 if (!i::V8::IsRunning()) return false;
460 return i::GlobalHandles::IsWeak(obj);
461}
462
463
464void V8::DisposeGlobal(i::Object** obj) {
465 LOG_API("DisposeGlobal");
466 if (!i::V8::IsRunning()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000467 i::GlobalHandles::Destroy(obj);
468}
469
470// --- H a n d l e s ---
471
472
John Reck59135872010-11-02 12:39:01 -0700473HandleScope::HandleScope()
474 : prev_next_(i::HandleScope::current_.next),
475 prev_limit_(i::HandleScope::current_.limit),
476 is_closed_(false) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000477 API_ENTRY_CHECK("HandleScope::HandleScope");
John Reck59135872010-11-02 12:39:01 -0700478 i::HandleScope::current_.level++;
Steve Blocka7e24c12009-10-30 11:49:00 +0000479}
480
481
482HandleScope::~HandleScope() {
483 if (!is_closed_) {
John Reck59135872010-11-02 12:39:01 -0700484 Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +0000485 }
486}
487
488
John Reck59135872010-11-02 12:39:01 -0700489void HandleScope::Leave() {
490 i::HandleScope::current_.level--;
491 ASSERT(i::HandleScope::current_.level >= 0);
492 i::HandleScope::current_.next = prev_next_;
493 if (i::HandleScope::current_.limit != prev_limit_) {
494 i::HandleScope::current_.limit = prev_limit_;
495 i::HandleScope::DeleteExtensions();
496 }
497
498#ifdef DEBUG
499 i::HandleScope::ZapRange(prev_next_, prev_limit_);
500#endif
501}
502
503
Steve Blocka7e24c12009-10-30 11:49:00 +0000504int HandleScope::NumberOfHandles() {
505 return i::HandleScope::NumberOfHandles();
506}
507
508
509i::Object** v8::HandleScope::CreateHandle(i::Object* value) {
510 return i::HandleScope::CreateHandle(value);
511}
512
513
514void Context::Enter() {
515 if (IsDeadCheck("v8::Context::Enter()")) return;
516 ENTER_V8;
517 i::Handle<i::Context> env = Utils::OpenHandle(this);
518 thread_local.EnterContext(env);
519
520 thread_local.SaveContext(i::Top::context());
521 i::Top::set_context(*env);
522}
523
524
525void Context::Exit() {
526 if (!i::V8::IsRunning()) return;
527 if (!ApiCheck(thread_local.LeaveLastContext(),
528 "v8::Context::Exit()",
529 "Cannot exit non-entered context")) {
530 return;
531 }
532
533 // Content of 'last_context' could be NULL.
534 i::Context* last_context = thread_local.RestoreContext();
535 i::Top::set_context(last_context);
536}
537
538
Steve Blockd0582a62009-12-15 09:54:21 +0000539void Context::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000540 if (IsDeadCheck("v8::Context::SetData()")) return;
541 ENTER_V8;
542 {
543 HandleScope scope;
544 i::Handle<i::Context> env = Utils::OpenHandle(this);
545 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
546 ASSERT(env->IsGlobalContext());
547 if (env->IsGlobalContext()) {
548 env->set_data(*raw_data);
549 }
550 }
551}
552
553
554v8::Local<v8::Value> Context::GetData() {
555 if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
556 ENTER_V8;
557 i::Object* raw_result = NULL;
558 {
559 HandleScope scope;
560 i::Handle<i::Context> env = Utils::OpenHandle(this);
561 ASSERT(env->IsGlobalContext());
562 if (env->IsGlobalContext()) {
563 raw_result = env->data();
564 } else {
565 return Local<Value>();
566 }
567 }
568 i::Handle<i::Object> result(raw_result);
569 return Utils::ToLocal(result);
570}
571
572
573i::Object** v8::HandleScope::RawClose(i::Object** value) {
574 if (!ApiCheck(!is_closed_,
575 "v8::HandleScope::Close()",
576 "Local scope has already been closed")) {
577 return 0;
578 }
579 LOG_API("CloseHandleScope");
580
581 // Read the result before popping the handle block.
Steve Block6ded16b2010-05-10 14:33:55 +0100582 i::Object* result = NULL;
583 if (value != NULL) {
584 result = *value;
585 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000586 is_closed_ = true;
John Reck59135872010-11-02 12:39:01 -0700587 Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +0000588
Steve Block6ded16b2010-05-10 14:33:55 +0100589 if (value == NULL) {
590 return NULL;
591 }
592
Steve Blocka7e24c12009-10-30 11:49:00 +0000593 // Allocate a new handle on the previous handle block.
594 i::Handle<i::Object> handle(result);
595 return handle.location();
596}
597
598
599// --- N e a n d e r ---
600
601
602// A constructor cannot easily return an error value, therefore it is necessary
603// to check for a dead VM with ON_BAILOUT before constructing any Neander
604// objects. To remind you about this there is no HandleScope in the
605// NeanderObject constructor. When you add one to the site calling the
606// constructor you should check that you ensured the VM was not dead first.
607NeanderObject::NeanderObject(int size) {
608 EnsureInitialized("v8::Nowhere");
609 ENTER_V8;
610 value_ = i::Factory::NewNeanderObject();
611 i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
612 value_->set_elements(*elements);
613}
614
615
616int NeanderObject::size() {
617 return i::FixedArray::cast(value_->elements())->length();
618}
619
620
621NeanderArray::NeanderArray() : obj_(2) {
622 obj_.set(0, i::Smi::FromInt(0));
623}
624
625
626int NeanderArray::length() {
627 return i::Smi::cast(obj_.get(0))->value();
628}
629
630
631i::Object* NeanderArray::get(int offset) {
632 ASSERT(0 <= offset);
633 ASSERT(offset < length());
634 return obj_.get(offset + 1);
635}
636
637
638// This method cannot easily return an error value, therefore it is necessary
639// to check for a dead VM with ON_BAILOUT before calling it. To remind you
640// about this there is no HandleScope in this method. When you add one to the
641// site calling this method you should check that you ensured the VM was not
642// dead first.
643void NeanderArray::add(i::Handle<i::Object> value) {
644 int length = this->length();
645 int size = obj_.size();
646 if (length == size - 1) {
647 i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
648 for (int i = 0; i < length; i++)
649 new_elms->set(i + 1, get(i));
650 obj_.value()->set_elements(*new_elms);
651 }
652 obj_.set(length + 1, *value);
653 obj_.set(0, i::Smi::FromInt(length + 1));
654}
655
656
657void NeanderArray::set(int index, i::Object* value) {
658 if (index < 0 || index >= this->length()) return;
659 obj_.set(index + 1, value);
660}
661
662
663// --- T e m p l a t e ---
664
665
666static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
667 that->set_tag(i::Smi::FromInt(type));
668}
669
670
671void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
672 v8::PropertyAttribute attribute) {
Steve Block1e0659c2011-05-24 12:43:12 +0100673 if (IsDeadCheck("v8::Template::Set()")) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000674 ENTER_V8;
675 HandleScope scope;
676 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
677 if (list->IsUndefined()) {
678 list = NeanderArray().value();
679 Utils::OpenHandle(this)->set_property_list(*list);
680 }
681 NeanderArray array(list);
682 array.add(Utils::OpenHandle(*name));
683 array.add(Utils::OpenHandle(*value));
684 array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
685}
686
687
688// --- F u n c t i o n T e m p l a t e ---
689static void InitializeFunctionTemplate(
690 i::Handle<i::FunctionTemplateInfo> info) {
691 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
692 info->set_flag(0);
693}
694
695
696Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
697 if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
698 return Local<ObjectTemplate>();
699 }
700 ENTER_V8;
701 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
702 if (result->IsUndefined()) {
703 result = Utils::OpenHandle(*ObjectTemplate::New());
704 Utils::OpenHandle(this)->set_prototype_template(*result);
705 }
706 return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
707}
708
709
710void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
711 if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
712 ENTER_V8;
713 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
714}
715
716
717// To distinguish the function templates, so that we can find them in the
718// function cache of the global context.
719static int next_serial_number = 0;
720
721
722Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
723 v8::Handle<Value> data, v8::Handle<Signature> signature) {
724 EnsureInitialized("v8::FunctionTemplate::New()");
725 LOG_API("FunctionTemplate::New");
726 ENTER_V8;
727 i::Handle<i::Struct> struct_obj =
728 i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
729 i::Handle<i::FunctionTemplateInfo> obj =
730 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
731 InitializeFunctionTemplate(obj);
732 obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
733 if (callback != 0) {
734 if (data.IsEmpty()) data = v8::Undefined();
735 Utils::ToLocal(obj)->SetCallHandler(callback, data);
736 }
737 obj->set_undetectable(false);
738 obj->set_needs_access_check(false);
739
740 if (!signature.IsEmpty())
741 obj->set_signature(*Utils::OpenHandle(*signature));
742 return Utils::ToLocal(obj);
743}
744
745
746Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
747 int argc, Handle<FunctionTemplate> argv[]) {
748 EnsureInitialized("v8::Signature::New()");
749 LOG_API("Signature::New");
750 ENTER_V8;
751 i::Handle<i::Struct> struct_obj =
752 i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
753 i::Handle<i::SignatureInfo> obj =
754 i::Handle<i::SignatureInfo>::cast(struct_obj);
755 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
756 if (argc > 0) {
757 i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
758 for (int i = 0; i < argc; i++) {
759 if (!argv[i].IsEmpty())
760 args->set(i, *Utils::OpenHandle(*argv[i]));
761 }
762 obj->set_args(*args);
763 }
764 return Utils::ToLocal(obj);
765}
766
767
768Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
769 Handle<FunctionTemplate> types[1] = { type };
770 return TypeSwitch::New(1, types);
771}
772
773
774Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
775 EnsureInitialized("v8::TypeSwitch::New()");
776 LOG_API("TypeSwitch::New");
777 ENTER_V8;
778 i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
779 for (int i = 0; i < argc; i++)
780 vector->set(i, *Utils::OpenHandle(*types[i]));
781 i::Handle<i::Struct> struct_obj =
782 i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
783 i::Handle<i::TypeSwitchInfo> obj =
784 i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
785 obj->set_types(*vector);
786 return Utils::ToLocal(obj);
787}
788
789
790int TypeSwitch::match(v8::Handle<Value> value) {
791 LOG_API("TypeSwitch::match");
792 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
793 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
794 i::FixedArray* types = i::FixedArray::cast(info->types());
795 for (int i = 0; i < types->length(); i++) {
796 if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
797 return i + 1;
798 }
799 return 0;
800}
801
802
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100803#define SET_FIELD_WRAPPED(obj, setter, cdata) do { \
804 i::Handle<i::Object> proxy = FromCData(cdata); \
805 (obj)->setter(*proxy); \
806 } while (false)
807
808
Steve Blocka7e24c12009-10-30 11:49:00 +0000809void FunctionTemplate::SetCallHandler(InvocationCallback callback,
810 v8::Handle<Value> data) {
811 if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
812 ENTER_V8;
813 HandleScope scope;
814 i::Handle<i::Struct> struct_obj =
815 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
816 i::Handle<i::CallHandlerInfo> obj =
817 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100818 SET_FIELD_WRAPPED(obj, set_callback, callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000819 if (data.IsEmpty()) data = v8::Undefined();
820 obj->set_data(*Utils::OpenHandle(*data));
821 Utils::OpenHandle(this)->set_call_code(*obj);
822}
823
824
Leon Clarkef7060e22010-06-03 12:02:55 +0100825static i::Handle<i::AccessorInfo> MakeAccessorInfo(
826 v8::Handle<String> name,
827 AccessorGetter getter,
828 AccessorSetter setter,
829 v8::Handle<Value> data,
830 v8::AccessControl settings,
831 v8::PropertyAttribute attributes) {
832 i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
833 ASSERT(getter != NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100834 SET_FIELD_WRAPPED(obj, set_getter, getter);
835 SET_FIELD_WRAPPED(obj, set_setter, setter);
Leon Clarkef7060e22010-06-03 12:02:55 +0100836 if (data.IsEmpty()) data = v8::Undefined();
837 obj->set_data(*Utils::OpenHandle(*data));
838 obj->set_name(*Utils::OpenHandle(*name));
839 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
840 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
841 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
842 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
843 return obj;
844}
845
846
Steve Blocka7e24c12009-10-30 11:49:00 +0000847void FunctionTemplate::AddInstancePropertyAccessor(
848 v8::Handle<String> name,
849 AccessorGetter getter,
850 AccessorSetter setter,
851 v8::Handle<Value> data,
852 v8::AccessControl settings,
853 v8::PropertyAttribute attributes) {
854 if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
855 return;
856 }
857 ENTER_V8;
858 HandleScope scope;
Steve Blocka7e24c12009-10-30 11:49:00 +0000859
Leon Clarkef7060e22010-06-03 12:02:55 +0100860 i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name,
861 getter, setter, data,
862 settings, attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000863 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
864 if (list->IsUndefined()) {
865 list = NeanderArray().value();
866 Utils::OpenHandle(this)->set_property_accessors(*list);
867 }
868 NeanderArray array(list);
869 array.add(obj);
870}
871
872
873Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
874 if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
875 || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
876 return Local<ObjectTemplate>();
877 ENTER_V8;
878 if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
879 Local<ObjectTemplate> templ =
880 ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
881 Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
882 }
883 i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
884 Utils::OpenHandle(this)->instance_template()));
885 return Utils::ToLocal(result);
886}
887
888
889void FunctionTemplate::SetClassName(Handle<String> name) {
890 if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
891 ENTER_V8;
892 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
893}
894
895
896void FunctionTemplate::SetHiddenPrototype(bool value) {
897 if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
898 ENTER_V8;
899 Utils::OpenHandle(this)->set_hidden_prototype(value);
900}
901
902
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100903void FunctionTemplate::SetNamedInstancePropertyHandler(
Steve Blocka7e24c12009-10-30 11:49:00 +0000904 NamedPropertyGetter getter,
905 NamedPropertySetter setter,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100906 NamedPropertyQuery query,
Steve Blocka7e24c12009-10-30 11:49:00 +0000907 NamedPropertyDeleter remover,
908 NamedPropertyEnumerator enumerator,
909 Handle<Value> data) {
910 if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
911 return;
912 }
913 ENTER_V8;
914 HandleScope scope;
915 i::Handle<i::Struct> struct_obj =
916 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
917 i::Handle<i::InterceptorInfo> obj =
918 i::Handle<i::InterceptorInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100919
920 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
921 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
922 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
923 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
924 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
925
Steve Blocka7e24c12009-10-30 11:49:00 +0000926 if (data.IsEmpty()) data = v8::Undefined();
927 obj->set_data(*Utils::OpenHandle(*data));
928 Utils::OpenHandle(this)->set_named_property_handler(*obj);
929}
930
931
932void FunctionTemplate::SetIndexedInstancePropertyHandler(
933 IndexedPropertyGetter getter,
934 IndexedPropertySetter setter,
935 IndexedPropertyQuery query,
936 IndexedPropertyDeleter remover,
937 IndexedPropertyEnumerator enumerator,
938 Handle<Value> data) {
939 if (IsDeadCheck(
940 "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
941 return;
942 }
943 ENTER_V8;
944 HandleScope scope;
945 i::Handle<i::Struct> struct_obj =
946 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
947 i::Handle<i::InterceptorInfo> obj =
948 i::Handle<i::InterceptorInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100949
950 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
951 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
952 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
953 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
954 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
955
Steve Blocka7e24c12009-10-30 11:49:00 +0000956 if (data.IsEmpty()) data = v8::Undefined();
957 obj->set_data(*Utils::OpenHandle(*data));
958 Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
959}
960
961
962void FunctionTemplate::SetInstanceCallAsFunctionHandler(
963 InvocationCallback callback,
964 Handle<Value> data) {
965 if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
966 return;
967 }
968 ENTER_V8;
969 HandleScope scope;
970 i::Handle<i::Struct> struct_obj =
971 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
972 i::Handle<i::CallHandlerInfo> obj =
973 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100974 SET_FIELD_WRAPPED(obj, set_callback, callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000975 if (data.IsEmpty()) data = v8::Undefined();
976 obj->set_data(*Utils::OpenHandle(*data));
977 Utils::OpenHandle(this)->set_instance_call_handler(*obj);
978}
979
980
981// --- O b j e c t T e m p l a t e ---
982
983
984Local<ObjectTemplate> ObjectTemplate::New() {
985 return New(Local<FunctionTemplate>());
986}
987
988
989Local<ObjectTemplate> ObjectTemplate::New(
990 v8::Handle<FunctionTemplate> constructor) {
991 if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
992 EnsureInitialized("v8::ObjectTemplate::New()");
993 LOG_API("ObjectTemplate::New");
994 ENTER_V8;
995 i::Handle<i::Struct> struct_obj =
996 i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
997 i::Handle<i::ObjectTemplateInfo> obj =
998 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
999 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
1000 if (!constructor.IsEmpty())
1001 obj->set_constructor(*Utils::OpenHandle(*constructor));
1002 obj->set_internal_field_count(i::Smi::FromInt(0));
1003 return Utils::ToLocal(obj);
1004}
1005
1006
1007// Ensure that the object template has a constructor. If no
1008// constructor is available we create one.
1009static void EnsureConstructor(ObjectTemplate* object_template) {
1010 if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
1011 Local<FunctionTemplate> templ = FunctionTemplate::New();
1012 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
1013 constructor->set_instance_template(*Utils::OpenHandle(object_template));
1014 Utils::OpenHandle(object_template)->set_constructor(*constructor);
1015 }
1016}
1017
1018
1019void ObjectTemplate::SetAccessor(v8::Handle<String> name,
1020 AccessorGetter getter,
1021 AccessorSetter setter,
1022 v8::Handle<Value> data,
1023 AccessControl settings,
1024 PropertyAttribute attribute) {
1025 if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
1026 ENTER_V8;
1027 HandleScope scope;
1028 EnsureConstructor(this);
1029 i::FunctionTemplateInfo* constructor =
1030 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1031 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1032 Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
1033 getter,
1034 setter,
1035 data,
1036 settings,
1037 attribute);
1038}
1039
1040
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001041void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
1042 NamedPropertySetter setter,
1043 NamedPropertyQuery query,
1044 NamedPropertyDeleter remover,
1045 NamedPropertyEnumerator enumerator,
1046 Handle<Value> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001047 if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
1048 ENTER_V8;
1049 HandleScope scope;
1050 EnsureConstructor(this);
1051 i::FunctionTemplateInfo* constructor =
1052 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1053 i::Handle<i::FunctionTemplateInfo> cons(constructor);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001054 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
1055 setter,
1056 query,
1057 remover,
1058 enumerator,
1059 data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001060}
1061
1062
1063void ObjectTemplate::MarkAsUndetectable() {
1064 if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
1065 ENTER_V8;
1066 HandleScope scope;
1067 EnsureConstructor(this);
1068 i::FunctionTemplateInfo* constructor =
1069 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1070 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1071 cons->set_undetectable(true);
1072}
1073
1074
1075void ObjectTemplate::SetAccessCheckCallbacks(
1076 NamedSecurityCallback named_callback,
1077 IndexedSecurityCallback indexed_callback,
1078 Handle<Value> data,
1079 bool turned_on_by_default) {
1080 if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
1081 ENTER_V8;
1082 HandleScope scope;
1083 EnsureConstructor(this);
1084
1085 i::Handle<i::Struct> struct_info =
1086 i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1087 i::Handle<i::AccessCheckInfo> info =
1088 i::Handle<i::AccessCheckInfo>::cast(struct_info);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001089
1090 SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
1091 SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
1092
Steve Blocka7e24c12009-10-30 11:49:00 +00001093 if (data.IsEmpty()) data = v8::Undefined();
1094 info->set_data(*Utils::OpenHandle(*data));
1095
1096 i::FunctionTemplateInfo* constructor =
1097 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1098 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1099 cons->set_access_check_info(*info);
1100 cons->set_needs_access_check(turned_on_by_default);
1101}
1102
1103
1104void ObjectTemplate::SetIndexedPropertyHandler(
1105 IndexedPropertyGetter getter,
1106 IndexedPropertySetter setter,
1107 IndexedPropertyQuery query,
1108 IndexedPropertyDeleter remover,
1109 IndexedPropertyEnumerator enumerator,
1110 Handle<Value> data) {
1111 if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
1112 ENTER_V8;
1113 HandleScope scope;
1114 EnsureConstructor(this);
1115 i::FunctionTemplateInfo* constructor =
1116 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1117 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1118 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
1119 setter,
1120 query,
1121 remover,
1122 enumerator,
1123 data);
1124}
1125
1126
1127void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1128 Handle<Value> data) {
1129 if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
1130 ENTER_V8;
1131 HandleScope scope;
1132 EnsureConstructor(this);
1133 i::FunctionTemplateInfo* constructor =
1134 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1135 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1136 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1137}
1138
1139
1140int ObjectTemplate::InternalFieldCount() {
1141 if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
1142 return 0;
1143 }
1144 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1145}
1146
1147
1148void ObjectTemplate::SetInternalFieldCount(int value) {
1149 if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
1150 if (!ApiCheck(i::Smi::IsValid(value),
1151 "v8::ObjectTemplate::SetInternalFieldCount()",
1152 "Invalid internal field count")) {
1153 return;
1154 }
1155 ENTER_V8;
1156 if (value > 0) {
1157 // The internal field count is set by the constructor function's
1158 // construct code, so we ensure that there is a constructor
1159 // function to do the setting.
1160 EnsureConstructor(this);
1161 }
1162 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1163}
1164
1165
1166// --- S c r i p t D a t a ---
1167
1168
1169ScriptData* ScriptData::PreCompile(const char* input, int length) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001170 i::Utf8ToUC16CharacterStream stream(
1171 reinterpret_cast<const unsigned char*>(input), length);
1172 return i::ParserApi::PreParse(&stream, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001173}
1174
1175
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001176ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
1177 i::Handle<i::String> str = Utils::OpenHandle(*source);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001178 if (str->IsExternalTwoByteString()) {
1179 i::ExternalTwoByteStringUC16CharacterStream stream(
1180 i::Handle<i::ExternalTwoByteString>::cast(str), 0, str->length());
1181 return i::ParserApi::PreParse(&stream, NULL);
1182 } else {
1183 i::GenericStringUC16CharacterStream stream(str, 0, str->length());
1184 return i::ParserApi::PreParse(&stream, NULL);
1185 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001186}
1187
1188
Leon Clarkef7060e22010-06-03 12:02:55 +01001189ScriptData* ScriptData::New(const char* data, int length) {
1190 // Return an empty ScriptData if the length is obviously invalid.
1191 if (length % sizeof(unsigned) != 0) {
Iain Merrick9ac36c92010-09-13 15:29:50 +01001192 return new i::ScriptDataImpl();
Leon Clarkef7060e22010-06-03 12:02:55 +01001193 }
1194
1195 // Copy the data to ensure it is properly aligned.
1196 int deserialized_data_length = length / sizeof(unsigned);
Iain Merrick9ac36c92010-09-13 15:29:50 +01001197 // If aligned, don't create a copy of the data.
1198 if (reinterpret_cast<intptr_t>(data) % sizeof(unsigned) == 0) {
1199 return new i::ScriptDataImpl(data, length);
1200 }
1201 // Copy the data to align it.
Leon Clarkef7060e22010-06-03 12:02:55 +01001202 unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
Iain Merrick9ac36c92010-09-13 15:29:50 +01001203 i::MemCopy(deserialized_data, data, length);
Leon Clarkef7060e22010-06-03 12:02:55 +01001204
1205 return new i::ScriptDataImpl(
1206 i::Vector<unsigned>(deserialized_data, deserialized_data_length));
Steve Blocka7e24c12009-10-30 11:49:00 +00001207}
1208
1209
1210// --- S c r i p t ---
1211
1212
1213Local<Script> Script::New(v8::Handle<String> source,
1214 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001215 v8::ScriptData* pre_data,
1216 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001217 ON_BAILOUT("v8::Script::New()", return Local<Script>());
1218 LOG_API("Script::New");
1219 ENTER_V8;
1220 i::Handle<i::String> str = Utils::OpenHandle(*source);
1221 i::Handle<i::Object> name_obj;
1222 int line_offset = 0;
1223 int column_offset = 0;
1224 if (origin != NULL) {
1225 if (!origin->ResourceName().IsEmpty()) {
1226 name_obj = Utils::OpenHandle(*origin->ResourceName());
1227 }
1228 if (!origin->ResourceLineOffset().IsEmpty()) {
1229 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1230 }
1231 if (!origin->ResourceColumnOffset().IsEmpty()) {
1232 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1233 }
1234 }
1235 EXCEPTION_PREAMBLE();
Andrei Popescu402d9372010-02-26 13:31:12 +00001236 i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001237 // We assert that the pre-data is sane, even though we can actually
1238 // handle it if it turns out not to be in release mode.
Andrei Popescu402d9372010-02-26 13:31:12 +00001239 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
Steve Blocka7e24c12009-10-30 11:49:00 +00001240 // If the pre-data isn't sane we simply ignore it
Andrei Popescu402d9372010-02-26 13:31:12 +00001241 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
1242 pre_data_impl = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001243 }
Steve Block6ded16b2010-05-10 14:33:55 +01001244 i::Handle<i::SharedFunctionInfo> result =
Andrei Popescu31002712010-02-23 13:46:05 +00001245 i::Compiler::Compile(str,
1246 name_obj,
1247 line_offset,
1248 column_offset,
1249 NULL,
Andrei Popescu402d9372010-02-26 13:31:12 +00001250 pre_data_impl,
1251 Utils::OpenHandle(*script_data),
Andrei Popescu31002712010-02-23 13:46:05 +00001252 i::NOT_NATIVES_CODE);
Steve Block6ded16b2010-05-10 14:33:55 +01001253 has_pending_exception = result.is_null();
Steve Blocka7e24c12009-10-30 11:49:00 +00001254 EXCEPTION_BAILOUT_CHECK(Local<Script>());
Steve Block6ded16b2010-05-10 14:33:55 +01001255 return Local<Script>(ToApi<Script>(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00001256}
1257
1258
1259Local<Script> Script::New(v8::Handle<String> source,
1260 v8::Handle<Value> file_name) {
1261 ScriptOrigin origin(file_name);
1262 return New(source, &origin);
1263}
1264
1265
1266Local<Script> Script::Compile(v8::Handle<String> source,
1267 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001268 v8::ScriptData* pre_data,
1269 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001270 ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1271 LOG_API("Script::Compile");
1272 ENTER_V8;
Andrei Popescu402d9372010-02-26 13:31:12 +00001273 Local<Script> generic = New(source, origin, pre_data, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001274 if (generic.IsEmpty())
1275 return generic;
Steve Block6ded16b2010-05-10 14:33:55 +01001276 i::Handle<i::Object> obj = Utils::OpenHandle(*generic);
1277 i::Handle<i::SharedFunctionInfo> function =
1278 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001279 i::Handle<i::JSFunction> result =
Steve Block6ded16b2010-05-10 14:33:55 +01001280 i::Factory::NewFunctionFromSharedFunctionInfo(function,
1281 i::Top::global_context());
Steve Blocka7e24c12009-10-30 11:49:00 +00001282 return Local<Script>(ToApi<Script>(result));
1283}
1284
1285
1286Local<Script> Script::Compile(v8::Handle<String> source,
Andrei Popescu402d9372010-02-26 13:31:12 +00001287 v8::Handle<Value> file_name,
1288 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001289 ScriptOrigin origin(file_name);
Andrei Popescu402d9372010-02-26 13:31:12 +00001290 return Compile(source, &origin, 0, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001291}
1292
1293
1294Local<Value> Script::Run() {
1295 ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1296 LOG_API("Script::Run");
1297 ENTER_V8;
1298 i::Object* raw_result = NULL;
1299 {
1300 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001301 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1302 i::Handle<i::JSFunction> fun;
1303 if (obj->IsSharedFunctionInfo()) {
1304 i::Handle<i::SharedFunctionInfo>
1305 function_info(i::SharedFunctionInfo::cast(*obj));
1306 fun = i::Factory::NewFunctionFromSharedFunctionInfo(
1307 function_info, i::Top::global_context());
1308 } else {
1309 fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001310 }
1311 EXCEPTION_PREAMBLE();
1312 i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
1313 i::Handle<i::Object> result =
1314 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
1315 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1316 raw_result = *result;
1317 }
1318 i::Handle<i::Object> result(raw_result);
1319 return Utils::ToLocal(result);
1320}
1321
1322
Steve Block6ded16b2010-05-10 14:33:55 +01001323static i::Handle<i::SharedFunctionInfo> OpenScript(Script* script) {
1324 i::Handle<i::Object> obj = Utils::OpenHandle(script);
1325 i::Handle<i::SharedFunctionInfo> result;
1326 if (obj->IsSharedFunctionInfo()) {
1327 result =
1328 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
1329 } else {
1330 result =
1331 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared());
1332 }
1333 return result;
1334}
1335
1336
Steve Blocka7e24c12009-10-30 11:49:00 +00001337Local<Value> Script::Id() {
1338 ON_BAILOUT("v8::Script::Id()", return Local<Value>());
1339 LOG_API("Script::Id");
1340 i::Object* raw_id = NULL;
1341 {
1342 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001343 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1344 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001345 i::Handle<i::Object> id(script->id());
1346 raw_id = *id;
1347 }
1348 i::Handle<i::Object> id(raw_id);
1349 return Utils::ToLocal(id);
1350}
1351
1352
Steve Blockd0582a62009-12-15 09:54:21 +00001353void Script::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001354 ON_BAILOUT("v8::Script::SetData()", return);
1355 LOG_API("Script::SetData");
1356 {
1357 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001358 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001359 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
Steve Block6ded16b2010-05-10 14:33:55 +01001360 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001361 script->set_data(*raw_data);
1362 }
1363}
1364
1365
1366// --- E x c e p t i o n s ---
1367
1368
1369v8::TryCatch::TryCatch()
Steve Blockd0582a62009-12-15 09:54:21 +00001370 : next_(i::Top::try_catch_handler_address()),
Steve Blocka7e24c12009-10-30 11:49:00 +00001371 exception_(i::Heap::the_hole_value()),
1372 message_(i::Smi::FromInt(0)),
1373 is_verbose_(false),
1374 can_continue_(true),
1375 capture_message_(true),
Steve Blockd0582a62009-12-15 09:54:21 +00001376 rethrow_(false) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001377 i::Top::RegisterTryCatchHandler(this);
1378}
1379
1380
1381v8::TryCatch::~TryCatch() {
Steve Blockd0582a62009-12-15 09:54:21 +00001382 if (rethrow_) {
1383 v8::HandleScope scope;
1384 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
1385 i::Top::UnregisterTryCatchHandler(this);
1386 v8::ThrowException(exc);
1387 } else {
1388 i::Top::UnregisterTryCatchHandler(this);
1389 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001390}
1391
1392
1393bool v8::TryCatch::HasCaught() const {
1394 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1395}
1396
1397
1398bool v8::TryCatch::CanContinue() const {
1399 return can_continue_;
1400}
1401
1402
Steve Blockd0582a62009-12-15 09:54:21 +00001403v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1404 if (!HasCaught()) return v8::Local<v8::Value>();
1405 rethrow_ = true;
1406 return v8::Undefined();
1407}
1408
1409
Steve Blocka7e24c12009-10-30 11:49:00 +00001410v8::Local<Value> v8::TryCatch::Exception() const {
1411 if (HasCaught()) {
1412 // Check for out of memory exception.
1413 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1414 return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1415 } else {
1416 return v8::Local<Value>();
1417 }
1418}
1419
1420
1421v8::Local<Value> v8::TryCatch::StackTrace() const {
1422 if (HasCaught()) {
1423 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1424 if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1425 v8::HandleScope scope;
1426 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
1427 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
1428 if (!obj->HasProperty(*name))
1429 return v8::Local<Value>();
1430 return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
1431 } else {
1432 return v8::Local<Value>();
1433 }
1434}
1435
1436
1437v8::Local<v8::Message> v8::TryCatch::Message() const {
1438 if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1439 i::Object* message = reinterpret_cast<i::Object*>(message_);
1440 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1441 } else {
1442 return v8::Local<v8::Message>();
1443 }
1444}
1445
1446
1447void v8::TryCatch::Reset() {
1448 exception_ = i::Heap::the_hole_value();
1449 message_ = i::Smi::FromInt(0);
1450}
1451
1452
1453void v8::TryCatch::SetVerbose(bool value) {
1454 is_verbose_ = value;
1455}
1456
1457
1458void v8::TryCatch::SetCaptureMessage(bool value) {
1459 capture_message_ = value;
1460}
1461
1462
1463// --- M e s s a g e ---
1464
1465
1466Local<String> Message::Get() const {
1467 ON_BAILOUT("v8::Message::Get()", return Local<String>());
1468 ENTER_V8;
1469 HandleScope scope;
1470 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1471 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1472 Local<String> result = Utils::ToLocal(raw_result);
1473 return scope.Close(result);
1474}
1475
1476
1477v8::Handle<Value> Message::GetScriptResourceName() const {
1478 if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1479 return Local<String>();
1480 }
1481 ENTER_V8;
1482 HandleScope scope;
Steve Block1e0659c2011-05-24 12:43:12 +01001483 i::Handle<i::JSMessageObject> message =
1484 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
Steve Blocka7e24c12009-10-30 11:49:00 +00001485 // Return this.script.name.
1486 i::Handle<i::JSValue> script =
Steve Block1e0659c2011-05-24 12:43:12 +01001487 i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001488 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
1489 return scope.Close(Utils::ToLocal(resource_name));
1490}
1491
1492
1493v8::Handle<Value> Message::GetScriptData() const {
1494 if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
1495 return Local<Value>();
1496 }
1497 ENTER_V8;
1498 HandleScope scope;
Steve Block1e0659c2011-05-24 12:43:12 +01001499 i::Handle<i::JSMessageObject> message =
1500 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
Steve Blocka7e24c12009-10-30 11:49:00 +00001501 // Return this.script.data.
1502 i::Handle<i::JSValue> script =
Steve Block1e0659c2011-05-24 12:43:12 +01001503 i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001504 i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1505 return scope.Close(Utils::ToLocal(data));
1506}
1507
1508
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001509v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
1510 if (IsDeadCheck("v8::Message::GetStackTrace()")) {
1511 return Local<v8::StackTrace>();
1512 }
1513 ENTER_V8;
1514 HandleScope scope;
Steve Block1e0659c2011-05-24 12:43:12 +01001515 i::Handle<i::JSMessageObject> message =
1516 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
1517 i::Handle<i::Object> stackFramesObj(message->stack_frames());
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001518 if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
1519 i::Handle<i::JSArray> stackTrace =
1520 i::Handle<i::JSArray>::cast(stackFramesObj);
1521 return scope.Close(Utils::StackTraceToLocal(stackTrace));
1522}
1523
1524
Steve Blocka7e24c12009-10-30 11:49:00 +00001525static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1526 i::Handle<i::Object> recv,
1527 int argc,
1528 i::Object** argv[],
1529 bool* has_pending_exception) {
1530 i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
John Reck59135872010-11-02 12:39:01 -07001531 i::Object* object_fun =
1532 i::Top::builtins()->GetPropertyNoExceptionThrown(*fmt_str);
Steve Blocka7e24c12009-10-30 11:49:00 +00001533 i::Handle<i::JSFunction> fun =
1534 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1535 i::Handle<i::Object> value =
1536 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1537 return value;
1538}
1539
1540
1541static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1542 i::Handle<i::Object> data,
1543 bool* has_pending_exception) {
1544 i::Object** argv[1] = { data.location() };
1545 return CallV8HeapFunction(name,
1546 i::Top::builtins(),
1547 1,
1548 argv,
1549 has_pending_exception);
1550}
1551
1552
1553int Message::GetLineNumber() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001554 ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001555 ENTER_V8;
1556 HandleScope scope;
Steve Block1e0659c2011-05-24 12:43:12 +01001557
Steve Blocka7e24c12009-10-30 11:49:00 +00001558 EXCEPTION_PREAMBLE();
1559 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1560 Utils::OpenHandle(this),
1561 &has_pending_exception);
1562 EXCEPTION_BAILOUT_CHECK(0);
1563 return static_cast<int>(result->Number());
1564}
1565
1566
1567int Message::GetStartPosition() const {
1568 if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1569 ENTER_V8;
1570 HandleScope scope;
Steve Block1e0659c2011-05-24 12:43:12 +01001571 i::Handle<i::JSMessageObject> message =
1572 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
1573 return message->start_position();
Steve Blocka7e24c12009-10-30 11:49:00 +00001574}
1575
1576
1577int Message::GetEndPosition() const {
1578 if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1579 ENTER_V8;
1580 HandleScope scope;
Steve Block1e0659c2011-05-24 12:43:12 +01001581 i::Handle<i::JSMessageObject> message =
1582 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
1583 return message->end_position();
Steve Blocka7e24c12009-10-30 11:49:00 +00001584}
1585
1586
1587int Message::GetStartColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001588 if (IsDeadCheck("v8::Message::GetStartColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001589 ENTER_V8;
1590 HandleScope scope;
1591 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1592 EXCEPTION_PREAMBLE();
1593 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1594 "GetPositionInLine",
1595 data_obj,
1596 &has_pending_exception);
1597 EXCEPTION_BAILOUT_CHECK(0);
1598 return static_cast<int>(start_col_obj->Number());
1599}
1600
1601
1602int Message::GetEndColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001603 if (IsDeadCheck("v8::Message::GetEndColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001604 ENTER_V8;
1605 HandleScope scope;
1606 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1607 EXCEPTION_PREAMBLE();
1608 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1609 "GetPositionInLine",
1610 data_obj,
1611 &has_pending_exception);
1612 EXCEPTION_BAILOUT_CHECK(0);
Steve Block1e0659c2011-05-24 12:43:12 +01001613 i::Handle<i::JSMessageObject> message =
1614 i::Handle<i::JSMessageObject>::cast(data_obj);
1615 int start = message->start_position();
1616 int end = message->end_position();
Steve Blocka7e24c12009-10-30 11:49:00 +00001617 return static_cast<int>(start_col_obj->Number()) + (end - start);
1618}
1619
1620
1621Local<String> Message::GetSourceLine() const {
1622 ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
1623 ENTER_V8;
1624 HandleScope scope;
1625 EXCEPTION_PREAMBLE();
1626 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1627 Utils::OpenHandle(this),
1628 &has_pending_exception);
1629 EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1630 if (result->IsString()) {
1631 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1632 } else {
1633 return Local<String>();
1634 }
1635}
1636
1637
1638void Message::PrintCurrentStackTrace(FILE* out) {
1639 if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1640 ENTER_V8;
1641 i::Top::PrintCurrentStackTrace(out);
1642}
1643
1644
Kristian Monsen25f61362010-05-21 11:50:48 +01001645// --- S t a c k T r a c e ---
1646
1647Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
1648 if (IsDeadCheck("v8::StackTrace::GetFrame()")) return Local<StackFrame>();
1649 ENTER_V8;
1650 HandleScope scope;
1651 i::Handle<i::JSArray> self = Utils::OpenHandle(this);
John Reck59135872010-11-02 12:39:01 -07001652 i::Object* raw_object = self->GetElementNoExceptionThrown(index);
1653 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_object));
Kristian Monsen25f61362010-05-21 11:50:48 +01001654 return scope.Close(Utils::StackFrameToLocal(obj));
1655}
1656
1657
1658int StackTrace::GetFrameCount() const {
1659 if (IsDeadCheck("v8::StackTrace::GetFrameCount()")) return -1;
1660 ENTER_V8;
1661 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
1662}
1663
1664
1665Local<Array> StackTrace::AsArray() {
1666 if (IsDeadCheck("v8::StackTrace::AsArray()")) Local<Array>();
1667 ENTER_V8;
1668 return Utils::ToLocal(Utils::OpenHandle(this));
1669}
1670
1671
1672Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
1673 StackTraceOptions options) {
1674 if (IsDeadCheck("v8::StackTrace::CurrentStackTrace()")) Local<StackTrace>();
1675 ENTER_V8;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001676 i::Handle<i::JSArray> stackTrace =
1677 i::Top::CaptureCurrentStackTrace(frame_limit, options);
1678 return Utils::StackTraceToLocal(stackTrace);
Kristian Monsen25f61362010-05-21 11:50:48 +01001679}
1680
1681
1682// --- S t a c k F r a m e ---
1683
1684int StackFrame::GetLineNumber() const {
1685 if (IsDeadCheck("v8::StackFrame::GetLineNumber()")) {
1686 return Message::kNoLineNumberInfo;
1687 }
1688 ENTER_V8;
1689 i::HandleScope scope;
1690 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1691 i::Handle<i::Object> line = GetProperty(self, "lineNumber");
1692 if (!line->IsSmi()) {
1693 return Message::kNoLineNumberInfo;
1694 }
1695 return i::Smi::cast(*line)->value();
1696}
1697
1698
1699int StackFrame::GetColumn() const {
1700 if (IsDeadCheck("v8::StackFrame::GetColumn()")) {
1701 return Message::kNoColumnInfo;
1702 }
1703 ENTER_V8;
1704 i::HandleScope scope;
1705 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1706 i::Handle<i::Object> column = GetProperty(self, "column");
1707 if (!column->IsSmi()) {
1708 return Message::kNoColumnInfo;
1709 }
1710 return i::Smi::cast(*column)->value();
1711}
1712
1713
1714Local<String> StackFrame::GetScriptName() const {
1715 if (IsDeadCheck("v8::StackFrame::GetScriptName()")) return Local<String>();
1716 ENTER_V8;
1717 HandleScope scope;
1718 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1719 i::Handle<i::Object> name = GetProperty(self, "scriptName");
1720 if (!name->IsString()) {
1721 return Local<String>();
1722 }
1723 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1724}
1725
1726
Ben Murdochf87a2032010-10-22 12:50:53 +01001727Local<String> StackFrame::GetScriptNameOrSourceURL() const {
1728 if (IsDeadCheck("v8::StackFrame::GetScriptNameOrSourceURL()")) {
1729 return Local<String>();
1730 }
1731 ENTER_V8;
1732 HandleScope scope;
1733 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1734 i::Handle<i::Object> name = GetProperty(self, "scriptNameOrSourceURL");
1735 if (!name->IsString()) {
1736 return Local<String>();
1737 }
1738 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1739}
1740
1741
Kristian Monsen25f61362010-05-21 11:50:48 +01001742Local<String> StackFrame::GetFunctionName() const {
1743 if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
1744 ENTER_V8;
1745 HandleScope scope;
1746 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1747 i::Handle<i::Object> name = GetProperty(self, "functionName");
1748 if (!name->IsString()) {
1749 return Local<String>();
1750 }
1751 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1752}
1753
1754
1755bool StackFrame::IsEval() const {
1756 if (IsDeadCheck("v8::StackFrame::IsEval()")) return false;
1757 ENTER_V8;
1758 i::HandleScope scope;
1759 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1760 i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
1761 return is_eval->IsTrue();
1762}
1763
1764
1765bool StackFrame::IsConstructor() const {
1766 if (IsDeadCheck("v8::StackFrame::IsConstructor()")) return false;
1767 ENTER_V8;
1768 i::HandleScope scope;
1769 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1770 i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
1771 return is_constructor->IsTrue();
1772}
1773
1774
Steve Blocka7e24c12009-10-30 11:49:00 +00001775// --- D a t a ---
1776
1777bool Value::IsUndefined() const {
1778 if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1779 return Utils::OpenHandle(this)->IsUndefined();
1780}
1781
1782
1783bool Value::IsNull() const {
1784 if (IsDeadCheck("v8::Value::IsNull()")) return false;
1785 return Utils::OpenHandle(this)->IsNull();
1786}
1787
1788
1789bool Value::IsTrue() const {
1790 if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1791 return Utils::OpenHandle(this)->IsTrue();
1792}
1793
1794
1795bool Value::IsFalse() const {
1796 if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1797 return Utils::OpenHandle(this)->IsFalse();
1798}
1799
1800
1801bool Value::IsFunction() const {
1802 if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1803 return Utils::OpenHandle(this)->IsJSFunction();
1804}
1805
1806
1807bool Value::FullIsString() const {
1808 if (IsDeadCheck("v8::Value::IsString()")) return false;
1809 bool result = Utils::OpenHandle(this)->IsString();
1810 ASSERT_EQ(result, QuickIsString());
1811 return result;
1812}
1813
1814
1815bool Value::IsArray() const {
1816 if (IsDeadCheck("v8::Value::IsArray()")) return false;
1817 return Utils::OpenHandle(this)->IsJSArray();
1818}
1819
1820
1821bool Value::IsObject() const {
1822 if (IsDeadCheck("v8::Value::IsObject()")) return false;
1823 return Utils::OpenHandle(this)->IsJSObject();
1824}
1825
1826
1827bool Value::IsNumber() const {
1828 if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1829 return Utils::OpenHandle(this)->IsNumber();
1830}
1831
1832
1833bool Value::IsBoolean() const {
1834 if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1835 return Utils::OpenHandle(this)->IsBoolean();
1836}
1837
1838
1839bool Value::IsExternal() const {
1840 if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1841 return Utils::OpenHandle(this)->IsProxy();
1842}
1843
1844
1845bool Value::IsInt32() const {
1846 if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1847 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1848 if (obj->IsSmi()) return true;
1849 if (obj->IsNumber()) {
1850 double value = obj->Number();
1851 return i::FastI2D(i::FastD2I(value)) == value;
1852 }
1853 return false;
1854}
1855
1856
Steve Block6ded16b2010-05-10 14:33:55 +01001857bool Value::IsUint32() const {
1858 if (IsDeadCheck("v8::Value::IsUint32()")) return false;
1859 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1860 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
1861 if (obj->IsNumber()) {
1862 double value = obj->Number();
1863 return i::FastUI2D(i::FastD2UI(value)) == value;
1864 }
1865 return false;
1866}
1867
1868
Steve Blocka7e24c12009-10-30 11:49:00 +00001869bool Value::IsDate() const {
1870 if (IsDeadCheck("v8::Value::IsDate()")) return false;
1871 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1872 return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1873}
1874
1875
Iain Merrick75681382010-08-19 15:07:18 +01001876bool Value::IsRegExp() const {
1877 if (IsDeadCheck("v8::Value::IsRegExp()")) return false;
1878 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1879 return obj->IsJSRegExp();
1880}
1881
1882
Steve Blocka7e24c12009-10-30 11:49:00 +00001883Local<String> Value::ToString() const {
1884 if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1885 LOG_API("ToString");
1886 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1887 i::Handle<i::Object> str;
1888 if (obj->IsString()) {
1889 str = obj;
1890 } else {
1891 ENTER_V8;
1892 EXCEPTION_PREAMBLE();
1893 str = i::Execution::ToString(obj, &has_pending_exception);
1894 EXCEPTION_BAILOUT_CHECK(Local<String>());
1895 }
1896 return Local<String>(ToApi<String>(str));
1897}
1898
1899
1900Local<String> Value::ToDetailString() const {
1901 if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1902 LOG_API("ToDetailString");
1903 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1904 i::Handle<i::Object> str;
1905 if (obj->IsString()) {
1906 str = obj;
1907 } else {
1908 ENTER_V8;
1909 EXCEPTION_PREAMBLE();
1910 str = i::Execution::ToDetailString(obj, &has_pending_exception);
1911 EXCEPTION_BAILOUT_CHECK(Local<String>());
1912 }
1913 return Local<String>(ToApi<String>(str));
1914}
1915
1916
1917Local<v8::Object> Value::ToObject() const {
1918 if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1919 LOG_API("ToObject");
1920 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1921 i::Handle<i::Object> val;
1922 if (obj->IsJSObject()) {
1923 val = obj;
1924 } else {
1925 ENTER_V8;
1926 EXCEPTION_PREAMBLE();
1927 val = i::Execution::ToObject(obj, &has_pending_exception);
1928 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1929 }
1930 return Local<v8::Object>(ToApi<Object>(val));
1931}
1932
1933
1934Local<Boolean> Value::ToBoolean() const {
1935 if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1936 LOG_API("ToBoolean");
1937 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1938 if (obj->IsBoolean()) {
1939 return Local<Boolean>(ToApi<Boolean>(obj));
1940 } else {
1941 ENTER_V8;
1942 i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1943 return Local<Boolean>(ToApi<Boolean>(val));
1944 }
1945}
1946
1947
1948Local<Number> Value::ToNumber() const {
1949 if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1950 LOG_API("ToNumber");
1951 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1952 i::Handle<i::Object> num;
1953 if (obj->IsNumber()) {
1954 num = obj;
1955 } else {
1956 ENTER_V8;
1957 EXCEPTION_PREAMBLE();
1958 num = i::Execution::ToNumber(obj, &has_pending_exception);
1959 EXCEPTION_BAILOUT_CHECK(Local<Number>());
1960 }
1961 return Local<Number>(ToApi<Number>(num));
1962}
1963
1964
1965Local<Integer> Value::ToInteger() const {
1966 if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1967 LOG_API("ToInteger");
1968 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1969 i::Handle<i::Object> num;
1970 if (obj->IsSmi()) {
1971 num = obj;
1972 } else {
1973 ENTER_V8;
1974 EXCEPTION_PREAMBLE();
1975 num = i::Execution::ToInteger(obj, &has_pending_exception);
1976 EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1977 }
1978 return Local<Integer>(ToApi<Integer>(num));
1979}
1980
1981
1982void External::CheckCast(v8::Value* that) {
1983 if (IsDeadCheck("v8::External::Cast()")) return;
1984 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1985 ApiCheck(obj->IsProxy(),
1986 "v8::External::Cast()",
1987 "Could not convert to external");
1988}
1989
1990
1991void v8::Object::CheckCast(Value* that) {
1992 if (IsDeadCheck("v8::Object::Cast()")) return;
1993 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1994 ApiCheck(obj->IsJSObject(),
1995 "v8::Object::Cast()",
1996 "Could not convert to object");
1997}
1998
1999
2000void v8::Function::CheckCast(Value* that) {
2001 if (IsDeadCheck("v8::Function::Cast()")) return;
2002 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2003 ApiCheck(obj->IsJSFunction(),
2004 "v8::Function::Cast()",
2005 "Could not convert to function");
2006}
2007
2008
2009void v8::String::CheckCast(v8::Value* that) {
2010 if (IsDeadCheck("v8::String::Cast()")) return;
2011 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2012 ApiCheck(obj->IsString(),
2013 "v8::String::Cast()",
2014 "Could not convert to string");
2015}
2016
2017
2018void v8::Number::CheckCast(v8::Value* that) {
2019 if (IsDeadCheck("v8::Number::Cast()")) return;
2020 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2021 ApiCheck(obj->IsNumber(),
2022 "v8::Number::Cast()",
2023 "Could not convert to number");
2024}
2025
2026
2027void v8::Integer::CheckCast(v8::Value* that) {
2028 if (IsDeadCheck("v8::Integer::Cast()")) return;
2029 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2030 ApiCheck(obj->IsNumber(),
2031 "v8::Integer::Cast()",
2032 "Could not convert to number");
2033}
2034
2035
2036void v8::Array::CheckCast(Value* that) {
2037 if (IsDeadCheck("v8::Array::Cast()")) return;
2038 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2039 ApiCheck(obj->IsJSArray(),
2040 "v8::Array::Cast()",
2041 "Could not convert to array");
2042}
2043
2044
2045void v8::Date::CheckCast(v8::Value* that) {
2046 if (IsDeadCheck("v8::Date::Cast()")) return;
2047 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2048 ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
2049 "v8::Date::Cast()",
2050 "Could not convert to date");
2051}
2052
2053
Ben Murdochf87a2032010-10-22 12:50:53 +01002054void v8::RegExp::CheckCast(v8::Value* that) {
2055 if (IsDeadCheck("v8::RegExp::Cast()")) return;
2056 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2057 ApiCheck(obj->IsJSRegExp(),
2058 "v8::RegExp::Cast()",
2059 "Could not convert to regular expression");
2060}
2061
2062
Steve Blocka7e24c12009-10-30 11:49:00 +00002063bool Value::BooleanValue() const {
2064 if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
2065 LOG_API("BooleanValue");
2066 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2067 if (obj->IsBoolean()) {
2068 return obj->IsTrue();
2069 } else {
2070 ENTER_V8;
2071 i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
2072 return value->IsTrue();
2073 }
2074}
2075
2076
2077double Value::NumberValue() const {
2078 if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
2079 LOG_API("NumberValue");
2080 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2081 i::Handle<i::Object> num;
2082 if (obj->IsNumber()) {
2083 num = obj;
2084 } else {
2085 ENTER_V8;
2086 EXCEPTION_PREAMBLE();
2087 num = i::Execution::ToNumber(obj, &has_pending_exception);
2088 EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
2089 }
2090 return num->Number();
2091}
2092
2093
2094int64_t Value::IntegerValue() const {
2095 if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
2096 LOG_API("IntegerValue");
2097 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2098 i::Handle<i::Object> num;
2099 if (obj->IsNumber()) {
2100 num = obj;
2101 } else {
2102 ENTER_V8;
2103 EXCEPTION_PREAMBLE();
2104 num = i::Execution::ToInteger(obj, &has_pending_exception);
2105 EXCEPTION_BAILOUT_CHECK(0);
2106 }
2107 if (num->IsSmi()) {
2108 return i::Smi::cast(*num)->value();
2109 } else {
2110 return static_cast<int64_t>(num->Number());
2111 }
2112}
2113
2114
2115Local<Int32> Value::ToInt32() const {
2116 if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
2117 LOG_API("ToInt32");
2118 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2119 i::Handle<i::Object> num;
2120 if (obj->IsSmi()) {
2121 num = obj;
2122 } else {
2123 ENTER_V8;
2124 EXCEPTION_PREAMBLE();
2125 num = i::Execution::ToInt32(obj, &has_pending_exception);
2126 EXCEPTION_BAILOUT_CHECK(Local<Int32>());
2127 }
2128 return Local<Int32>(ToApi<Int32>(num));
2129}
2130
2131
2132Local<Uint32> Value::ToUint32() const {
2133 if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
2134 LOG_API("ToUInt32");
2135 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2136 i::Handle<i::Object> num;
2137 if (obj->IsSmi()) {
2138 num = obj;
2139 } else {
2140 ENTER_V8;
2141 EXCEPTION_PREAMBLE();
2142 num = i::Execution::ToUint32(obj, &has_pending_exception);
2143 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2144 }
2145 return Local<Uint32>(ToApi<Uint32>(num));
2146}
2147
2148
2149Local<Uint32> Value::ToArrayIndex() const {
2150 if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
2151 LOG_API("ToArrayIndex");
2152 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2153 if (obj->IsSmi()) {
2154 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2155 return Local<Uint32>();
2156 }
2157 ENTER_V8;
2158 EXCEPTION_PREAMBLE();
2159 i::Handle<i::Object> string_obj =
2160 i::Execution::ToString(obj, &has_pending_exception);
2161 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2162 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2163 uint32_t index;
2164 if (str->AsArrayIndex(&index)) {
2165 i::Handle<i::Object> value;
2166 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2167 value = i::Handle<i::Object>(i::Smi::FromInt(index));
2168 } else {
2169 value = i::Factory::NewNumber(index);
2170 }
2171 return Utils::Uint32ToLocal(value);
2172 }
2173 return Local<Uint32>();
2174}
2175
2176
2177int32_t Value::Int32Value() const {
2178 if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
2179 LOG_API("Int32Value");
2180 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2181 if (obj->IsSmi()) {
2182 return i::Smi::cast(*obj)->value();
2183 } else {
2184 LOG_API("Int32Value (slow)");
2185 ENTER_V8;
2186 EXCEPTION_PREAMBLE();
2187 i::Handle<i::Object> num =
2188 i::Execution::ToInt32(obj, &has_pending_exception);
2189 EXCEPTION_BAILOUT_CHECK(0);
2190 if (num->IsSmi()) {
2191 return i::Smi::cast(*num)->value();
2192 } else {
2193 return static_cast<int32_t>(num->Number());
2194 }
2195 }
2196}
2197
2198
2199bool Value::Equals(Handle<Value> that) const {
2200 if (IsDeadCheck("v8::Value::Equals()")
2201 || EmptyCheck("v8::Value::Equals()", this)
2202 || EmptyCheck("v8::Value::Equals()", that)) {
2203 return false;
2204 }
2205 LOG_API("Equals");
2206 ENTER_V8;
2207 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2208 i::Handle<i::Object> other = Utils::OpenHandle(*that);
Steve Block1e0659c2011-05-24 12:43:12 +01002209 // If both obj and other are JSObjects, we'd better compare by identity
2210 // immediately when going into JS builtin. The reason is Invoke
2211 // would overwrite global object receiver with global proxy.
2212 if (obj->IsJSObject() && other->IsJSObject()) {
2213 return *obj == *other;
2214 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002215 i::Object** args[1] = { other.location() };
2216 EXCEPTION_PREAMBLE();
2217 i::Handle<i::Object> result =
2218 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
2219 EXCEPTION_BAILOUT_CHECK(false);
2220 return *result == i::Smi::FromInt(i::EQUAL);
2221}
2222
2223
2224bool Value::StrictEquals(Handle<Value> that) const {
2225 if (IsDeadCheck("v8::Value::StrictEquals()")
2226 || EmptyCheck("v8::Value::StrictEquals()", this)
2227 || EmptyCheck("v8::Value::StrictEquals()", that)) {
2228 return false;
2229 }
2230 LOG_API("StrictEquals");
2231 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2232 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2233 // Must check HeapNumber first, since NaN !== NaN.
2234 if (obj->IsHeapNumber()) {
2235 if (!other->IsNumber()) return false;
2236 double x = obj->Number();
2237 double y = other->Number();
2238 // Must check explicitly for NaN:s on Windows, but -0 works fine.
2239 return x == y && !isnan(x) && !isnan(y);
2240 } else if (*obj == *other) { // Also covers Booleans.
2241 return true;
2242 } else if (obj->IsSmi()) {
2243 return other->IsNumber() && obj->Number() == other->Number();
2244 } else if (obj->IsString()) {
2245 return other->IsString() &&
2246 i::String::cast(*obj)->Equals(i::String::cast(*other));
2247 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2248 return other->IsUndefined() || other->IsUndetectableObject();
2249 } else {
2250 return false;
2251 }
2252}
2253
2254
2255uint32_t Value::Uint32Value() const {
2256 if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
2257 LOG_API("Uint32Value");
2258 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2259 if (obj->IsSmi()) {
2260 return i::Smi::cast(*obj)->value();
2261 } else {
2262 ENTER_V8;
2263 EXCEPTION_PREAMBLE();
2264 i::Handle<i::Object> num =
2265 i::Execution::ToUint32(obj, &has_pending_exception);
2266 EXCEPTION_BAILOUT_CHECK(0);
2267 if (num->IsSmi()) {
2268 return i::Smi::cast(*num)->value();
2269 } else {
2270 return static_cast<uint32_t>(num->Number());
2271 }
2272 }
2273}
2274
2275
2276bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
2277 v8::PropertyAttribute attribs) {
2278 ON_BAILOUT("v8::Object::Set()", return false);
2279 ENTER_V8;
2280 HandleScope scope;
2281 i::Handle<i::Object> self = Utils::OpenHandle(this);
2282 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2283 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2284 EXCEPTION_PREAMBLE();
2285 i::Handle<i::Object> obj = i::SetProperty(
2286 self,
2287 key_obj,
2288 value_obj,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002289 static_cast<PropertyAttributes>(attribs),
2290 i::kNonStrictMode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002291 has_pending_exception = obj.is_null();
2292 EXCEPTION_BAILOUT_CHECK(false);
2293 return true;
2294}
2295
2296
Steve Block6ded16b2010-05-10 14:33:55 +01002297bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
2298 ON_BAILOUT("v8::Object::Set()", return false);
2299 ENTER_V8;
2300 HandleScope scope;
2301 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2302 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2303 EXCEPTION_PREAMBLE();
2304 i::Handle<i::Object> obj = i::SetElement(
2305 self,
2306 index,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002307 value_obj,
2308 i::kNonStrictMode);
Steve Block6ded16b2010-05-10 14:33:55 +01002309 has_pending_exception = obj.is_null();
2310 EXCEPTION_BAILOUT_CHECK(false);
2311 return true;
2312}
2313
2314
Steve Blocka7e24c12009-10-30 11:49:00 +00002315bool v8::Object::ForceSet(v8::Handle<Value> key,
2316 v8::Handle<Value> value,
2317 v8::PropertyAttribute attribs) {
2318 ON_BAILOUT("v8::Object::ForceSet()", return false);
2319 ENTER_V8;
2320 HandleScope scope;
2321 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2322 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2323 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2324 EXCEPTION_PREAMBLE();
2325 i::Handle<i::Object> obj = i::ForceSetProperty(
2326 self,
2327 key_obj,
2328 value_obj,
2329 static_cast<PropertyAttributes>(attribs));
2330 has_pending_exception = obj.is_null();
2331 EXCEPTION_BAILOUT_CHECK(false);
2332 return true;
2333}
2334
2335
2336bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2337 ON_BAILOUT("v8::Object::ForceDelete()", return false);
2338 ENTER_V8;
2339 HandleScope scope;
2340 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2341 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002342
2343 // When turning on access checks for a global object deoptimize all functions
2344 // as optimized code does not always handle access checks.
2345 i::Deoptimizer::DeoptimizeGlobalObject(*self);
2346
Steve Blocka7e24c12009-10-30 11:49:00 +00002347 EXCEPTION_PREAMBLE();
2348 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2349 has_pending_exception = obj.is_null();
2350 EXCEPTION_BAILOUT_CHECK(false);
2351 return obj->IsTrue();
2352}
2353
2354
2355Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2356 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2357 ENTER_V8;
2358 i::Handle<i::Object> self = Utils::OpenHandle(this);
2359 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2360 EXCEPTION_PREAMBLE();
2361 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2362 has_pending_exception = result.is_null();
2363 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2364 return Utils::ToLocal(result);
2365}
2366
2367
Steve Block6ded16b2010-05-10 14:33:55 +01002368Local<Value> v8::Object::Get(uint32_t index) {
2369 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2370 ENTER_V8;
2371 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2372 EXCEPTION_PREAMBLE();
2373 i::Handle<i::Object> result = i::GetElement(self, index);
2374 has_pending_exception = result.is_null();
2375 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2376 return Utils::ToLocal(result);
2377}
2378
2379
Steve Blocka7e24c12009-10-30 11:49:00 +00002380Local<Value> v8::Object::GetPrototype() {
2381 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
2382 ENTER_V8;
2383 i::Handle<i::Object> self = Utils::OpenHandle(this);
2384 i::Handle<i::Object> result = i::GetPrototype(self);
2385 return Utils::ToLocal(result);
2386}
2387
2388
Andrei Popescu402d9372010-02-26 13:31:12 +00002389bool v8::Object::SetPrototype(Handle<Value> value) {
2390 ON_BAILOUT("v8::Object::SetPrototype()", return false);
2391 ENTER_V8;
2392 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2393 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2394 EXCEPTION_PREAMBLE();
2395 i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2396 has_pending_exception = result.is_null();
2397 EXCEPTION_BAILOUT_CHECK(false);
2398 return true;
2399}
2400
2401
Steve Blocka7e24c12009-10-30 11:49:00 +00002402Local<Object> v8::Object::FindInstanceInPrototypeChain(
2403 v8::Handle<FunctionTemplate> tmpl) {
2404 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
2405 return Local<v8::Object>());
2406 ENTER_V8;
2407 i::JSObject* object = *Utils::OpenHandle(this);
2408 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2409 while (!object->IsInstanceOf(tmpl_info)) {
2410 i::Object* prototype = object->GetPrototype();
2411 if (!prototype->IsJSObject()) return Local<Object>();
2412 object = i::JSObject::cast(prototype);
2413 }
2414 return Utils::ToLocal(i::Handle<i::JSObject>(object));
2415}
2416
2417
2418Local<Array> v8::Object::GetPropertyNames() {
2419 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
2420 ENTER_V8;
2421 v8::HandleScope scope;
2422 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2423 i::Handle<i::FixedArray> value =
2424 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2425 // Because we use caching to speed up enumeration it is important
2426 // to never change the result of the basic enumeration function so
2427 // we clone the result.
2428 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
2429 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
2430 return scope.Close(Utils::ToLocal(result));
2431}
2432
2433
2434Local<String> v8::Object::ObjectProtoToString() {
2435 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2436 ENTER_V8;
2437 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2438
2439 i::Handle<i::Object> name(self->class_name());
2440
2441 // Native implementation of Object.prototype.toString (v8natives.js):
2442 // var c = %ClassOf(this);
2443 // if (c === 'Arguments') c = 'Object';
2444 // return "[object " + c + "]";
2445
2446 if (!name->IsString()) {
2447 return v8::String::New("[object ]");
2448
2449 } else {
2450 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2451 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2452 return v8::String::New("[object Object]");
2453
2454 } else {
2455 const char* prefix = "[object ";
2456 Local<String> str = Utils::ToLocal(class_name);
2457 const char* postfix = "]";
2458
Steve Blockd0582a62009-12-15 09:54:21 +00002459 int prefix_len = i::StrLength(prefix);
2460 int str_len = str->Length();
2461 int postfix_len = i::StrLength(postfix);
Steve Blocka7e24c12009-10-30 11:49:00 +00002462
Steve Blockd0582a62009-12-15 09:54:21 +00002463 int buf_len = prefix_len + str_len + postfix_len;
Kristian Monsen25f61362010-05-21 11:50:48 +01002464 i::ScopedVector<char> buf(buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002465
2466 // Write prefix.
Kristian Monsen25f61362010-05-21 11:50:48 +01002467 char* ptr = buf.start();
Steve Blocka7e24c12009-10-30 11:49:00 +00002468 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2469 ptr += prefix_len;
2470
2471 // Write real content.
2472 str->WriteAscii(ptr, 0, str_len);
2473 ptr += str_len;
2474
2475 // Write postfix.
2476 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2477
2478 // Copy the buffer into a heap-allocated string and return it.
Kristian Monsen25f61362010-05-21 11:50:48 +01002479 Local<String> result = v8::String::New(buf.start(), buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002480 return result;
2481 }
2482 }
2483}
2484
2485
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002486Local<String> v8::Object::GetConstructorName() {
2487 ON_BAILOUT("v8::Object::GetConstructorName()", return Local<v8::String>());
2488 ENTER_V8;
2489 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2490 i::Handle<i::String> name(self->constructor_name());
2491 return Utils::ToLocal(name);
2492}
2493
2494
Steve Blocka7e24c12009-10-30 11:49:00 +00002495bool v8::Object::Delete(v8::Handle<String> key) {
2496 ON_BAILOUT("v8::Object::Delete()", return false);
2497 ENTER_V8;
2498 HandleScope scope;
2499 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2500 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2501 return i::DeleteProperty(self, key_obj)->IsTrue();
2502}
2503
2504
2505bool v8::Object::Has(v8::Handle<String> key) {
2506 ON_BAILOUT("v8::Object::Has()", return false);
2507 ENTER_V8;
2508 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2509 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2510 return self->HasProperty(*key_obj);
2511}
2512
2513
2514bool v8::Object::Delete(uint32_t index) {
2515 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2516 ENTER_V8;
2517 HandleScope scope;
2518 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2519 return i::DeleteElement(self, index)->IsTrue();
2520}
2521
2522
2523bool v8::Object::Has(uint32_t index) {
2524 ON_BAILOUT("v8::Object::HasProperty()", return false);
2525 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2526 return self->HasElement(index);
2527}
2528
2529
Leon Clarkef7060e22010-06-03 12:02:55 +01002530bool Object::SetAccessor(Handle<String> name,
2531 AccessorGetter getter,
2532 AccessorSetter setter,
2533 v8::Handle<Value> data,
2534 AccessControl settings,
2535 PropertyAttribute attributes) {
2536 ON_BAILOUT("v8::Object::SetAccessor()", return false);
2537 ENTER_V8;
2538 HandleScope scope;
2539 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name,
2540 getter, setter, data,
2541 settings, attributes);
2542 i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info);
2543 return !result.is_null() && !result->IsUndefined();
2544}
2545
2546
Steve Blocka7e24c12009-10-30 11:49:00 +00002547bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2548 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2549 return Utils::OpenHandle(this)->HasRealNamedProperty(
2550 *Utils::OpenHandle(*key));
2551}
2552
2553
2554bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2555 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2556 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2557}
2558
2559
2560bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2561 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2562 ENTER_V8;
2563 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2564 *Utils::OpenHandle(*key));
2565}
2566
2567
2568bool v8::Object::HasNamedLookupInterceptor() {
2569 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2570 return Utils::OpenHandle(this)->HasNamedInterceptor();
2571}
2572
2573
2574bool v8::Object::HasIndexedLookupInterceptor() {
2575 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2576 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2577}
2578
2579
2580Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2581 Handle<String> key) {
2582 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2583 return Local<Value>());
2584 ENTER_V8;
2585 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2586 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2587 i::LookupResult lookup;
2588 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002589 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002590 PropertyAttributes attributes;
John Reck59135872010-11-02 12:39:01 -07002591 i::Object* property =
2592 self_obj->GetProperty(*self_obj,
2593 &lookup,
2594 *key_obj,
2595 &attributes)->ToObjectUnchecked();
2596 i::Handle<i::Object> result(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00002597 return Utils::ToLocal(result);
2598 }
2599 return Local<Value>(); // No real property was found in prototype chain.
2600}
2601
2602
2603Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2604 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
2605 ENTER_V8;
2606 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2607 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2608 i::LookupResult lookup;
2609 self_obj->LookupRealNamedProperty(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002610 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002611 PropertyAttributes attributes;
John Reck59135872010-11-02 12:39:01 -07002612 i::Object* property =
2613 self_obj->GetProperty(*self_obj,
2614 &lookup,
2615 *key_obj,
2616 &attributes)->ToObjectUnchecked();
2617 i::Handle<i::Object> result(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00002618 return Utils::ToLocal(result);
2619 }
2620 return Local<Value>(); // No real property was found in prototype chain.
2621}
2622
2623
2624// Turns on access checks by copying the map and setting the check flag.
2625// Because the object gets a new map, existing inline cache caching
2626// the old map of this object will fail.
2627void v8::Object::TurnOnAccessCheck() {
2628 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2629 ENTER_V8;
2630 HandleScope scope;
2631 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2632
Ben Murdochb0fe1622011-05-05 13:52:32 +01002633 // When turning on access checks for a global object deoptimize all functions
2634 // as optimized code does not always handle access checks.
2635 i::Deoptimizer::DeoptimizeGlobalObject(*obj);
2636
Steve Blocka7e24c12009-10-30 11:49:00 +00002637 i::Handle<i::Map> new_map =
2638 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2639 new_map->set_is_access_check_needed(true);
2640 obj->set_map(*new_map);
2641}
2642
2643
2644bool v8::Object::IsDirty() {
2645 return Utils::OpenHandle(this)->IsDirty();
2646}
2647
2648
2649Local<v8::Object> v8::Object::Clone() {
2650 ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2651 ENTER_V8;
2652 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2653 EXCEPTION_PREAMBLE();
2654 i::Handle<i::JSObject> result = i::Copy(self);
2655 has_pending_exception = result.is_null();
2656 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2657 return Utils::ToLocal(result);
2658}
2659
2660
2661int v8::Object::GetIdentityHash() {
2662 ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2663 ENTER_V8;
2664 HandleScope scope;
2665 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002666 i::Handle<i::Object> hidden_props_obj(i::GetHiddenProperties(self, true));
2667 if (!hidden_props_obj->IsJSObject()) {
2668 // We failed to create hidden properties. That's a detached
2669 // global proxy.
2670 ASSERT(hidden_props_obj->IsUndefined());
2671 return 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002672 }
Steve Block1e0659c2011-05-24 12:43:12 +01002673 i::Handle<i::JSObject> hidden_props =
2674 i::Handle<i::JSObject>::cast(hidden_props_obj);
2675 i::Handle<i::String> hash_symbol = i::Factory::identity_hash_symbol();
2676 if (hidden_props->HasLocalProperty(*hash_symbol)) {
2677 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2678 CHECK(!hash.is_null());
2679 CHECK(hash->IsSmi());
2680 return i::Smi::cast(*hash)->value();
2681 }
2682
2683 int hash_value;
2684 int attempts = 0;
2685 do {
2686 // Generate a random 32-bit hash value but limit range to fit
2687 // within a smi.
2688 hash_value = i::V8::Random() & i::Smi::kMaxValue;
2689 attempts++;
2690 } while (hash_value == 0 && attempts < 30);
2691 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
2692 CHECK(!i::SetLocalPropertyIgnoreAttributes(
2693 hidden_props,
2694 hash_symbol,
2695 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2696 static_cast<PropertyAttributes>(None)).is_null());
2697
Steve Blocka7e24c12009-10-30 11:49:00 +00002698 return hash_value;
2699}
2700
2701
2702bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2703 v8::Handle<v8::Value> value) {
2704 ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
2705 ENTER_V8;
2706 HandleScope scope;
2707 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2708 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2709 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2710 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2711 EXCEPTION_PREAMBLE();
2712 i::Handle<i::Object> obj = i::SetProperty(
2713 hidden_props,
2714 key_obj,
2715 value_obj,
Ben Murdoche0cee9b2011-05-25 10:26:03 +01002716 static_cast<PropertyAttributes>(None),
2717 i::kNonStrictMode);
Steve Blocka7e24c12009-10-30 11:49:00 +00002718 has_pending_exception = obj.is_null();
2719 EXCEPTION_BAILOUT_CHECK(false);
2720 return true;
2721}
2722
2723
2724v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2725 ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2726 ENTER_V8;
2727 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2728 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2729 if (hidden_props->IsUndefined()) {
2730 return v8::Local<v8::Value>();
2731 }
2732 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2733 EXCEPTION_PREAMBLE();
2734 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2735 has_pending_exception = result.is_null();
2736 EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2737 if (result->IsUndefined()) {
2738 return v8::Local<v8::Value>();
2739 }
2740 return Utils::ToLocal(result);
2741}
2742
2743
2744bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2745 ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2746 ENTER_V8;
2747 HandleScope scope;
2748 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2749 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2750 if (hidden_props->IsUndefined()) {
2751 return true;
2752 }
2753 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2754 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2755 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2756}
2757
2758
2759void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2760 ON_BAILOUT("v8::SetElementsToPixelData()", return);
2761 ENTER_V8;
2762 HandleScope scope;
Steve Block3ce2e202009-11-05 08:53:23 +00002763 if (!ApiCheck(length <= i::PixelArray::kMaxLength,
Steve Blocka7e24c12009-10-30 11:49:00 +00002764 "v8::Object::SetIndexedPropertiesToPixelData()",
2765 "length exceeds max acceptable value")) {
2766 return;
2767 }
2768 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2769 if (!ApiCheck(!self->IsJSArray(),
2770 "v8::Object::SetIndexedPropertiesToPixelData()",
2771 "JSArray is not supported")) {
2772 return;
2773 }
2774 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
Steve Block1e0659c2011-05-24 12:43:12 +01002775 i::Handle<i::Map> pixel_array_map =
2776 i::Factory::GetPixelArrayElementsMap(i::Handle<i::Map>(self->map()));
2777 self->set_map(*pixel_array_map);
Steve Blocka7e24c12009-10-30 11:49:00 +00002778 self->set_elements(*pixels);
2779}
2780
2781
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002782bool v8::Object::HasIndexedPropertiesInPixelData() {
2783 ON_BAILOUT("v8::HasIndexedPropertiesInPixelData()", return false);
2784 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2785 return self->HasPixelElements();
2786}
2787
2788
2789uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
2790 ON_BAILOUT("v8::GetIndexedPropertiesPixelData()", return NULL);
2791 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2792 if (self->HasPixelElements()) {
2793 return i::PixelArray::cast(self->elements())->external_pointer();
2794 } else {
2795 return NULL;
2796 }
2797}
2798
2799
2800int v8::Object::GetIndexedPropertiesPixelDataLength() {
2801 ON_BAILOUT("v8::GetIndexedPropertiesPixelDataLength()", return -1);
2802 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2803 if (self->HasPixelElements()) {
2804 return i::PixelArray::cast(self->elements())->length();
2805 } else {
2806 return -1;
2807 }
2808}
2809
2810
Steve Block3ce2e202009-11-05 08:53:23 +00002811void v8::Object::SetIndexedPropertiesToExternalArrayData(
2812 void* data,
2813 ExternalArrayType array_type,
2814 int length) {
2815 ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
2816 ENTER_V8;
2817 HandleScope scope;
2818 if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
2819 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2820 "length exceeds max acceptable value")) {
2821 return;
2822 }
2823 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2824 if (!ApiCheck(!self->IsJSArray(),
2825 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2826 "JSArray is not supported")) {
2827 return;
2828 }
2829 i::Handle<i::ExternalArray> array =
2830 i::Factory::NewExternalArray(length, array_type, data);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002831 i::Handle<i::Map> slow_map =
2832 i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map()));
2833 self->set_map(*slow_map);
Steve Block3ce2e202009-11-05 08:53:23 +00002834 self->set_elements(*array);
2835}
2836
2837
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002838bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
2839 ON_BAILOUT("v8::HasIndexedPropertiesInExternalArrayData()", return false);
2840 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2841 return self->HasExternalArrayElements();
2842}
2843
2844
2845void* v8::Object::GetIndexedPropertiesExternalArrayData() {
2846 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayData()", return NULL);
2847 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2848 if (self->HasExternalArrayElements()) {
2849 return i::ExternalArray::cast(self->elements())->external_pointer();
2850 } else {
2851 return NULL;
2852 }
2853}
2854
2855
2856ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
2857 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataType()",
2858 return static_cast<ExternalArrayType>(-1));
2859 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2860 switch (self->elements()->map()->instance_type()) {
2861 case i::EXTERNAL_BYTE_ARRAY_TYPE:
2862 return kExternalByteArray;
2863 case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2864 return kExternalUnsignedByteArray;
2865 case i::EXTERNAL_SHORT_ARRAY_TYPE:
2866 return kExternalShortArray;
2867 case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2868 return kExternalUnsignedShortArray;
2869 case i::EXTERNAL_INT_ARRAY_TYPE:
2870 return kExternalIntArray;
2871 case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2872 return kExternalUnsignedIntArray;
2873 case i::EXTERNAL_FLOAT_ARRAY_TYPE:
2874 return kExternalFloatArray;
2875 default:
2876 return static_cast<ExternalArrayType>(-1);
2877 }
2878}
2879
2880
2881int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
2882 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataLength()", return 0);
2883 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2884 if (self->HasExternalArrayElements()) {
2885 return i::ExternalArray::cast(self->elements())->length();
2886 } else {
2887 return -1;
2888 }
2889}
2890
2891
Steve Blocka7e24c12009-10-30 11:49:00 +00002892Local<v8::Object> Function::NewInstance() const {
2893 return NewInstance(0, NULL);
2894}
2895
2896
2897Local<v8::Object> Function::NewInstance(int argc,
2898 v8::Handle<v8::Value> argv[]) const {
2899 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2900 LOG_API("Function::NewInstance");
2901 ENTER_V8;
2902 HandleScope scope;
2903 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2904 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2905 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2906 EXCEPTION_PREAMBLE();
2907 i::Handle<i::Object> returned =
2908 i::Execution::New(function, argc, args, &has_pending_exception);
2909 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2910 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2911}
2912
2913
2914Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2915 v8::Handle<v8::Value> argv[]) {
2916 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2917 LOG_API("Function::Call");
2918 ENTER_V8;
2919 i::Object* raw_result = NULL;
2920 {
2921 HandleScope scope;
2922 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2923 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2924 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2925 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2926 EXCEPTION_PREAMBLE();
2927 i::Handle<i::Object> returned =
2928 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2929 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2930 raw_result = *returned;
2931 }
2932 i::Handle<i::Object> result(raw_result);
2933 return Utils::ToLocal(result);
2934}
2935
2936
2937void Function::SetName(v8::Handle<v8::String> name) {
2938 ENTER_V8;
2939 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2940 func->shared()->set_name(*Utils::OpenHandle(*name));
2941}
2942
2943
2944Handle<Value> Function::GetName() const {
2945 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2946 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2947}
2948
2949
Andrei Popescu402d9372010-02-26 13:31:12 +00002950ScriptOrigin Function::GetScriptOrigin() const {
2951 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2952 if (func->shared()->script()->IsScript()) {
2953 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2954 v8::ScriptOrigin origin(
2955 Utils::ToLocal(i::Handle<i::Object>(script->name())),
2956 v8::Integer::New(script->line_offset()->value()),
2957 v8::Integer::New(script->column_offset()->value()));
2958 return origin;
2959 }
2960 return v8::ScriptOrigin(Handle<Value>());
2961}
2962
2963
2964const int Function::kLineOffsetNotFound = -1;
2965
2966
2967int Function::GetScriptLineNumber() const {
2968 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2969 if (func->shared()->script()->IsScript()) {
2970 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2971 return i::GetScriptLineNumber(script, func->shared()->start_position());
2972 }
2973 return kLineOffsetNotFound;
2974}
2975
2976
2977namespace {
2978
2979// Tracks string usage to help make better decisions when
2980// externalizing strings.
2981//
2982// Implementation note: internally this class only tracks fresh
2983// strings and keeps a single use counter for them.
2984class StringTracker {
2985 public:
2986 // Records that the given string's characters were copied to some
2987 // external buffer. If this happens often we should honor
2988 // externalization requests for the string.
2989 static void RecordWrite(i::Handle<i::String> string) {
2990 i::Address address = reinterpret_cast<i::Address>(*string);
2991 i::Address top = i::Heap::NewSpaceTop();
2992 if (IsFreshString(address, top)) {
2993 IncrementUseCount(top);
2994 }
2995 }
2996
2997 // Estimates freshness and use frequency of the given string based
2998 // on how close it is to the new space top and the recorded usage
2999 // history.
3000 static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
3001 i::Address address = reinterpret_cast<i::Address>(*string);
3002 i::Address top = i::Heap::NewSpaceTop();
3003 return IsFreshString(address, top) && IsUseCountLow(top);
3004 }
3005
3006 private:
3007 static inline bool IsFreshString(i::Address string, i::Address top) {
3008 return top - kFreshnessLimit <= string && string <= top;
3009 }
3010
3011 static inline bool IsUseCountLow(i::Address top) {
3012 if (last_top_ != top) return true;
3013 return use_count_ < kUseLimit;
3014 }
3015
3016 static inline void IncrementUseCount(i::Address top) {
3017 if (last_top_ != top) {
3018 use_count_ = 0;
3019 last_top_ = top;
3020 }
3021 ++use_count_;
3022 }
3023
3024 // How close to the new space top a fresh string has to be.
3025 static const int kFreshnessLimit = 1024;
3026
3027 // The number of uses required to consider a string useful.
3028 static const int kUseLimit = 32;
3029
3030 // Single use counter shared by all fresh strings.
3031 static int use_count_;
3032
3033 // Last new space top when the use count above was valid.
3034 static i::Address last_top_;
3035};
3036
3037int StringTracker::use_count_ = 0;
3038i::Address StringTracker::last_top_ = NULL;
3039
3040} // namespace
3041
3042
Steve Blocka7e24c12009-10-30 11:49:00 +00003043int String::Length() const {
3044 if (IsDeadCheck("v8::String::Length()")) return 0;
3045 return Utils::OpenHandle(this)->length();
3046}
3047
3048
3049int String::Utf8Length() const {
3050 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
3051 return Utils::OpenHandle(this)->Utf8Length();
3052}
3053
3054
Steve Block6ded16b2010-05-10 14:33:55 +01003055int String::WriteUtf8(char* buffer,
3056 int capacity,
3057 int* nchars_ref,
3058 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003059 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
3060 LOG_API("String::WriteUtf8");
3061 ENTER_V8;
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 write_input_buffer.Reset(0, *str);
3070 int len = str->length();
3071 // Encode the first K - 3 bytes directly into the buffer since we
3072 // know there's room for them. If no capacity is given we copy all
3073 // of them here.
3074 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
3075 int i;
3076 int pos = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01003077 int nchars = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00003078 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
3079 i::uc32 c = write_input_buffer.GetNext();
3080 int written = unibrow::Utf8::Encode(buffer + pos, c);
3081 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01003082 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00003083 }
3084 if (i < len) {
3085 // For the last characters we need to check the length for each one
3086 // because they may be longer than the remaining space in the
3087 // buffer.
3088 char intermediate[unibrow::Utf8::kMaxEncodedSize];
3089 for (; i < len && pos < capacity; i++) {
3090 i::uc32 c = write_input_buffer.GetNext();
3091 int written = unibrow::Utf8::Encode(intermediate, c);
3092 if (pos + written <= capacity) {
3093 for (int j = 0; j < written; j++)
3094 buffer[pos + j] = intermediate[j];
3095 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01003096 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00003097 } else {
3098 // We've reached the end of the buffer
3099 break;
3100 }
3101 }
3102 }
Steve Block6ded16b2010-05-10 14:33:55 +01003103 if (nchars_ref != NULL) *nchars_ref = nchars;
Steve Blocka7e24c12009-10-30 11:49:00 +00003104 if (i == len && (capacity == -1 || pos < capacity))
3105 buffer[pos++] = '\0';
3106 return pos;
3107}
3108
3109
Steve Block6ded16b2010-05-10 14:33:55 +01003110int String::WriteAscii(char* buffer,
3111 int start,
3112 int length,
3113 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003114 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
3115 LOG_API("String::WriteAscii");
3116 ENTER_V8;
3117 ASSERT(start >= 0 && length >= -1);
3118 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003119 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003120 if (hints & HINT_MANY_WRITES_EXPECTED) {
3121 // Flatten the string for efficiency. This applies whether we are
3122 // using StringInputBuffer or Get(i) to access the characters.
3123 str->TryFlatten();
3124 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003125 int end = length;
3126 if ( (length == -1) || (length > str->length() - start) )
3127 end = str->length() - start;
3128 if (end < 0) return 0;
3129 write_input_buffer.Reset(start, *str);
3130 int i;
3131 for (i = 0; i < end; i++) {
3132 char c = static_cast<char>(write_input_buffer.GetNext());
3133 if (c == '\0') c = ' ';
3134 buffer[i] = c;
3135 }
3136 if (length == -1 || i < length)
3137 buffer[i] = '\0';
3138 return i;
3139}
3140
3141
Steve Block6ded16b2010-05-10 14:33:55 +01003142int String::Write(uint16_t* buffer,
3143 int start,
3144 int length,
3145 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003146 if (IsDeadCheck("v8::String::Write()")) return 0;
3147 LOG_API("String::Write");
3148 ENTER_V8;
3149 ASSERT(start >= 0 && length >= -1);
3150 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003151 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003152 if (hints & HINT_MANY_WRITES_EXPECTED) {
3153 // Flatten the string for efficiency. This applies whether we are
3154 // using StringInputBuffer or Get(i) to access the characters.
3155 str->TryFlatten();
3156 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003157 int end = start + length;
3158 if ((length == -1) || (length > str->length() - start) )
3159 end = str->length();
Steve Blocka7e24c12009-10-30 11:49:00 +00003160 if (end < 0) return 0;
3161 i::String::WriteToFlat(*str, buffer, start, end);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003162 if (length == -1 || end - start < length) {
3163 buffer[end - start] = '\0';
3164 }
3165 return end - start;
Steve Blocka7e24c12009-10-30 11:49:00 +00003166}
3167
3168
3169bool v8::String::IsExternal() const {
3170 EnsureInitialized("v8::String::IsExternal()");
3171 i::Handle<i::String> str = Utils::OpenHandle(this);
3172 return i::StringShape(*str).IsExternalTwoByte();
3173}
3174
3175
3176bool v8::String::IsExternalAscii() const {
3177 EnsureInitialized("v8::String::IsExternalAscii()");
3178 i::Handle<i::String> str = Utils::OpenHandle(this);
3179 return i::StringShape(*str).IsExternalAscii();
3180}
3181
3182
3183void v8::String::VerifyExternalStringResource(
3184 v8::String::ExternalStringResource* value) const {
3185 i::Handle<i::String> str = Utils::OpenHandle(this);
3186 v8::String::ExternalStringResource* expected;
3187 if (i::StringShape(*str).IsExternalTwoByte()) {
3188 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
3189 expected = reinterpret_cast<ExternalStringResource*>(resource);
3190 } else {
3191 expected = NULL;
3192 }
3193 CHECK_EQ(expected, value);
3194}
3195
3196
3197v8::String::ExternalAsciiStringResource*
3198 v8::String::GetExternalAsciiStringResource() const {
3199 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
3200 i::Handle<i::String> str = Utils::OpenHandle(this);
3201 if (i::StringShape(*str).IsExternalAscii()) {
3202 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
3203 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
3204 } else {
3205 return NULL;
3206 }
3207}
3208
3209
3210double Number::Value() const {
3211 if (IsDeadCheck("v8::Number::Value()")) return 0;
3212 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3213 return obj->Number();
3214}
3215
3216
3217bool Boolean::Value() const {
3218 if (IsDeadCheck("v8::Boolean::Value()")) return false;
3219 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3220 return obj->IsTrue();
3221}
3222
3223
3224int64_t Integer::Value() const {
3225 if (IsDeadCheck("v8::Integer::Value()")) return 0;
3226 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3227 if (obj->IsSmi()) {
3228 return i::Smi::cast(*obj)->value();
3229 } else {
3230 return static_cast<int64_t>(obj->Number());
3231 }
3232}
3233
3234
3235int32_t Int32::Value() const {
3236 if (IsDeadCheck("v8::Int32::Value()")) return 0;
3237 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3238 if (obj->IsSmi()) {
3239 return i::Smi::cast(*obj)->value();
3240 } else {
3241 return static_cast<int32_t>(obj->Number());
3242 }
3243}
3244
3245
Steve Block6ded16b2010-05-10 14:33:55 +01003246uint32_t Uint32::Value() const {
3247 if (IsDeadCheck("v8::Uint32::Value()")) return 0;
3248 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3249 if (obj->IsSmi()) {
3250 return i::Smi::cast(*obj)->value();
3251 } else {
3252 return static_cast<uint32_t>(obj->Number());
3253 }
3254}
3255
3256
Steve Blocka7e24c12009-10-30 11:49:00 +00003257int v8::Object::InternalFieldCount() {
3258 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
3259 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3260 return obj->GetInternalFieldCount();
3261}
3262
3263
3264Local<Value> v8::Object::CheckedGetInternalField(int index) {
3265 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
3266 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3267 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3268 "v8::Object::GetInternalField()",
3269 "Reading internal field out of bounds")) {
3270 return Local<Value>();
3271 }
3272 i::Handle<i::Object> value(obj->GetInternalField(index));
3273 Local<Value> result = Utils::ToLocal(value);
3274#ifdef DEBUG
3275 Local<Value> unchecked = UncheckedGetInternalField(index);
3276 ASSERT(unchecked.IsEmpty() || (unchecked == result));
3277#endif
3278 return result;
3279}
3280
3281
3282void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
3283 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
3284 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3285 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3286 "v8::Object::SetInternalField()",
3287 "Writing internal field out of bounds")) {
3288 return;
3289 }
3290 ENTER_V8;
3291 i::Handle<i::Object> val = Utils::OpenHandle(*value);
3292 obj->SetInternalField(index, *val);
3293}
3294
3295
Ben Murdochb8e0da22011-05-16 14:20:40 +01003296static bool CanBeEncodedAsSmi(void* ptr) {
Steve Block1e0659c2011-05-24 12:43:12 +01003297 const uintptr_t address = reinterpret_cast<uintptr_t>(ptr);
Ben Murdochb8e0da22011-05-16 14:20:40 +01003298 return ((address & i::kEncodablePointerMask) == 0);
3299}
3300
3301
3302static i::Smi* EncodeAsSmi(void* ptr) {
3303 ASSERT(CanBeEncodedAsSmi(ptr));
Steve Block1e0659c2011-05-24 12:43:12 +01003304 const uintptr_t address = reinterpret_cast<uintptr_t>(ptr);
Ben Murdochb8e0da22011-05-16 14:20:40 +01003305 i::Smi* result = reinterpret_cast<i::Smi*>(address << i::kPointerToSmiShift);
3306 ASSERT(i::Internals::HasSmiTag(result));
3307 ASSERT_EQ(result, i::Smi::FromInt(result->value()));
3308 ASSERT_EQ(ptr, i::Internals::GetExternalPointerFromSmi(result));
3309 return result;
3310}
3311
3312
Steve Blocka7e24c12009-10-30 11:49:00 +00003313void v8::Object::SetPointerInInternalField(int index, void* value) {
Steve Block6ded16b2010-05-10 14:33:55 +01003314 ENTER_V8;
Ben Murdochb8e0da22011-05-16 14:20:40 +01003315 if (CanBeEncodedAsSmi(value)) {
3316 Utils::OpenHandle(this)->SetInternalField(index, EncodeAsSmi(value));
3317 } else {
3318 HandleScope scope;
3319 i::Handle<i::Proxy> proxy =
3320 i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
3321 if (!proxy.is_null())
3322 Utils::OpenHandle(this)->SetInternalField(index, *proxy);
Steve Block3ce2e202009-11-05 08:53:23 +00003323 }
Ben Murdochb8e0da22011-05-16 14:20:40 +01003324 ASSERT_EQ(value, GetPointerFromInternalField(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00003325}
3326
3327
3328// --- E n v i r o n m e n t ---
3329
3330bool v8::V8::Initialize() {
3331 if (i::V8::IsRunning()) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003332 HandleScope scope;
Steve Blockd0582a62009-12-15 09:54:21 +00003333 if (i::Snapshot::Initialize()) return true;
3334 return i::V8::Initialize(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00003335}
3336
3337
3338bool v8::V8::Dispose() {
3339 i::V8::TearDown();
3340 return true;
3341}
3342
3343
Russell Brenner90bac252010-11-18 13:33:46 -08003344HeapStatistics::HeapStatistics(): total_heap_size_(0),
3345 total_heap_size_executable_(0),
Ben Murdochb8e0da22011-05-16 14:20:40 +01003346 used_heap_size_(0),
3347 heap_size_limit_(0) { }
Steve Block3ce2e202009-11-05 08:53:23 +00003348
3349
3350void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
3351 heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
Russell Brenner90bac252010-11-18 13:33:46 -08003352 heap_statistics->set_total_heap_size_executable(
3353 i::Heap::CommittedMemoryExecutable());
Steve Block3ce2e202009-11-05 08:53:23 +00003354 heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
Ben Murdochb8e0da22011-05-16 14:20:40 +01003355 heap_statistics->set_heap_size_limit(i::Heap::MaxReserved());
Steve Block3ce2e202009-11-05 08:53:23 +00003356}
3357
3358
3359bool v8::V8::IdleNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003360 // Returning true tells the caller that it need not
3361 // continue to call IdleNotification.
3362 if (!i::V8::IsRunning()) return true;
Steve Block3ce2e202009-11-05 08:53:23 +00003363 return i::V8::IdleNotification();
Steve Blocka7e24c12009-10-30 11:49:00 +00003364}
3365
3366
3367void v8::V8::LowMemoryNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003368 if (!i::V8::IsRunning()) return;
3369 i::Heap::CollectAllGarbage(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00003370}
3371
3372
Steve Block6ded16b2010-05-10 14:33:55 +01003373int v8::V8::ContextDisposedNotification() {
3374 if (!i::V8::IsRunning()) return 0;
3375 return i::Heap::NotifyContextDisposed();
3376}
3377
3378
Steve Blocka7e24c12009-10-30 11:49:00 +00003379const char* v8::V8::GetVersion() {
3380 static v8::internal::EmbeddedVector<char, 128> buffer;
3381 v8::internal::Version::GetString(buffer);
3382 return buffer.start();
3383}
3384
3385
3386static i::Handle<i::FunctionTemplateInfo>
3387 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
3388 if (templ->constructor()->IsUndefined()) {
3389 Local<FunctionTemplate> constructor = FunctionTemplate::New();
3390 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
3391 templ->set_constructor(*Utils::OpenHandle(*constructor));
3392 }
3393 return i::Handle<i::FunctionTemplateInfo>(
3394 i::FunctionTemplateInfo::cast(templ->constructor()));
3395}
3396
3397
3398Persistent<Context> v8::Context::New(
3399 v8::ExtensionConfiguration* extensions,
3400 v8::Handle<ObjectTemplate> global_template,
3401 v8::Handle<Value> global_object) {
3402 EnsureInitialized("v8::Context::New()");
3403 LOG_API("Context::New");
3404 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
3405
3406 // Enter V8 via an ENTER_V8 scope.
3407 i::Handle<i::Context> env;
3408 {
3409 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003410 v8::Handle<ObjectTemplate> proxy_template = global_template;
3411 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
3412 i::Handle<i::FunctionTemplateInfo> global_constructor;
3413
3414 if (!global_template.IsEmpty()) {
3415 // Make sure that the global_template has a constructor.
3416 global_constructor =
3417 EnsureConstructor(Utils::OpenHandle(*global_template));
3418
3419 // Create a fresh template for the global proxy object.
3420 proxy_template = ObjectTemplate::New();
3421 proxy_constructor =
3422 EnsureConstructor(Utils::OpenHandle(*proxy_template));
3423
3424 // Set the global template to be the prototype template of
3425 // global proxy template.
3426 proxy_constructor->set_prototype_template(
3427 *Utils::OpenHandle(*global_template));
3428
3429 // Migrate security handlers from global_template to
3430 // proxy_template. Temporarily removing access check
3431 // information from the global template.
3432 if (!global_constructor->access_check_info()->IsUndefined()) {
3433 proxy_constructor->set_access_check_info(
3434 global_constructor->access_check_info());
3435 proxy_constructor->set_needs_access_check(
3436 global_constructor->needs_access_check());
3437 global_constructor->set_needs_access_check(false);
3438 global_constructor->set_access_check_info(i::Heap::undefined_value());
3439 }
3440 }
3441
3442 // Create the environment.
3443 env = i::Bootstrapper::CreateEnvironment(
3444 Utils::OpenHandle(*global_object),
3445 proxy_template,
3446 extensions);
3447
3448 // Restore the access check info on the global template.
3449 if (!global_template.IsEmpty()) {
3450 ASSERT(!global_constructor.is_null());
3451 ASSERT(!proxy_constructor.is_null());
3452 global_constructor->set_access_check_info(
3453 proxy_constructor->access_check_info());
3454 global_constructor->set_needs_access_check(
3455 proxy_constructor->needs_access_check());
3456 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003457 i::RuntimeProfiler::Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00003458 }
3459 // Leave V8.
3460
3461 if (env.is_null())
3462 return Persistent<Context>();
3463 return Persistent<Context>(Utils::ToLocal(env));
3464}
3465
3466
3467void v8::Context::SetSecurityToken(Handle<Value> token) {
3468 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
3469 ENTER_V8;
3470 i::Handle<i::Context> env = Utils::OpenHandle(this);
3471 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
3472 env->set_security_token(*token_handle);
3473}
3474
3475
3476void v8::Context::UseDefaultSecurityToken() {
3477 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
3478 ENTER_V8;
3479 i::Handle<i::Context> env = Utils::OpenHandle(this);
3480 env->set_security_token(env->global());
3481}
3482
3483
3484Handle<Value> v8::Context::GetSecurityToken() {
3485 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
3486 i::Handle<i::Context> env = Utils::OpenHandle(this);
3487 i::Object* security_token = env->security_token();
3488 i::Handle<i::Object> token_handle(security_token);
3489 return Utils::ToLocal(token_handle);
3490}
3491
3492
3493bool Context::HasOutOfMemoryException() {
3494 i::Handle<i::Context> env = Utils::OpenHandle(this);
3495 return env->has_out_of_memory();
3496}
3497
3498
3499bool Context::InContext() {
3500 return i::Top::context() != NULL;
3501}
3502
3503
3504v8::Local<v8::Context> Context::GetEntered() {
3505 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
3506 i::Handle<i::Object> last = thread_local.LastEnteredContext();
3507 if (last.is_null()) return Local<Context>();
3508 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
3509 return Utils::ToLocal(context);
3510}
3511
3512
3513v8::Local<v8::Context> Context::GetCurrent() {
3514 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
Steve Block3ce2e202009-11-05 08:53:23 +00003515 i::Handle<i::Object> current = i::Top::global_context();
3516 if (current.is_null()) return Local<Context>();
3517 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
Steve Blocka7e24c12009-10-30 11:49:00 +00003518 return Utils::ToLocal(context);
3519}
3520
3521
3522v8::Local<v8::Context> Context::GetCalling() {
3523 if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
3524 i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
3525 if (calling.is_null()) return Local<Context>();
3526 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
3527 return Utils::ToLocal(context);
3528}
3529
3530
3531v8::Local<v8::Object> Context::Global() {
3532 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
3533 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3534 i::Handle<i::Context> context =
3535 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3536 i::Handle<i::Object> global(context->global_proxy());
3537 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
3538}
3539
3540
3541void Context::DetachGlobal() {
3542 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
3543 ENTER_V8;
3544 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3545 i::Handle<i::Context> context =
3546 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3547 i::Bootstrapper::DetachGlobal(context);
3548}
3549
3550
Andrei Popescu74b3c142010-03-29 12:03:09 +01003551void Context::ReattachGlobal(Handle<Object> global_object) {
3552 if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
3553 ENTER_V8;
3554 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3555 i::Handle<i::Context> context =
3556 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3557 i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
3558}
3559
3560
Steve Blocka7e24c12009-10-30 11:49:00 +00003561Local<v8::Object> ObjectTemplate::NewInstance() {
3562 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
3563 LOG_API("ObjectTemplate::NewInstance");
3564 ENTER_V8;
3565 EXCEPTION_PREAMBLE();
3566 i::Handle<i::Object> obj =
3567 i::Execution::InstantiateObject(Utils::OpenHandle(this),
3568 &has_pending_exception);
3569 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
3570 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3571}
3572
3573
3574Local<v8::Function> FunctionTemplate::GetFunction() {
3575 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
3576 return Local<v8::Function>());
3577 LOG_API("FunctionTemplate::GetFunction");
3578 ENTER_V8;
3579 EXCEPTION_PREAMBLE();
3580 i::Handle<i::Object> obj =
3581 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3582 &has_pending_exception);
3583 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
3584 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3585}
3586
3587
3588bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3589 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
3590 i::Object* obj = *Utils::OpenHandle(*value);
3591 return obj->IsInstanceOf(*Utils::OpenHandle(this));
3592}
3593
3594
3595static Local<External> ExternalNewImpl(void* data) {
3596 return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
3597}
3598
3599static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3600 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3601}
3602
3603
Steve Blocka7e24c12009-10-30 11:49:00 +00003604Local<Value> v8::External::Wrap(void* data) {
3605 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3606 LOG_API("External::Wrap");
3607 EnsureInitialized("v8::External::Wrap()");
3608 ENTER_V8;
Ben Murdochb8e0da22011-05-16 14:20:40 +01003609
3610 v8::Local<v8::Value> result = CanBeEncodedAsSmi(data)
3611 ? Utils::ToLocal(i::Handle<i::Object>(EncodeAsSmi(data)))
3612 : v8::Local<v8::Value>(ExternalNewImpl(data));
3613
3614 ASSERT_EQ(data, Unwrap(result));
3615 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003616}
3617
3618
Steve Block3ce2e202009-11-05 08:53:23 +00003619void* v8::Object::SlowGetPointerFromInternalField(int index) {
3620 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3621 i::Object* value = obj->GetInternalField(index);
3622 if (value->IsSmi()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01003623 return i::Internals::GetExternalPointerFromSmi(value);
Steve Block3ce2e202009-11-05 08:53:23 +00003624 } else if (value->IsProxy()) {
3625 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3626 } else {
3627 return NULL;
3628 }
3629}
3630
3631
Steve Blocka7e24c12009-10-30 11:49:00 +00003632void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3633 if (IsDeadCheck("v8::External::Unwrap()")) return 0;
3634 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3635 void* result;
3636 if (obj->IsSmi()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01003637 result = i::Internals::GetExternalPointerFromSmi(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003638 } else if (obj->IsProxy()) {
3639 result = ExternalValueImpl(obj);
3640 } else {
3641 result = NULL;
3642 }
3643 ASSERT_EQ(result, QuickUnwrap(wrapper));
3644 return result;
3645}
3646
3647
3648Local<External> v8::External::New(void* data) {
3649 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3650 LOG_API("External::New");
3651 EnsureInitialized("v8::External::New()");
3652 ENTER_V8;
3653 return ExternalNewImpl(data);
3654}
3655
3656
3657void* External::Value() const {
3658 if (IsDeadCheck("v8::External::Value()")) return 0;
3659 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3660 return ExternalValueImpl(obj);
3661}
3662
3663
3664Local<String> v8::String::Empty() {
3665 EnsureInitialized("v8::String::Empty()");
3666 LOG_API("String::Empty()");
3667 return Utils::ToLocal(i::Factory::empty_symbol());
3668}
3669
3670
3671Local<String> v8::String::New(const char* data, int length) {
3672 EnsureInitialized("v8::String::New()");
3673 LOG_API("String::New(char)");
3674 if (length == 0) return Empty();
3675 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003676 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003677 i::Handle<i::String> result =
3678 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3679 return Utils::ToLocal(result);
3680}
3681
3682
Steve Block3ce2e202009-11-05 08:53:23 +00003683Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3684 EnsureInitialized("v8::String::New()");
3685 LOG_API("String::New(char)");
3686 ENTER_V8;
3687 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3688 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3689 i::Handle<i::String> result = i::Factory::NewConsString(left_string,
3690 right_string);
3691 return Utils::ToLocal(result);
3692}
3693
3694
Steve Blocka7e24c12009-10-30 11:49:00 +00003695Local<String> v8::String::NewUndetectable(const char* data, int length) {
3696 EnsureInitialized("v8::String::NewUndetectable()");
3697 LOG_API("String::NewUndetectable(char)");
3698 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003699 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003700 i::Handle<i::String> result =
3701 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3702 result->MarkAsUndetectable();
3703 return Utils::ToLocal(result);
3704}
3705
3706
3707static int TwoByteStringLength(const uint16_t* data) {
3708 int length = 0;
3709 while (data[length] != '\0') length++;
3710 return length;
3711}
3712
3713
3714Local<String> v8::String::New(const uint16_t* data, int length) {
3715 EnsureInitialized("v8::String::New()");
3716 LOG_API("String::New(uint16_)");
3717 if (length == 0) return Empty();
3718 ENTER_V8;
3719 if (length == -1) length = TwoByteStringLength(data);
3720 i::Handle<i::String> result =
3721 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3722 return Utils::ToLocal(result);
3723}
3724
3725
3726Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
3727 EnsureInitialized("v8::String::NewUndetectable()");
3728 LOG_API("String::NewUndetectable(uint16_)");
3729 ENTER_V8;
3730 if (length == -1) length = TwoByteStringLength(data);
3731 i::Handle<i::String> result =
3732 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3733 result->MarkAsUndetectable();
3734 return Utils::ToLocal(result);
3735}
3736
3737
3738i::Handle<i::String> NewExternalStringHandle(
3739 v8::String::ExternalStringResource* resource) {
3740 i::Handle<i::String> result =
3741 i::Factory::NewExternalStringFromTwoByte(resource);
3742 return result;
3743}
3744
3745
3746i::Handle<i::String> NewExternalAsciiStringHandle(
3747 v8::String::ExternalAsciiStringResource* resource) {
3748 i::Handle<i::String> result =
3749 i::Factory::NewExternalStringFromAscii(resource);
3750 return result;
3751}
3752
3753
Steve Blocka7e24c12009-10-30 11:49:00 +00003754Local<String> v8::String::NewExternal(
3755 v8::String::ExternalStringResource* resource) {
3756 EnsureInitialized("v8::String::NewExternal()");
3757 LOG_API("String::NewExternal");
3758 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003759 i::Handle<i::String> result = NewExternalStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003760 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003761 return Utils::ToLocal(result);
3762}
3763
3764
3765bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3766 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3767 if (this->IsExternal()) return false; // Already an external string.
3768 ENTER_V8;
3769 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003770 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003771 bool result = obj->MakeExternal(resource);
3772 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003773 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003774 }
3775 return result;
3776}
3777
3778
3779Local<String> v8::String::NewExternal(
3780 v8::String::ExternalAsciiStringResource* resource) {
3781 EnsureInitialized("v8::String::NewExternal()");
3782 LOG_API("String::NewExternal");
3783 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003784 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003785 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003786 return Utils::ToLocal(result);
3787}
3788
3789
3790bool v8::String::MakeExternal(
3791 v8::String::ExternalAsciiStringResource* resource) {
3792 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3793 if (this->IsExternal()) return false; // Already an external string.
3794 ENTER_V8;
3795 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003796 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003797 bool result = obj->MakeExternal(resource);
3798 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003799 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003800 }
3801 return result;
3802}
3803
3804
3805bool v8::String::CanMakeExternal() {
3806 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3807 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003808 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003809 int size = obj->Size(); // Byte size of the original string.
3810 if (size < i::ExternalString::kSize)
3811 return false;
3812 i::StringShape shape(*obj);
3813 return !shape.IsExternal();
3814}
3815
3816
3817Local<v8::Object> v8::Object::New() {
3818 EnsureInitialized("v8::Object::New()");
3819 LOG_API("Object::New");
3820 ENTER_V8;
3821 i::Handle<i::JSObject> obj =
3822 i::Factory::NewJSObject(i::Top::object_function());
3823 return Utils::ToLocal(obj);
3824}
3825
3826
3827Local<v8::Value> v8::Date::New(double time) {
3828 EnsureInitialized("v8::Date::New()");
3829 LOG_API("Date::New");
Steve Blockd0582a62009-12-15 09:54:21 +00003830 if (isnan(time)) {
3831 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3832 time = i::OS::nan_value();
3833 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003834 ENTER_V8;
3835 EXCEPTION_PREAMBLE();
3836 i::Handle<i::Object> obj =
3837 i::Execution::NewDate(time, &has_pending_exception);
3838 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3839 return Utils::ToLocal(obj);
3840}
3841
3842
3843double v8::Date::NumberValue() const {
3844 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3845 LOG_API("Date::NumberValue");
3846 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3847 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3848 return jsvalue->value()->Number();
3849}
3850
3851
Ben Murdochb0fe1622011-05-05 13:52:32 +01003852void v8::Date::DateTimeConfigurationChangeNotification() {
3853 ON_BAILOUT("v8::Date::DateTimeConfigurationChangeNotification()", return);
3854 LOG_API("Date::DateTimeConfigurationChangeNotification");
3855 ENTER_V8;
3856
3857 HandleScope scope;
3858
3859 // Get the function ResetDateCache (defined in date-delay.js).
3860 i::Handle<i::String> func_name_str =
3861 i::Factory::LookupAsciiSymbol("ResetDateCache");
3862 i::MaybeObject* result = i::Top::builtins()->GetProperty(*func_name_str);
3863 i::Object* object_func;
3864 if (!result->ToObject(&object_func)) {
3865 return;
3866 }
3867
3868 if (object_func->IsJSFunction()) {
3869 i::Handle<i::JSFunction> func =
3870 i::Handle<i::JSFunction>(i::JSFunction::cast(object_func));
3871
3872 // Call ResetDateCache(0 but expect no exceptions:
3873 bool caught_exception = false;
3874 i::Handle<i::Object> result =
3875 i::Execution::TryCall(func, i::Top::builtins(), 0, NULL,
3876 &caught_exception);
3877 }
3878}
3879
3880
Ben Murdochf87a2032010-10-22 12:50:53 +01003881static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
3882 char flags_buf[3];
3883 int num_flags = 0;
3884 if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
3885 if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
3886 if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
3887 ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
3888 return i::Factory::LookupSymbol(
3889 i::Vector<const char>(flags_buf, num_flags));
3890}
3891
3892
3893Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
3894 Flags flags) {
3895 EnsureInitialized("v8::RegExp::New()");
3896 LOG_API("RegExp::New");
3897 ENTER_V8;
3898 EXCEPTION_PREAMBLE();
3899 i::Handle<i::JSRegExp> obj = i::Execution::NewJSRegExp(
3900 Utils::OpenHandle(*pattern),
3901 RegExpFlagsToString(flags),
3902 &has_pending_exception);
3903 EXCEPTION_BAILOUT_CHECK(Local<v8::RegExp>());
3904 return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
3905}
3906
3907
3908Local<v8::String> v8::RegExp::GetSource() const {
3909 if (IsDeadCheck("v8::RegExp::GetSource()")) return Local<v8::String>();
3910 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
3911 return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
3912}
3913
3914
3915// Assert that the static flags cast in GetFlags is valid.
3916#define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \
3917 STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \
3918 static_cast<int>(i::JSRegExp::internal_flag))
3919REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
3920REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
3921REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
3922REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
3923#undef REGEXP_FLAG_ASSERT_EQ
3924
3925v8::RegExp::Flags v8::RegExp::GetFlags() const {
3926 if (IsDeadCheck("v8::RegExp::GetFlags()")) return v8::RegExp::kNone;
3927 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
3928 return static_cast<RegExp::Flags>(obj->GetFlags().value());
3929}
3930
3931
Steve Blocka7e24c12009-10-30 11:49:00 +00003932Local<v8::Array> v8::Array::New(int length) {
3933 EnsureInitialized("v8::Array::New()");
3934 LOG_API("Array::New");
3935 ENTER_V8;
3936 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3937 return Utils::ToLocal(obj);
3938}
3939
3940
3941uint32_t v8::Array::Length() const {
3942 if (IsDeadCheck("v8::Array::Length()")) return 0;
3943 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3944 i::Object* length = obj->length();
3945 if (length->IsSmi()) {
3946 return i::Smi::cast(length)->value();
3947 } else {
3948 return static_cast<uint32_t>(length->Number());
3949 }
3950}
3951
3952
3953Local<Object> Array::CloneElementAt(uint32_t index) {
3954 ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3955 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3956 if (!self->HasFastElements()) {
3957 return Local<Object>();
3958 }
3959 i::FixedArray* elms = i::FixedArray::cast(self->elements());
3960 i::Object* paragon = elms->get(index);
3961 if (!paragon->IsJSObject()) {
3962 return Local<Object>();
3963 }
3964 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3965 EXCEPTION_PREAMBLE();
Steve Block6ded16b2010-05-10 14:33:55 +01003966 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003967 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3968 has_pending_exception = result.is_null();
3969 EXCEPTION_BAILOUT_CHECK(Local<Object>());
3970 return Utils::ToLocal(result);
3971}
3972
3973
3974Local<String> v8::String::NewSymbol(const char* data, int length) {
3975 EnsureInitialized("v8::String::NewSymbol()");
3976 LOG_API("String::NewSymbol(char)");
3977 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003978 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003979 i::Handle<i::String> result =
3980 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3981 return Utils::ToLocal(result);
3982}
3983
3984
3985Local<Number> v8::Number::New(double value) {
3986 EnsureInitialized("v8::Number::New()");
Steve Blockd0582a62009-12-15 09:54:21 +00003987 if (isnan(value)) {
3988 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3989 value = i::OS::nan_value();
3990 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003991 ENTER_V8;
3992 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3993 return Utils::NumberToLocal(result);
3994}
3995
3996
3997Local<Integer> v8::Integer::New(int32_t value) {
3998 EnsureInitialized("v8::Integer::New()");
3999 if (i::Smi::IsValid(value)) {
4000 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
4001 }
4002 ENTER_V8;
4003 i::Handle<i::Object> result = i::Factory::NewNumber(value);
4004 return Utils::IntegerToLocal(result);
4005}
4006
4007
Steve Block3ce2e202009-11-05 08:53:23 +00004008Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
4009 bool fits_into_int32_t = (value & (1 << 31)) == 0;
4010 if (fits_into_int32_t) {
4011 return Integer::New(static_cast<int32_t>(value));
4012 }
4013 ENTER_V8;
4014 i::Handle<i::Object> result = i::Factory::NewNumber(value);
4015 return Utils::IntegerToLocal(result);
4016}
4017
4018
Steve Blocka7e24c12009-10-30 11:49:00 +00004019void V8::IgnoreOutOfMemoryException() {
4020 thread_local.set_ignore_out_of_memory(true);
4021}
4022
4023
4024bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
4025 EnsureInitialized("v8::V8::AddMessageListener()");
4026 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
4027 ENTER_V8;
4028 HandleScope scope;
4029 NeanderArray listeners(i::Factory::message_listeners());
4030 NeanderObject obj(2);
4031 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
4032 obj.set(1, data.IsEmpty() ?
4033 i::Heap::undefined_value() :
4034 *Utils::OpenHandle(*data));
4035 listeners.add(obj.value());
4036 return true;
4037}
4038
4039
4040void V8::RemoveMessageListeners(MessageCallback that) {
4041 EnsureInitialized("v8::V8::RemoveMessageListener()");
4042 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
4043 ENTER_V8;
4044 HandleScope scope;
4045 NeanderArray listeners(i::Factory::message_listeners());
4046 for (int i = 0; i < listeners.length(); i++) {
4047 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
4048
4049 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
4050 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
4051 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
4052 listeners.set(i, i::Heap::undefined_value());
4053 }
4054 }
4055}
4056
4057
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004058void V8::SetCaptureStackTraceForUncaughtExceptions(
4059 bool capture,
4060 int frame_limit,
4061 StackTrace::StackTraceOptions options) {
4062 i::Top::SetCaptureStackTraceForUncaughtExceptions(
4063 capture,
4064 frame_limit,
4065 options);
4066}
4067
4068
Steve Blocka7e24c12009-10-30 11:49:00 +00004069void V8::SetCounterFunction(CounterLookupCallback callback) {
4070 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
4071 i::StatsTable::SetCounterFunction(callback);
4072}
4073
4074void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
4075 if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
4076 i::StatsTable::SetCreateHistogramFunction(callback);
4077}
4078
4079void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
4080 if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
4081 i::StatsTable::SetAddHistogramSampleFunction(callback);
4082}
4083
4084void V8::EnableSlidingStateWindow() {
4085 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
4086 i::Logger::EnableSlidingStateWindow();
4087}
4088
4089
4090void V8::SetFailedAccessCheckCallbackFunction(
4091 FailedAccessCheckCallback callback) {
4092 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
4093 i::Top::SetFailedAccessCheckCallback(callback);
4094}
4095
4096
4097void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
4098 if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
4099 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
4100 i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
4101}
4102
4103
4104int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
4105 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
4106 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
4107}
4108
4109
4110void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
4111 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
4112 i::Heap::SetGlobalGCPrologueCallback(callback);
4113}
4114
4115
4116void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
4117 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
4118 i::Heap::SetGlobalGCEpilogueCallback(callback);
4119}
4120
4121
Steve Block6ded16b2010-05-10 14:33:55 +01004122void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
4123 if (IsDeadCheck("v8::V8::AddGCPrologueCallback()")) return;
4124 i::Heap::AddGCPrologueCallback(callback, gc_type);
4125}
4126
4127
4128void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
4129 if (IsDeadCheck("v8::V8::RemoveGCPrologueCallback()")) return;
4130 i::Heap::RemoveGCPrologueCallback(callback);
4131}
4132
4133
4134void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
4135 if (IsDeadCheck("v8::V8::AddGCEpilogueCallback()")) return;
4136 i::Heap::AddGCEpilogueCallback(callback, gc_type);
4137}
4138
4139
4140void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
4141 if (IsDeadCheck("v8::V8::RemoveGCEpilogueCallback()")) return;
4142 i::Heap::RemoveGCEpilogueCallback(callback);
4143}
4144
4145
Iain Merrick9ac36c92010-09-13 15:29:50 +01004146void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
4147 ObjectSpace space,
4148 AllocationAction action) {
4149 if (IsDeadCheck("v8::V8::AddMemoryAllocationCallback()")) return;
4150 i::MemoryAllocator::AddMemoryAllocationCallback(callback,
4151 space,
4152 action);
4153}
4154
4155
4156void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
4157 if (IsDeadCheck("v8::V8::RemoveMemoryAllocationCallback()")) return;
4158 i::MemoryAllocator::RemoveMemoryAllocationCallback(callback);
4159}
4160
4161
Steve Blocka7e24c12009-10-30 11:49:00 +00004162void V8::PauseProfiler() {
4163#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004164 PauseProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00004165#endif
4166}
4167
4168
4169void V8::ResumeProfiler() {
4170#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004171 ResumeProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00004172#endif
4173}
4174
4175
4176bool V8::IsProfilerPaused() {
4177#ifdef ENABLE_LOGGING_AND_PROFILING
4178 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
4179#else
4180 return true;
4181#endif
4182}
4183
4184
Andrei Popescu402d9372010-02-26 13:31:12 +00004185void V8::ResumeProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004186#ifdef ENABLE_LOGGING_AND_PROFILING
4187 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
4188 // Snapshot mode: resume modules, perform GC, then pause only
4189 // those modules which haven't been started prior to making a
4190 // snapshot.
4191
Steve Block6ded16b2010-05-10 14:33:55 +01004192 // Make a GC prior to taking a snapshot.
4193 i::Heap::CollectAllGarbage(false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004194 // Reset snapshot flag and CPU module flags.
4195 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
4196 const int current_flags = i::Logger::GetActiveProfilerModules();
Andrei Popescu402d9372010-02-26 13:31:12 +00004197 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004198 i::Heap::CollectAllGarbage(false);
Andrei Popescu402d9372010-02-26 13:31:12 +00004199 i::Logger::PauseProfiler(~current_flags & flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004200 } else {
Andrei Popescu402d9372010-02-26 13:31:12 +00004201 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004202 }
4203#endif
4204}
4205
4206
Andrei Popescu402d9372010-02-26 13:31:12 +00004207void V8::PauseProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004208#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004209 i::Logger::PauseProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004210#endif
4211}
4212
4213
4214int V8::GetActiveProfilerModules() {
4215#ifdef ENABLE_LOGGING_AND_PROFILING
4216 return i::Logger::GetActiveProfilerModules();
4217#else
4218 return PROFILER_MODULE_NONE;
4219#endif
4220}
4221
4222
4223int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
4224#ifdef ENABLE_LOGGING_AND_PROFILING
Steve Block6ded16b2010-05-10 14:33:55 +01004225 ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
Steve Blocka7e24c12009-10-30 11:49:00 +00004226 return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
4227#endif
4228 return 0;
4229}
4230
4231
4232int V8::GetCurrentThreadId() {
4233 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
4234 EnsureInitialized("V8::GetCurrentThreadId()");
4235 return i::Top::thread_id();
4236}
4237
4238
4239void V8::TerminateExecution(int thread_id) {
4240 if (!i::V8::IsRunning()) return;
4241 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
4242 // If the thread_id identifies the current thread just terminate
4243 // execution right away. Otherwise, ask the thread manager to
4244 // terminate the thread with the given id if any.
4245 if (thread_id == i::Top::thread_id()) {
4246 i::StackGuard::TerminateExecution();
4247 } else {
4248 i::ThreadManager::TerminateExecution(thread_id);
4249 }
4250}
4251
4252
4253void V8::TerminateExecution() {
4254 if (!i::V8::IsRunning()) return;
4255 i::StackGuard::TerminateExecution();
4256}
4257
4258
Steve Block6ded16b2010-05-10 14:33:55 +01004259bool V8::IsExecutionTerminating() {
4260 if (!i::V8::IsRunning()) return false;
4261 if (i::Top::has_scheduled_exception()) {
4262 return i::Top::scheduled_exception() == i::Heap::termination_exception();
4263 }
4264 return false;
4265}
4266
4267
Steve Blocka7e24c12009-10-30 11:49:00 +00004268String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
4269 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
4270 if (obj.IsEmpty()) {
4271 str_ = NULL;
4272 length_ = 0;
4273 return;
4274 }
4275 ENTER_V8;
4276 HandleScope scope;
4277 TryCatch try_catch;
4278 Handle<String> str = obj->ToString();
4279 if (str.IsEmpty()) {
4280 str_ = NULL;
4281 length_ = 0;
4282 } else {
4283 length_ = str->Utf8Length();
4284 str_ = i::NewArray<char>(length_ + 1);
4285 str->WriteUtf8(str_);
4286 }
4287}
4288
4289
4290String::Utf8Value::~Utf8Value() {
4291 i::DeleteArray(str_);
4292}
4293
4294
4295String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
4296 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
4297 if (obj.IsEmpty()) {
4298 str_ = NULL;
4299 length_ = 0;
4300 return;
4301 }
4302 ENTER_V8;
4303 HandleScope scope;
4304 TryCatch try_catch;
4305 Handle<String> str = obj->ToString();
4306 if (str.IsEmpty()) {
4307 str_ = NULL;
4308 length_ = 0;
4309 } else {
4310 length_ = str->Length();
4311 str_ = i::NewArray<char>(length_ + 1);
4312 str->WriteAscii(str_);
4313 }
4314}
4315
4316
4317String::AsciiValue::~AsciiValue() {
4318 i::DeleteArray(str_);
4319}
4320
4321
4322String::Value::Value(v8::Handle<v8::Value> obj) {
4323 EnsureInitialized("v8::String::Value::Value()");
4324 if (obj.IsEmpty()) {
4325 str_ = NULL;
4326 length_ = 0;
4327 return;
4328 }
4329 ENTER_V8;
4330 HandleScope scope;
4331 TryCatch try_catch;
4332 Handle<String> str = obj->ToString();
4333 if (str.IsEmpty()) {
4334 str_ = NULL;
4335 length_ = 0;
4336 } else {
4337 length_ = str->Length();
4338 str_ = i::NewArray<uint16_t>(length_ + 1);
4339 str->Write(str_);
4340 }
4341}
4342
4343
4344String::Value::~Value() {
4345 i::DeleteArray(str_);
4346}
4347
4348Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
4349 LOG_API("RangeError");
4350 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
4351 ENTER_V8;
4352 i::Object* error;
4353 {
4354 HandleScope scope;
4355 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4356 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
4357 error = *result;
4358 }
4359 i::Handle<i::Object> result(error);
4360 return Utils::ToLocal(result);
4361}
4362
4363Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
4364 LOG_API("ReferenceError");
4365 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
4366 ENTER_V8;
4367 i::Object* error;
4368 {
4369 HandleScope scope;
4370 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4371 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
4372 error = *result;
4373 }
4374 i::Handle<i::Object> result(error);
4375 return Utils::ToLocal(result);
4376}
4377
4378Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
4379 LOG_API("SyntaxError");
4380 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
4381 ENTER_V8;
4382 i::Object* error;
4383 {
4384 HandleScope scope;
4385 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4386 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
4387 error = *result;
4388 }
4389 i::Handle<i::Object> result(error);
4390 return Utils::ToLocal(result);
4391}
4392
4393Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
4394 LOG_API("TypeError");
4395 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
4396 ENTER_V8;
4397 i::Object* error;
4398 {
4399 HandleScope scope;
4400 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4401 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
4402 error = *result;
4403 }
4404 i::Handle<i::Object> result(error);
4405 return Utils::ToLocal(result);
4406}
4407
4408Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
4409 LOG_API("Error");
4410 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
4411 ENTER_V8;
4412 i::Object* error;
4413 {
4414 HandleScope scope;
4415 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4416 i::Handle<i::Object> result = i::Factory::NewError(message);
4417 error = *result;
4418 }
4419 i::Handle<i::Object> result(error);
4420 return Utils::ToLocal(result);
4421}
4422
4423
4424// --- D e b u g S u p p o r t ---
4425
4426#ifdef ENABLE_DEBUGGER_SUPPORT
Leon Clarkef7060e22010-06-03 12:02:55 +01004427
4428static v8::Debug::EventCallback event_callback = NULL;
4429
4430static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) {
4431 if (event_callback) {
4432 event_callback(event_details.GetEvent(),
4433 event_details.GetExecutionState(),
4434 event_details.GetEventData(),
4435 event_details.GetCallbackData());
4436 }
4437}
4438
4439
Steve Blocka7e24c12009-10-30 11:49:00 +00004440bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
4441 EnsureInitialized("v8::Debug::SetDebugEventListener()");
4442 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4443 ENTER_V8;
Leon Clarkef7060e22010-06-03 12:02:55 +01004444
4445 event_callback = that;
4446
4447 HandleScope scope;
4448 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4449 if (that != NULL) {
4450 proxy = i::Factory::NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
4451 }
4452 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4453 return true;
4454}
4455
4456
4457bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
4458 EnsureInitialized("v8::Debug::SetDebugEventListener2()");
4459 ON_BAILOUT("v8::Debug::SetDebugEventListener2()", return false);
4460 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004461 HandleScope scope;
4462 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4463 if (that != NULL) {
4464 proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
4465 }
4466 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4467 return true;
4468}
4469
4470
4471bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
4472 Handle<Value> data) {
4473 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4474 ENTER_V8;
4475 i::Debugger::SetEventListener(Utils::OpenHandle(*that),
4476 Utils::OpenHandle(*data));
4477 return true;
4478}
4479
4480
4481void Debug::DebugBreak() {
4482 if (!i::V8::IsRunning()) return;
4483 i::StackGuard::DebugBreak();
4484}
4485
4486
Ben Murdochf87a2032010-10-22 12:50:53 +01004487void Debug::CancelDebugBreak() {
4488 i::StackGuard::Continue(i::DEBUGBREAK);
4489}
4490
4491
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004492void Debug::DebugBreakForCommand(ClientData* data) {
4493 if (!i::V8::IsRunning()) return;
4494 i::Debugger::EnqueueDebugCommand(data);
4495}
4496
4497
Steve Blocka7e24c12009-10-30 11:49:00 +00004498static v8::Debug::MessageHandler message_handler = NULL;
4499
4500static void MessageHandlerWrapper(const v8::Debug::Message& message) {
4501 if (message_handler) {
4502 v8::String::Value json(message.GetJSON());
4503 message_handler(*json, json.length(), message.GetClientData());
4504 }
4505}
4506
4507
4508void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
4509 bool message_handler_thread) {
4510 EnsureInitialized("v8::Debug::SetMessageHandler");
4511 ENTER_V8;
4512 // Message handler thread not supported any more. Parameter temporally left in
4513 // the API for client compatability reasons.
4514 CHECK(!message_handler_thread);
4515
4516 // TODO(sgjesse) support the old message handler API through a simple wrapper.
4517 message_handler = handler;
4518 if (message_handler != NULL) {
4519 i::Debugger::SetMessageHandler(MessageHandlerWrapper);
4520 } else {
4521 i::Debugger::SetMessageHandler(NULL);
4522 }
4523}
4524
4525
4526void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
4527 EnsureInitialized("v8::Debug::SetMessageHandler");
4528 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004529 i::Debugger::SetMessageHandler(handler);
4530}
4531
4532
4533void Debug::SendCommand(const uint16_t* command, int length,
4534 ClientData* client_data) {
4535 if (!i::V8::IsRunning()) return;
4536 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
4537 client_data);
4538}
4539
4540
4541void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
4542 int period) {
4543 EnsureInitialized("v8::Debug::SetHostDispatchHandler");
4544 ENTER_V8;
4545 i::Debugger::SetHostDispatchHandler(handler, period);
4546}
4547
4548
Steve Blockd0582a62009-12-15 09:54:21 +00004549void Debug::SetDebugMessageDispatchHandler(
Leon Clarkee46be812010-01-19 14:06:41 +00004550 DebugMessageDispatchHandler handler, bool provide_locker) {
Steve Blockd0582a62009-12-15 09:54:21 +00004551 EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
4552 ENTER_V8;
Leon Clarkee46be812010-01-19 14:06:41 +00004553 i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
Steve Blockd0582a62009-12-15 09:54:21 +00004554}
4555
4556
Steve Blocka7e24c12009-10-30 11:49:00 +00004557Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
4558 v8::Handle<v8::Value> data) {
4559 if (!i::V8::IsRunning()) return Local<Value>();
4560 ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
4561 ENTER_V8;
4562 i::Handle<i::Object> result;
4563 EXCEPTION_PREAMBLE();
4564 if (data.IsEmpty()) {
4565 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4566 i::Factory::undefined_value(),
4567 &has_pending_exception);
4568 } else {
4569 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4570 Utils::OpenHandle(*data),
4571 &has_pending_exception);
4572 }
4573 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4574 return Utils::ToLocal(result);
4575}
4576
4577
4578Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
4579 if (!i::V8::IsRunning()) return Local<Value>();
4580 ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
4581 ENTER_V8;
4582 v8::HandleScope scope;
4583 i::Debug::Load();
4584 i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
4585 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
4586 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
4587 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
4588 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
4589 const int kArgc = 1;
4590 v8::Handle<v8::Value> argv[kArgc] = { obj };
4591 EXCEPTION_PREAMBLE();
4592 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
4593 kArgc,
4594 argv);
4595 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4596 return scope.Close(result);
4597}
4598
4599
Leon Clarkee46be812010-01-19 14:06:41 +00004600bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
4601 return i::Debugger::StartAgent(name, port, wait_for_connection);
Steve Blocka7e24c12009-10-30 11:49:00 +00004602}
Leon Clarkee46be812010-01-19 14:06:41 +00004603
4604void Debug::ProcessDebugMessages() {
4605 i::Execution::ProcessDebugMesssages(true);
4606}
4607
Steve Block6ded16b2010-05-10 14:33:55 +01004608Local<Context> Debug::GetDebugContext() {
4609 EnsureInitialized("v8::Debug::GetDebugContext()");
4610 ENTER_V8;
4611 return Utils::ToLocal(i::Debugger::GetDebugContext());
4612}
4613
Steve Blocka7e24c12009-10-30 11:49:00 +00004614#endif // ENABLE_DEBUGGER_SUPPORT
4615
Steve Block6ded16b2010-05-10 14:33:55 +01004616
4617#ifdef ENABLE_LOGGING_AND_PROFILING
4618
4619Handle<String> CpuProfileNode::GetFunctionName() const {
4620 IsDeadCheck("v8::CpuProfileNode::GetFunctionName");
4621 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4622 const i::CodeEntry* entry = node->entry();
4623 if (!entry->has_name_prefix()) {
4624 return Handle<String>(ToApi<String>(
4625 i::Factory::LookupAsciiSymbol(entry->name())));
4626 } else {
4627 return Handle<String>(ToApi<String>(i::Factory::NewConsString(
4628 i::Factory::LookupAsciiSymbol(entry->name_prefix()),
4629 i::Factory::LookupAsciiSymbol(entry->name()))));
4630 }
4631}
4632
4633
4634Handle<String> CpuProfileNode::GetScriptResourceName() const {
4635 IsDeadCheck("v8::CpuProfileNode::GetScriptResourceName");
4636 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4637 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4638 node->entry()->resource_name())));
4639}
4640
4641
4642int CpuProfileNode::GetLineNumber() const {
4643 IsDeadCheck("v8::CpuProfileNode::GetLineNumber");
4644 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
4645}
4646
4647
4648double CpuProfileNode::GetTotalTime() const {
4649 IsDeadCheck("v8::CpuProfileNode::GetTotalTime");
4650 return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis();
4651}
4652
4653
4654double CpuProfileNode::GetSelfTime() const {
4655 IsDeadCheck("v8::CpuProfileNode::GetSelfTime");
4656 return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis();
4657}
4658
4659
4660double CpuProfileNode::GetTotalSamplesCount() const {
4661 IsDeadCheck("v8::CpuProfileNode::GetTotalSamplesCount");
4662 return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
4663}
4664
4665
4666double CpuProfileNode::GetSelfSamplesCount() const {
4667 IsDeadCheck("v8::CpuProfileNode::GetSelfSamplesCount");
4668 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
4669}
4670
4671
4672unsigned CpuProfileNode::GetCallUid() const {
4673 IsDeadCheck("v8::CpuProfileNode::GetCallUid");
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004674 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
Steve Block6ded16b2010-05-10 14:33:55 +01004675}
4676
4677
4678int CpuProfileNode::GetChildrenCount() const {
4679 IsDeadCheck("v8::CpuProfileNode::GetChildrenCount");
4680 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
4681}
4682
4683
4684const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
4685 IsDeadCheck("v8::CpuProfileNode::GetChild");
4686 const i::ProfileNode* child =
4687 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
4688 return reinterpret_cast<const CpuProfileNode*>(child);
4689}
4690
4691
4692unsigned CpuProfile::GetUid() const {
4693 IsDeadCheck("v8::CpuProfile::GetUid");
4694 return reinterpret_cast<const i::CpuProfile*>(this)->uid();
4695}
4696
4697
4698Handle<String> CpuProfile::GetTitle() const {
4699 IsDeadCheck("v8::CpuProfile::GetTitle");
4700 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4701 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4702 profile->title())));
4703}
4704
4705
4706const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
4707 IsDeadCheck("v8::CpuProfile::GetBottomUpRoot");
4708 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4709 return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
4710}
4711
4712
4713const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
4714 IsDeadCheck("v8::CpuProfile::GetTopDownRoot");
4715 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4716 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
4717}
4718
4719
4720int CpuProfiler::GetProfilesCount() {
4721 IsDeadCheck("v8::CpuProfiler::GetProfilesCount");
4722 return i::CpuProfiler::GetProfilesCount();
4723}
4724
4725
Leon Clarkef7060e22010-06-03 12:02:55 +01004726const CpuProfile* CpuProfiler::GetProfile(int index,
4727 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004728 IsDeadCheck("v8::CpuProfiler::GetProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004729 return reinterpret_cast<const CpuProfile*>(
4730 i::CpuProfiler::GetProfile(
4731 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4732 index));
Steve Block6ded16b2010-05-10 14:33:55 +01004733}
4734
4735
Leon Clarkef7060e22010-06-03 12:02:55 +01004736const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
4737 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004738 IsDeadCheck("v8::CpuProfiler::FindProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004739 return reinterpret_cast<const CpuProfile*>(
4740 i::CpuProfiler::FindProfile(
4741 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4742 uid));
Steve Block6ded16b2010-05-10 14:33:55 +01004743}
4744
4745
4746void CpuProfiler::StartProfiling(Handle<String> title) {
4747 IsDeadCheck("v8::CpuProfiler::StartProfiling");
4748 i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
4749}
4750
4751
Leon Clarkef7060e22010-06-03 12:02:55 +01004752const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
4753 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004754 IsDeadCheck("v8::CpuProfiler::StopProfiling");
4755 return reinterpret_cast<const CpuProfile*>(
Leon Clarkef7060e22010-06-03 12:02:55 +01004756 i::CpuProfiler::StopProfiling(
4757 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4758 *Utils::OpenHandle(*title)));
Steve Block6ded16b2010-05-10 14:33:55 +01004759}
4760
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004761
Iain Merrick75681382010-08-19 15:07:18 +01004762static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
4763 return const_cast<i::HeapGraphEdge*>(
4764 reinterpret_cast<const i::HeapGraphEdge*>(edge));
4765}
4766
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004767HeapGraphEdge::Type HeapGraphEdge::GetType() const {
4768 IsDeadCheck("v8::HeapGraphEdge::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004769 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004770}
4771
4772
4773Handle<Value> HeapGraphEdge::GetName() const {
4774 IsDeadCheck("v8::HeapGraphEdge::GetName");
Iain Merrick75681382010-08-19 15:07:18 +01004775 i::HeapGraphEdge* edge = ToInternal(this);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004776 switch (edge->type()) {
Iain Merrick75681382010-08-19 15:07:18 +01004777 case i::HeapGraphEdge::kContextVariable:
4778 case i::HeapGraphEdge::kInternal:
4779 case i::HeapGraphEdge::kProperty:
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004780 case i::HeapGraphEdge::kShortcut:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004781 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4782 edge->name())));
Iain Merrick75681382010-08-19 15:07:18 +01004783 case i::HeapGraphEdge::kElement:
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004784 case i::HeapGraphEdge::kHidden:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004785 return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt(
4786 edge->index())));
4787 default: UNREACHABLE();
4788 }
4789 return ImplementationUtilities::Undefined();
4790}
4791
4792
4793const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
4794 IsDeadCheck("v8::HeapGraphEdge::GetFromNode");
Iain Merrick75681382010-08-19 15:07:18 +01004795 const i::HeapEntry* from = ToInternal(this)->From();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004796 return reinterpret_cast<const HeapGraphNode*>(from);
4797}
4798
4799
4800const HeapGraphNode* HeapGraphEdge::GetToNode() const {
4801 IsDeadCheck("v8::HeapGraphEdge::GetToNode");
Iain Merrick75681382010-08-19 15:07:18 +01004802 const i::HeapEntry* to = ToInternal(this)->to();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004803 return reinterpret_cast<const HeapGraphNode*>(to);
4804}
4805
4806
Iain Merrick75681382010-08-19 15:07:18 +01004807static i::HeapGraphPath* ToInternal(const HeapGraphPath* path) {
4808 return const_cast<i::HeapGraphPath*>(
4809 reinterpret_cast<const i::HeapGraphPath*>(path));
4810}
4811
4812
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004813int HeapGraphPath::GetEdgesCount() const {
Iain Merrick75681382010-08-19 15:07:18 +01004814 return ToInternal(this)->path()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004815}
4816
4817
4818const HeapGraphEdge* HeapGraphPath::GetEdge(int index) const {
4819 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004820 ToInternal(this)->path()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004821}
4822
4823
4824const HeapGraphNode* HeapGraphPath::GetFromNode() const {
4825 return GetEdgesCount() > 0 ? GetEdge(0)->GetFromNode() : NULL;
4826}
4827
4828
4829const HeapGraphNode* HeapGraphPath::GetToNode() const {
4830 const int count = GetEdgesCount();
4831 return count > 0 ? GetEdge(count - 1)->GetToNode() : NULL;
4832}
4833
4834
Iain Merrick75681382010-08-19 15:07:18 +01004835static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
4836 return const_cast<i::HeapEntry*>(
4837 reinterpret_cast<const i::HeapEntry*>(entry));
4838}
4839
4840
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004841HeapGraphNode::Type HeapGraphNode::GetType() const {
4842 IsDeadCheck("v8::HeapGraphNode::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004843 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004844}
4845
4846
4847Handle<String> HeapGraphNode::GetName() const {
4848 IsDeadCheck("v8::HeapGraphNode::GetName");
4849 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004850 ToInternal(this)->name())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004851}
4852
4853
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004854uint64_t HeapGraphNode::GetId() const {
4855 IsDeadCheck("v8::HeapGraphNode::GetId");
Steve Block791712a2010-08-27 10:21:07 +01004856 ASSERT(ToInternal(this)->snapshot()->type() != i::HeapSnapshot::kAggregated);
Iain Merrick75681382010-08-19 15:07:18 +01004857 return ToInternal(this)->id();
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004858}
4859
4860
Steve Block791712a2010-08-27 10:21:07 +01004861int HeapGraphNode::GetInstancesCount() const {
4862 IsDeadCheck("v8::HeapGraphNode::GetInstancesCount");
4863 ASSERT(ToInternal(this)->snapshot()->type() == i::HeapSnapshot::kAggregated);
4864 return static_cast<int>(ToInternal(this)->id());
4865}
4866
4867
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004868int HeapGraphNode::GetSelfSize() const {
4869 IsDeadCheck("v8::HeapGraphNode::GetSelfSize");
Iain Merrick75681382010-08-19 15:07:18 +01004870 return ToInternal(this)->self_size();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004871}
4872
4873
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004874int HeapGraphNode::GetRetainedSize(bool exact) const {
Iain Merrick75681382010-08-19 15:07:18 +01004875 IsDeadCheck("v8::HeapSnapshot::GetRetainedSize");
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004876 return ToInternal(this)->RetainedSize(exact);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004877}
4878
4879
4880int HeapGraphNode::GetChildrenCount() const {
4881 IsDeadCheck("v8::HeapSnapshot::GetChildrenCount");
Iain Merrick75681382010-08-19 15:07:18 +01004882 return ToInternal(this)->children().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004883}
4884
4885
4886const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
4887 IsDeadCheck("v8::HeapSnapshot::GetChild");
4888 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004889 &ToInternal(this)->children()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004890}
4891
4892
4893int HeapGraphNode::GetRetainersCount() const {
4894 IsDeadCheck("v8::HeapSnapshot::GetRetainersCount");
Iain Merrick75681382010-08-19 15:07:18 +01004895 return ToInternal(this)->retainers().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004896}
4897
4898
4899const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const {
4900 IsDeadCheck("v8::HeapSnapshot::GetRetainer");
4901 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004902 ToInternal(this)->retainers()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004903}
4904
4905
4906int HeapGraphNode::GetRetainingPathsCount() const {
4907 IsDeadCheck("v8::HeapSnapshot::GetRetainingPathsCount");
Iain Merrick75681382010-08-19 15:07:18 +01004908 return ToInternal(this)->GetRetainingPaths()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004909}
4910
4911
4912const HeapGraphPath* HeapGraphNode::GetRetainingPath(int index) const {
4913 IsDeadCheck("v8::HeapSnapshot::GetRetainingPath");
4914 return reinterpret_cast<const HeapGraphPath*>(
Iain Merrick75681382010-08-19 15:07:18 +01004915 ToInternal(this)->GetRetainingPaths()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004916}
4917
4918
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004919const HeapGraphNode* HeapGraphNode::GetDominatorNode() const {
4920 IsDeadCheck("v8::HeapSnapshot::GetDominatorNode");
4921 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->dominator());
4922}
4923
4924
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004925const HeapGraphNode* HeapSnapshotsDiff::GetAdditionsRoot() const {
4926 IsDeadCheck("v8::HeapSnapshotsDiff::GetAdditionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004927 i::HeapSnapshotsDiff* diff =
4928 const_cast<i::HeapSnapshotsDiff*>(
4929 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004930 return reinterpret_cast<const HeapGraphNode*>(diff->additions_root());
4931}
4932
4933
4934const HeapGraphNode* HeapSnapshotsDiff::GetDeletionsRoot() const {
4935 IsDeadCheck("v8::HeapSnapshotsDiff::GetDeletionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004936 i::HeapSnapshotsDiff* diff =
4937 const_cast<i::HeapSnapshotsDiff*>(
4938 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004939 return reinterpret_cast<const HeapGraphNode*>(diff->deletions_root());
4940}
4941
4942
Iain Merrick75681382010-08-19 15:07:18 +01004943static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
4944 return const_cast<i::HeapSnapshot*>(
4945 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
4946}
4947
4948
Steve Block791712a2010-08-27 10:21:07 +01004949HeapSnapshot::Type HeapSnapshot::GetType() const {
4950 IsDeadCheck("v8::HeapSnapshot::GetType");
4951 return static_cast<HeapSnapshot::Type>(ToInternal(this)->type());
4952}
4953
4954
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004955unsigned HeapSnapshot::GetUid() const {
4956 IsDeadCheck("v8::HeapSnapshot::GetUid");
Iain Merrick75681382010-08-19 15:07:18 +01004957 return ToInternal(this)->uid();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004958}
4959
4960
4961Handle<String> HeapSnapshot::GetTitle() const {
4962 IsDeadCheck("v8::HeapSnapshot::GetTitle");
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004963 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004964 ToInternal(this)->title())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004965}
4966
4967
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004968const HeapGraphNode* HeapSnapshot::GetRoot() const {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004969 IsDeadCheck("v8::HeapSnapshot::GetHead");
Iain Merrick75681382010-08-19 15:07:18 +01004970 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004971}
4972
4973
Ben Murdochb0fe1622011-05-05 13:52:32 +01004974const HeapGraphNode* HeapSnapshot::GetNodeById(uint64_t id) const {
4975 IsDeadCheck("v8::HeapSnapshot::GetNodeById");
4976 return reinterpret_cast<const HeapGraphNode*>(
4977 ToInternal(this)->GetEntryById(id));
4978}
4979
4980
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004981const HeapSnapshotsDiff* HeapSnapshot::CompareWith(
4982 const HeapSnapshot* snapshot) const {
4983 IsDeadCheck("v8::HeapSnapshot::CompareWith");
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004984 return reinterpret_cast<const HeapSnapshotsDiff*>(
Iain Merrick75681382010-08-19 15:07:18 +01004985 ToInternal(this)->CompareWith(ToInternal(snapshot)));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004986}
4987
4988
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004989void HeapSnapshot::Serialize(OutputStream* stream,
4990 HeapSnapshot::SerializationFormat format) const {
4991 IsDeadCheck("v8::HeapSnapshot::Serialize");
4992 ApiCheck(format == kJSON,
4993 "v8::HeapSnapshot::Serialize",
4994 "Unknown serialization format");
4995 ApiCheck(stream->GetOutputEncoding() == OutputStream::kAscii,
4996 "v8::HeapSnapshot::Serialize",
4997 "Unsupported output encoding");
4998 ApiCheck(stream->GetChunkSize() > 0,
4999 "v8::HeapSnapshot::Serialize",
5000 "Invalid stream chunk size");
5001 i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
5002 serializer.Serialize(stream);
5003}
5004
5005
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005006int HeapProfiler::GetSnapshotsCount() {
5007 IsDeadCheck("v8::HeapProfiler::GetSnapshotsCount");
5008 return i::HeapProfiler::GetSnapshotsCount();
5009}
5010
5011
5012const HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
5013 IsDeadCheck("v8::HeapProfiler::GetSnapshot");
5014 return reinterpret_cast<const HeapSnapshot*>(
5015 i::HeapProfiler::GetSnapshot(index));
5016}
5017
5018
5019const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
5020 IsDeadCheck("v8::HeapProfiler::FindSnapshot");
5021 return reinterpret_cast<const HeapSnapshot*>(
5022 i::HeapProfiler::FindSnapshot(uid));
5023}
5024
5025
Steve Block791712a2010-08-27 10:21:07 +01005026const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title,
Ben Murdochb0fe1622011-05-05 13:52:32 +01005027 HeapSnapshot::Type type,
5028 ActivityControl* control) {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005029 IsDeadCheck("v8::HeapProfiler::TakeSnapshot");
Steve Block791712a2010-08-27 10:21:07 +01005030 i::HeapSnapshot::Type internal_type = i::HeapSnapshot::kFull;
5031 switch (type) {
5032 case HeapSnapshot::kFull:
5033 internal_type = i::HeapSnapshot::kFull;
5034 break;
5035 case HeapSnapshot::kAggregated:
5036 internal_type = i::HeapSnapshot::kAggregated;
5037 break;
5038 default:
5039 UNREACHABLE();
5040 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005041 return reinterpret_cast<const HeapSnapshot*>(
Ben Murdochb0fe1622011-05-05 13:52:32 +01005042 i::HeapProfiler::TakeSnapshot(
5043 *Utils::OpenHandle(*title), internal_type, control));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005044}
5045
Steve Block6ded16b2010-05-10 14:33:55 +01005046#endif // ENABLE_LOGGING_AND_PROFILING
5047
5048
Ben Murdochb0fe1622011-05-05 13:52:32 +01005049v8::Testing::StressType internal::Testing::stress_type_ =
5050 v8::Testing::kStressTypeOpt;
5051
5052
5053void Testing::SetStressRunType(Testing::StressType type) {
5054 internal::Testing::set_stress_type(type);
5055}
5056
5057int Testing::GetStressRuns() {
5058 if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs;
5059#ifdef DEBUG
5060 // In debug mode the code runs much slower so stressing will only make two
5061 // runs.
5062 return 2;
5063#else
5064 return 5;
5065#endif
5066}
5067
5068
5069static void SetFlagsFromString(const char* flags) {
5070 V8::SetFlagsFromString(flags, i::StrLength(flags));
5071}
5072
5073
5074void Testing::PrepareStressRun(int run) {
5075 static const char* kLazyOptimizations =
5076 "--prepare-always-opt --nolimit-inlining "
5077 "--noalways-opt --noopt-eagerly";
5078 static const char* kEagerOptimizations = "--opt-eagerly";
5079 static const char* kForcedOptimizations = "--always-opt";
5080
5081 // If deoptimization stressed turn on frequent deoptimization. If no value
5082 // is spefified through --deopt-every-n-times use a default default value.
5083 static const char* kDeoptEvery13Times = "--deopt-every-n-times=13";
5084 if (internal::Testing::stress_type() == Testing::kStressTypeDeopt &&
5085 internal::FLAG_deopt_every_n_times == 0) {
5086 SetFlagsFromString(kDeoptEvery13Times);
5087 }
5088
5089#ifdef DEBUG
5090 // As stressing in debug mode only make two runs skip the deopt stressing
5091 // here.
5092 if (run == GetStressRuns() - 1) {
5093 SetFlagsFromString(kForcedOptimizations);
5094 } else {
5095 SetFlagsFromString(kEagerOptimizations);
5096 SetFlagsFromString(kLazyOptimizations);
5097 }
5098#else
5099 if (run == GetStressRuns() - 1) {
5100 SetFlagsFromString(kForcedOptimizations);
5101 } else if (run == GetStressRuns() - 2) {
5102 SetFlagsFromString(kEagerOptimizations);
5103 } else {
5104 SetFlagsFromString(kLazyOptimizations);
5105 }
5106#endif
5107}
5108
5109
Steve Blocka7e24c12009-10-30 11:49:00 +00005110namespace internal {
5111
5112
5113HandleScopeImplementer* HandleScopeImplementer::instance() {
5114 return &thread_local;
5115}
5116
5117
5118void HandleScopeImplementer::FreeThreadResources() {
5119 thread_local.Free();
5120}
5121
5122
5123char* HandleScopeImplementer::ArchiveThread(char* storage) {
5124 return thread_local.ArchiveThreadHelper(storage);
5125}
5126
5127
5128char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
5129 v8::ImplementationUtilities::HandleScopeData* current =
5130 v8::ImplementationUtilities::CurrentHandleScope();
5131 handle_scope_data_ = *current;
5132 memcpy(storage, this, sizeof(*this));
5133
5134 ResetAfterArchive();
5135 current->Initialize();
5136
5137 return storage + ArchiveSpacePerThread();
5138}
5139
5140
5141int HandleScopeImplementer::ArchiveSpacePerThread() {
5142 return sizeof(thread_local);
5143}
5144
5145
5146char* HandleScopeImplementer::RestoreThread(char* storage) {
5147 return thread_local.RestoreThreadHelper(storage);
5148}
5149
5150
5151char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
5152 memcpy(this, storage, sizeof(*this));
5153 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
5154 return storage + ArchiveSpacePerThread();
5155}
5156
5157
5158void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
5159 // Iterate over all handles in the blocks except for the last.
5160 for (int i = blocks()->length() - 2; i >= 0; --i) {
5161 Object** block = blocks()->at(i);
5162 v->VisitPointers(block, &block[kHandleBlockSize]);
5163 }
5164
5165 // Iterate over live handles in the last block (if any).
5166 if (!blocks()->is_empty()) {
5167 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
5168 }
5169
5170 if (!saved_contexts_.is_empty()) {
5171 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
5172 v->VisitPointers(start, start + saved_contexts_.length());
5173 }
5174}
5175
5176
5177void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
5178 v8::ImplementationUtilities::HandleScopeData* current =
5179 v8::ImplementationUtilities::CurrentHandleScope();
5180 thread_local.handle_scope_data_ = *current;
5181 thread_local.IterateThis(v);
5182}
5183
5184
5185char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
5186 HandleScopeImplementer* thread_local =
5187 reinterpret_cast<HandleScopeImplementer*>(storage);
5188 thread_local->IterateThis(v);
5189 return storage + ArchiveSpacePerThread();
5190}
5191
5192} } // namespace v8::internal