blob: d718c8875b5973e11a6cc6151f96bb773f4baa55 [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,
2289 static_cast<PropertyAttributes>(attribs));
2290 has_pending_exception = obj.is_null();
2291 EXCEPTION_BAILOUT_CHECK(false);
2292 return true;
2293}
2294
2295
Steve Block6ded16b2010-05-10 14:33:55 +01002296bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
2297 ON_BAILOUT("v8::Object::Set()", return false);
2298 ENTER_V8;
2299 HandleScope scope;
2300 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2301 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2302 EXCEPTION_PREAMBLE();
2303 i::Handle<i::Object> obj = i::SetElement(
2304 self,
2305 index,
2306 value_obj);
2307 has_pending_exception = obj.is_null();
2308 EXCEPTION_BAILOUT_CHECK(false);
2309 return true;
2310}
2311
2312
Steve Blocka7e24c12009-10-30 11:49:00 +00002313bool v8::Object::ForceSet(v8::Handle<Value> key,
2314 v8::Handle<Value> value,
2315 v8::PropertyAttribute attribs) {
2316 ON_BAILOUT("v8::Object::ForceSet()", return false);
2317 ENTER_V8;
2318 HandleScope scope;
2319 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2320 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2321 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2322 EXCEPTION_PREAMBLE();
2323 i::Handle<i::Object> obj = i::ForceSetProperty(
2324 self,
2325 key_obj,
2326 value_obj,
2327 static_cast<PropertyAttributes>(attribs));
2328 has_pending_exception = obj.is_null();
2329 EXCEPTION_BAILOUT_CHECK(false);
2330 return true;
2331}
2332
2333
2334bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2335 ON_BAILOUT("v8::Object::ForceDelete()", return false);
2336 ENTER_V8;
2337 HandleScope scope;
2338 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2339 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002340
2341 // When turning on access checks for a global object deoptimize all functions
2342 // as optimized code does not always handle access checks.
2343 i::Deoptimizer::DeoptimizeGlobalObject(*self);
2344
Steve Blocka7e24c12009-10-30 11:49:00 +00002345 EXCEPTION_PREAMBLE();
2346 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2347 has_pending_exception = obj.is_null();
2348 EXCEPTION_BAILOUT_CHECK(false);
2349 return obj->IsTrue();
2350}
2351
2352
2353Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2354 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2355 ENTER_V8;
2356 i::Handle<i::Object> self = Utils::OpenHandle(this);
2357 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2358 EXCEPTION_PREAMBLE();
2359 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2360 has_pending_exception = result.is_null();
2361 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2362 return Utils::ToLocal(result);
2363}
2364
2365
Steve Block6ded16b2010-05-10 14:33:55 +01002366Local<Value> v8::Object::Get(uint32_t index) {
2367 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2368 ENTER_V8;
2369 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2370 EXCEPTION_PREAMBLE();
2371 i::Handle<i::Object> result = i::GetElement(self, index);
2372 has_pending_exception = result.is_null();
2373 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2374 return Utils::ToLocal(result);
2375}
2376
2377
Steve Blocka7e24c12009-10-30 11:49:00 +00002378Local<Value> v8::Object::GetPrototype() {
2379 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
2380 ENTER_V8;
2381 i::Handle<i::Object> self = Utils::OpenHandle(this);
2382 i::Handle<i::Object> result = i::GetPrototype(self);
2383 return Utils::ToLocal(result);
2384}
2385
2386
Andrei Popescu402d9372010-02-26 13:31:12 +00002387bool v8::Object::SetPrototype(Handle<Value> value) {
2388 ON_BAILOUT("v8::Object::SetPrototype()", return false);
2389 ENTER_V8;
2390 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2391 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2392 EXCEPTION_PREAMBLE();
2393 i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2394 has_pending_exception = result.is_null();
2395 EXCEPTION_BAILOUT_CHECK(false);
2396 return true;
2397}
2398
2399
Steve Blocka7e24c12009-10-30 11:49:00 +00002400Local<Object> v8::Object::FindInstanceInPrototypeChain(
2401 v8::Handle<FunctionTemplate> tmpl) {
2402 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
2403 return Local<v8::Object>());
2404 ENTER_V8;
2405 i::JSObject* object = *Utils::OpenHandle(this);
2406 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2407 while (!object->IsInstanceOf(tmpl_info)) {
2408 i::Object* prototype = object->GetPrototype();
2409 if (!prototype->IsJSObject()) return Local<Object>();
2410 object = i::JSObject::cast(prototype);
2411 }
2412 return Utils::ToLocal(i::Handle<i::JSObject>(object));
2413}
2414
2415
2416Local<Array> v8::Object::GetPropertyNames() {
2417 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
2418 ENTER_V8;
2419 v8::HandleScope scope;
2420 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2421 i::Handle<i::FixedArray> value =
2422 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2423 // Because we use caching to speed up enumeration it is important
2424 // to never change the result of the basic enumeration function so
2425 // we clone the result.
2426 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
2427 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
2428 return scope.Close(Utils::ToLocal(result));
2429}
2430
2431
2432Local<String> v8::Object::ObjectProtoToString() {
2433 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2434 ENTER_V8;
2435 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2436
2437 i::Handle<i::Object> name(self->class_name());
2438
2439 // Native implementation of Object.prototype.toString (v8natives.js):
2440 // var c = %ClassOf(this);
2441 // if (c === 'Arguments') c = 'Object';
2442 // return "[object " + c + "]";
2443
2444 if (!name->IsString()) {
2445 return v8::String::New("[object ]");
2446
2447 } else {
2448 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2449 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2450 return v8::String::New("[object Object]");
2451
2452 } else {
2453 const char* prefix = "[object ";
2454 Local<String> str = Utils::ToLocal(class_name);
2455 const char* postfix = "]";
2456
Steve Blockd0582a62009-12-15 09:54:21 +00002457 int prefix_len = i::StrLength(prefix);
2458 int str_len = str->Length();
2459 int postfix_len = i::StrLength(postfix);
Steve Blocka7e24c12009-10-30 11:49:00 +00002460
Steve Blockd0582a62009-12-15 09:54:21 +00002461 int buf_len = prefix_len + str_len + postfix_len;
Kristian Monsen25f61362010-05-21 11:50:48 +01002462 i::ScopedVector<char> buf(buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002463
2464 // Write prefix.
Kristian Monsen25f61362010-05-21 11:50:48 +01002465 char* ptr = buf.start();
Steve Blocka7e24c12009-10-30 11:49:00 +00002466 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2467 ptr += prefix_len;
2468
2469 // Write real content.
2470 str->WriteAscii(ptr, 0, str_len);
2471 ptr += str_len;
2472
2473 // Write postfix.
2474 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2475
2476 // Copy the buffer into a heap-allocated string and return it.
Kristian Monsen25f61362010-05-21 11:50:48 +01002477 Local<String> result = v8::String::New(buf.start(), buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002478 return result;
2479 }
2480 }
2481}
2482
2483
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002484Local<String> v8::Object::GetConstructorName() {
2485 ON_BAILOUT("v8::Object::GetConstructorName()", return Local<v8::String>());
2486 ENTER_V8;
2487 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2488 i::Handle<i::String> name(self->constructor_name());
2489 return Utils::ToLocal(name);
2490}
2491
2492
Steve Blocka7e24c12009-10-30 11:49:00 +00002493bool v8::Object::Delete(v8::Handle<String> key) {
2494 ON_BAILOUT("v8::Object::Delete()", return false);
2495 ENTER_V8;
2496 HandleScope scope;
2497 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2498 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2499 return i::DeleteProperty(self, key_obj)->IsTrue();
2500}
2501
2502
2503bool v8::Object::Has(v8::Handle<String> key) {
2504 ON_BAILOUT("v8::Object::Has()", return false);
2505 ENTER_V8;
2506 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2507 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2508 return self->HasProperty(*key_obj);
2509}
2510
2511
2512bool v8::Object::Delete(uint32_t index) {
2513 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2514 ENTER_V8;
2515 HandleScope scope;
2516 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2517 return i::DeleteElement(self, index)->IsTrue();
2518}
2519
2520
2521bool v8::Object::Has(uint32_t index) {
2522 ON_BAILOUT("v8::Object::HasProperty()", return false);
2523 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2524 return self->HasElement(index);
2525}
2526
2527
Leon Clarkef7060e22010-06-03 12:02:55 +01002528bool Object::SetAccessor(Handle<String> name,
2529 AccessorGetter getter,
2530 AccessorSetter setter,
2531 v8::Handle<Value> data,
2532 AccessControl settings,
2533 PropertyAttribute attributes) {
2534 ON_BAILOUT("v8::Object::SetAccessor()", return false);
2535 ENTER_V8;
2536 HandleScope scope;
2537 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name,
2538 getter, setter, data,
2539 settings, attributes);
2540 i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info);
2541 return !result.is_null() && !result->IsUndefined();
2542}
2543
2544
Steve Blocka7e24c12009-10-30 11:49:00 +00002545bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2546 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2547 return Utils::OpenHandle(this)->HasRealNamedProperty(
2548 *Utils::OpenHandle(*key));
2549}
2550
2551
2552bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2553 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2554 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2555}
2556
2557
2558bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2559 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2560 ENTER_V8;
2561 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2562 *Utils::OpenHandle(*key));
2563}
2564
2565
2566bool v8::Object::HasNamedLookupInterceptor() {
2567 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2568 return Utils::OpenHandle(this)->HasNamedInterceptor();
2569}
2570
2571
2572bool v8::Object::HasIndexedLookupInterceptor() {
2573 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2574 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2575}
2576
2577
2578Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2579 Handle<String> key) {
2580 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2581 return Local<Value>());
2582 ENTER_V8;
2583 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2584 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2585 i::LookupResult lookup;
2586 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002587 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002588 PropertyAttributes attributes;
John Reck59135872010-11-02 12:39:01 -07002589 i::Object* property =
2590 self_obj->GetProperty(*self_obj,
2591 &lookup,
2592 *key_obj,
2593 &attributes)->ToObjectUnchecked();
2594 i::Handle<i::Object> result(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00002595 return Utils::ToLocal(result);
2596 }
2597 return Local<Value>(); // No real property was found in prototype chain.
2598}
2599
2600
2601Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2602 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
2603 ENTER_V8;
2604 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2605 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2606 i::LookupResult lookup;
2607 self_obj->LookupRealNamedProperty(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002608 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002609 PropertyAttributes attributes;
John Reck59135872010-11-02 12:39:01 -07002610 i::Object* property =
2611 self_obj->GetProperty(*self_obj,
2612 &lookup,
2613 *key_obj,
2614 &attributes)->ToObjectUnchecked();
2615 i::Handle<i::Object> result(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00002616 return Utils::ToLocal(result);
2617 }
2618 return Local<Value>(); // No real property was found in prototype chain.
2619}
2620
2621
2622// Turns on access checks by copying the map and setting the check flag.
2623// Because the object gets a new map, existing inline cache caching
2624// the old map of this object will fail.
2625void v8::Object::TurnOnAccessCheck() {
2626 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2627 ENTER_V8;
2628 HandleScope scope;
2629 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2630
Ben Murdochb0fe1622011-05-05 13:52:32 +01002631 // When turning on access checks for a global object deoptimize all functions
2632 // as optimized code does not always handle access checks.
2633 i::Deoptimizer::DeoptimizeGlobalObject(*obj);
2634
Steve Blocka7e24c12009-10-30 11:49:00 +00002635 i::Handle<i::Map> new_map =
2636 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2637 new_map->set_is_access_check_needed(true);
2638 obj->set_map(*new_map);
2639}
2640
2641
2642bool v8::Object::IsDirty() {
2643 return Utils::OpenHandle(this)->IsDirty();
2644}
2645
2646
2647Local<v8::Object> v8::Object::Clone() {
2648 ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2649 ENTER_V8;
2650 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2651 EXCEPTION_PREAMBLE();
2652 i::Handle<i::JSObject> result = i::Copy(self);
2653 has_pending_exception = result.is_null();
2654 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2655 return Utils::ToLocal(result);
2656}
2657
2658
2659int v8::Object::GetIdentityHash() {
2660 ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2661 ENTER_V8;
2662 HandleScope scope;
2663 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
Steve Block1e0659c2011-05-24 12:43:12 +01002664 i::Handle<i::Object> hidden_props_obj(i::GetHiddenProperties(self, true));
2665 if (!hidden_props_obj->IsJSObject()) {
2666 // We failed to create hidden properties. That's a detached
2667 // global proxy.
2668 ASSERT(hidden_props_obj->IsUndefined());
2669 return 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00002670 }
Steve Block1e0659c2011-05-24 12:43:12 +01002671 i::Handle<i::JSObject> hidden_props =
2672 i::Handle<i::JSObject>::cast(hidden_props_obj);
2673 i::Handle<i::String> hash_symbol = i::Factory::identity_hash_symbol();
2674 if (hidden_props->HasLocalProperty(*hash_symbol)) {
2675 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2676 CHECK(!hash.is_null());
2677 CHECK(hash->IsSmi());
2678 return i::Smi::cast(*hash)->value();
2679 }
2680
2681 int hash_value;
2682 int attempts = 0;
2683 do {
2684 // Generate a random 32-bit hash value but limit range to fit
2685 // within a smi.
2686 hash_value = i::V8::Random() & i::Smi::kMaxValue;
2687 attempts++;
2688 } while (hash_value == 0 && attempts < 30);
2689 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
2690 CHECK(!i::SetLocalPropertyIgnoreAttributes(
2691 hidden_props,
2692 hash_symbol,
2693 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2694 static_cast<PropertyAttributes>(None)).is_null());
2695
Steve Blocka7e24c12009-10-30 11:49:00 +00002696 return hash_value;
2697}
2698
2699
2700bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2701 v8::Handle<v8::Value> value) {
2702 ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
2703 ENTER_V8;
2704 HandleScope scope;
2705 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2706 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2707 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2708 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2709 EXCEPTION_PREAMBLE();
2710 i::Handle<i::Object> obj = i::SetProperty(
2711 hidden_props,
2712 key_obj,
2713 value_obj,
2714 static_cast<PropertyAttributes>(None));
2715 has_pending_exception = obj.is_null();
2716 EXCEPTION_BAILOUT_CHECK(false);
2717 return true;
2718}
2719
2720
2721v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2722 ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2723 ENTER_V8;
2724 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2725 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2726 if (hidden_props->IsUndefined()) {
2727 return v8::Local<v8::Value>();
2728 }
2729 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2730 EXCEPTION_PREAMBLE();
2731 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2732 has_pending_exception = result.is_null();
2733 EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2734 if (result->IsUndefined()) {
2735 return v8::Local<v8::Value>();
2736 }
2737 return Utils::ToLocal(result);
2738}
2739
2740
2741bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2742 ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2743 ENTER_V8;
2744 HandleScope scope;
2745 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2746 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2747 if (hidden_props->IsUndefined()) {
2748 return true;
2749 }
2750 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2751 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2752 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2753}
2754
2755
2756void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2757 ON_BAILOUT("v8::SetElementsToPixelData()", return);
2758 ENTER_V8;
2759 HandleScope scope;
Steve Block3ce2e202009-11-05 08:53:23 +00002760 if (!ApiCheck(length <= i::PixelArray::kMaxLength,
Steve Blocka7e24c12009-10-30 11:49:00 +00002761 "v8::Object::SetIndexedPropertiesToPixelData()",
2762 "length exceeds max acceptable value")) {
2763 return;
2764 }
2765 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2766 if (!ApiCheck(!self->IsJSArray(),
2767 "v8::Object::SetIndexedPropertiesToPixelData()",
2768 "JSArray is not supported")) {
2769 return;
2770 }
2771 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
Steve Block1e0659c2011-05-24 12:43:12 +01002772 i::Handle<i::Map> pixel_array_map =
2773 i::Factory::GetPixelArrayElementsMap(i::Handle<i::Map>(self->map()));
2774 self->set_map(*pixel_array_map);
Steve Blocka7e24c12009-10-30 11:49:00 +00002775 self->set_elements(*pixels);
2776}
2777
2778
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002779bool v8::Object::HasIndexedPropertiesInPixelData() {
2780 ON_BAILOUT("v8::HasIndexedPropertiesInPixelData()", return false);
2781 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2782 return self->HasPixelElements();
2783}
2784
2785
2786uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
2787 ON_BAILOUT("v8::GetIndexedPropertiesPixelData()", return NULL);
2788 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2789 if (self->HasPixelElements()) {
2790 return i::PixelArray::cast(self->elements())->external_pointer();
2791 } else {
2792 return NULL;
2793 }
2794}
2795
2796
2797int v8::Object::GetIndexedPropertiesPixelDataLength() {
2798 ON_BAILOUT("v8::GetIndexedPropertiesPixelDataLength()", return -1);
2799 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2800 if (self->HasPixelElements()) {
2801 return i::PixelArray::cast(self->elements())->length();
2802 } else {
2803 return -1;
2804 }
2805}
2806
2807
Steve Block3ce2e202009-11-05 08:53:23 +00002808void v8::Object::SetIndexedPropertiesToExternalArrayData(
2809 void* data,
2810 ExternalArrayType array_type,
2811 int length) {
2812 ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
2813 ENTER_V8;
2814 HandleScope scope;
2815 if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
2816 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2817 "length exceeds max acceptable value")) {
2818 return;
2819 }
2820 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2821 if (!ApiCheck(!self->IsJSArray(),
2822 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2823 "JSArray is not supported")) {
2824 return;
2825 }
2826 i::Handle<i::ExternalArray> array =
2827 i::Factory::NewExternalArray(length, array_type, data);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002828 i::Handle<i::Map> slow_map =
2829 i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map()));
2830 self->set_map(*slow_map);
Steve Block3ce2e202009-11-05 08:53:23 +00002831 self->set_elements(*array);
2832}
2833
2834
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002835bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
2836 ON_BAILOUT("v8::HasIndexedPropertiesInExternalArrayData()", return false);
2837 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2838 return self->HasExternalArrayElements();
2839}
2840
2841
2842void* v8::Object::GetIndexedPropertiesExternalArrayData() {
2843 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayData()", return NULL);
2844 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2845 if (self->HasExternalArrayElements()) {
2846 return i::ExternalArray::cast(self->elements())->external_pointer();
2847 } else {
2848 return NULL;
2849 }
2850}
2851
2852
2853ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
2854 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataType()",
2855 return static_cast<ExternalArrayType>(-1));
2856 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2857 switch (self->elements()->map()->instance_type()) {
2858 case i::EXTERNAL_BYTE_ARRAY_TYPE:
2859 return kExternalByteArray;
2860 case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2861 return kExternalUnsignedByteArray;
2862 case i::EXTERNAL_SHORT_ARRAY_TYPE:
2863 return kExternalShortArray;
2864 case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2865 return kExternalUnsignedShortArray;
2866 case i::EXTERNAL_INT_ARRAY_TYPE:
2867 return kExternalIntArray;
2868 case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2869 return kExternalUnsignedIntArray;
2870 case i::EXTERNAL_FLOAT_ARRAY_TYPE:
2871 return kExternalFloatArray;
2872 default:
2873 return static_cast<ExternalArrayType>(-1);
2874 }
2875}
2876
2877
2878int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
2879 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataLength()", return 0);
2880 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2881 if (self->HasExternalArrayElements()) {
2882 return i::ExternalArray::cast(self->elements())->length();
2883 } else {
2884 return -1;
2885 }
2886}
2887
2888
Steve Blocka7e24c12009-10-30 11:49:00 +00002889Local<v8::Object> Function::NewInstance() const {
2890 return NewInstance(0, NULL);
2891}
2892
2893
2894Local<v8::Object> Function::NewInstance(int argc,
2895 v8::Handle<v8::Value> argv[]) const {
2896 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2897 LOG_API("Function::NewInstance");
2898 ENTER_V8;
2899 HandleScope scope;
2900 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2901 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2902 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2903 EXCEPTION_PREAMBLE();
2904 i::Handle<i::Object> returned =
2905 i::Execution::New(function, argc, args, &has_pending_exception);
2906 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2907 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2908}
2909
2910
2911Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2912 v8::Handle<v8::Value> argv[]) {
2913 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2914 LOG_API("Function::Call");
2915 ENTER_V8;
2916 i::Object* raw_result = NULL;
2917 {
2918 HandleScope scope;
2919 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2920 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2921 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2922 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2923 EXCEPTION_PREAMBLE();
2924 i::Handle<i::Object> returned =
2925 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2926 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2927 raw_result = *returned;
2928 }
2929 i::Handle<i::Object> result(raw_result);
2930 return Utils::ToLocal(result);
2931}
2932
2933
2934void Function::SetName(v8::Handle<v8::String> name) {
2935 ENTER_V8;
2936 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2937 func->shared()->set_name(*Utils::OpenHandle(*name));
2938}
2939
2940
2941Handle<Value> Function::GetName() const {
2942 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2943 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2944}
2945
2946
Andrei Popescu402d9372010-02-26 13:31:12 +00002947ScriptOrigin Function::GetScriptOrigin() const {
2948 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2949 if (func->shared()->script()->IsScript()) {
2950 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2951 v8::ScriptOrigin origin(
2952 Utils::ToLocal(i::Handle<i::Object>(script->name())),
2953 v8::Integer::New(script->line_offset()->value()),
2954 v8::Integer::New(script->column_offset()->value()));
2955 return origin;
2956 }
2957 return v8::ScriptOrigin(Handle<Value>());
2958}
2959
2960
2961const int Function::kLineOffsetNotFound = -1;
2962
2963
2964int Function::GetScriptLineNumber() const {
2965 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2966 if (func->shared()->script()->IsScript()) {
2967 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2968 return i::GetScriptLineNumber(script, func->shared()->start_position());
2969 }
2970 return kLineOffsetNotFound;
2971}
2972
2973
2974namespace {
2975
2976// Tracks string usage to help make better decisions when
2977// externalizing strings.
2978//
2979// Implementation note: internally this class only tracks fresh
2980// strings and keeps a single use counter for them.
2981class StringTracker {
2982 public:
2983 // Records that the given string's characters were copied to some
2984 // external buffer. If this happens often we should honor
2985 // externalization requests for the string.
2986 static void RecordWrite(i::Handle<i::String> string) {
2987 i::Address address = reinterpret_cast<i::Address>(*string);
2988 i::Address top = i::Heap::NewSpaceTop();
2989 if (IsFreshString(address, top)) {
2990 IncrementUseCount(top);
2991 }
2992 }
2993
2994 // Estimates freshness and use frequency of the given string based
2995 // on how close it is to the new space top and the recorded usage
2996 // history.
2997 static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
2998 i::Address address = reinterpret_cast<i::Address>(*string);
2999 i::Address top = i::Heap::NewSpaceTop();
3000 return IsFreshString(address, top) && IsUseCountLow(top);
3001 }
3002
3003 private:
3004 static inline bool IsFreshString(i::Address string, i::Address top) {
3005 return top - kFreshnessLimit <= string && string <= top;
3006 }
3007
3008 static inline bool IsUseCountLow(i::Address top) {
3009 if (last_top_ != top) return true;
3010 return use_count_ < kUseLimit;
3011 }
3012
3013 static inline void IncrementUseCount(i::Address top) {
3014 if (last_top_ != top) {
3015 use_count_ = 0;
3016 last_top_ = top;
3017 }
3018 ++use_count_;
3019 }
3020
3021 // How close to the new space top a fresh string has to be.
3022 static const int kFreshnessLimit = 1024;
3023
3024 // The number of uses required to consider a string useful.
3025 static const int kUseLimit = 32;
3026
3027 // Single use counter shared by all fresh strings.
3028 static int use_count_;
3029
3030 // Last new space top when the use count above was valid.
3031 static i::Address last_top_;
3032};
3033
3034int StringTracker::use_count_ = 0;
3035i::Address StringTracker::last_top_ = NULL;
3036
3037} // namespace
3038
3039
Steve Blocka7e24c12009-10-30 11:49:00 +00003040int String::Length() const {
3041 if (IsDeadCheck("v8::String::Length()")) return 0;
3042 return Utils::OpenHandle(this)->length();
3043}
3044
3045
3046int String::Utf8Length() const {
3047 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
3048 return Utils::OpenHandle(this)->Utf8Length();
3049}
3050
3051
Steve Block6ded16b2010-05-10 14:33:55 +01003052int String::WriteUtf8(char* buffer,
3053 int capacity,
3054 int* nchars_ref,
3055 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003056 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
3057 LOG_API("String::WriteUtf8");
3058 ENTER_V8;
3059 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003060 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003061 if (hints & HINT_MANY_WRITES_EXPECTED) {
3062 // Flatten the string for efficiency. This applies whether we are
3063 // using StringInputBuffer or Get(i) to access the characters.
3064 str->TryFlatten();
3065 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003066 write_input_buffer.Reset(0, *str);
3067 int len = str->length();
3068 // Encode the first K - 3 bytes directly into the buffer since we
3069 // know there's room for them. If no capacity is given we copy all
3070 // of them here.
3071 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
3072 int i;
3073 int pos = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01003074 int nchars = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00003075 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
3076 i::uc32 c = write_input_buffer.GetNext();
3077 int written = unibrow::Utf8::Encode(buffer + pos, c);
3078 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01003079 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00003080 }
3081 if (i < len) {
3082 // For the last characters we need to check the length for each one
3083 // because they may be longer than the remaining space in the
3084 // buffer.
3085 char intermediate[unibrow::Utf8::kMaxEncodedSize];
3086 for (; i < len && pos < capacity; i++) {
3087 i::uc32 c = write_input_buffer.GetNext();
3088 int written = unibrow::Utf8::Encode(intermediate, c);
3089 if (pos + written <= capacity) {
3090 for (int j = 0; j < written; j++)
3091 buffer[pos + j] = intermediate[j];
3092 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01003093 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00003094 } else {
3095 // We've reached the end of the buffer
3096 break;
3097 }
3098 }
3099 }
Steve Block6ded16b2010-05-10 14:33:55 +01003100 if (nchars_ref != NULL) *nchars_ref = nchars;
Steve Blocka7e24c12009-10-30 11:49:00 +00003101 if (i == len && (capacity == -1 || pos < capacity))
3102 buffer[pos++] = '\0';
3103 return pos;
3104}
3105
3106
Steve Block6ded16b2010-05-10 14:33:55 +01003107int String::WriteAscii(char* buffer,
3108 int start,
3109 int length,
3110 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003111 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
3112 LOG_API("String::WriteAscii");
3113 ENTER_V8;
3114 ASSERT(start >= 0 && length >= -1);
3115 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003116 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003117 if (hints & HINT_MANY_WRITES_EXPECTED) {
3118 // Flatten the string for efficiency. This applies whether we are
3119 // using StringInputBuffer or Get(i) to access the characters.
3120 str->TryFlatten();
3121 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003122 int end = length;
3123 if ( (length == -1) || (length > str->length() - start) )
3124 end = str->length() - start;
3125 if (end < 0) return 0;
3126 write_input_buffer.Reset(start, *str);
3127 int i;
3128 for (i = 0; i < end; i++) {
3129 char c = static_cast<char>(write_input_buffer.GetNext());
3130 if (c == '\0') c = ' ';
3131 buffer[i] = c;
3132 }
3133 if (length == -1 || i < length)
3134 buffer[i] = '\0';
3135 return i;
3136}
3137
3138
Steve Block6ded16b2010-05-10 14:33:55 +01003139int String::Write(uint16_t* buffer,
3140 int start,
3141 int length,
3142 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003143 if (IsDeadCheck("v8::String::Write()")) return 0;
3144 LOG_API("String::Write");
3145 ENTER_V8;
3146 ASSERT(start >= 0 && length >= -1);
3147 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003148 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003149 if (hints & HINT_MANY_WRITES_EXPECTED) {
3150 // Flatten the string for efficiency. This applies whether we are
3151 // using StringInputBuffer or Get(i) to access the characters.
3152 str->TryFlatten();
3153 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003154 int end = start + length;
3155 if ((length == -1) || (length > str->length() - start) )
3156 end = str->length();
Steve Blocka7e24c12009-10-30 11:49:00 +00003157 if (end < 0) return 0;
3158 i::String::WriteToFlat(*str, buffer, start, end);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003159 if (length == -1 || end - start < length) {
3160 buffer[end - start] = '\0';
3161 }
3162 return end - start;
Steve Blocka7e24c12009-10-30 11:49:00 +00003163}
3164
3165
3166bool v8::String::IsExternal() const {
3167 EnsureInitialized("v8::String::IsExternal()");
3168 i::Handle<i::String> str = Utils::OpenHandle(this);
3169 return i::StringShape(*str).IsExternalTwoByte();
3170}
3171
3172
3173bool v8::String::IsExternalAscii() const {
3174 EnsureInitialized("v8::String::IsExternalAscii()");
3175 i::Handle<i::String> str = Utils::OpenHandle(this);
3176 return i::StringShape(*str).IsExternalAscii();
3177}
3178
3179
3180void v8::String::VerifyExternalStringResource(
3181 v8::String::ExternalStringResource* value) const {
3182 i::Handle<i::String> str = Utils::OpenHandle(this);
3183 v8::String::ExternalStringResource* expected;
3184 if (i::StringShape(*str).IsExternalTwoByte()) {
3185 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
3186 expected = reinterpret_cast<ExternalStringResource*>(resource);
3187 } else {
3188 expected = NULL;
3189 }
3190 CHECK_EQ(expected, value);
3191}
3192
3193
3194v8::String::ExternalAsciiStringResource*
3195 v8::String::GetExternalAsciiStringResource() const {
3196 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
3197 i::Handle<i::String> str = Utils::OpenHandle(this);
3198 if (i::StringShape(*str).IsExternalAscii()) {
3199 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
3200 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
3201 } else {
3202 return NULL;
3203 }
3204}
3205
3206
3207double Number::Value() const {
3208 if (IsDeadCheck("v8::Number::Value()")) return 0;
3209 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3210 return obj->Number();
3211}
3212
3213
3214bool Boolean::Value() const {
3215 if (IsDeadCheck("v8::Boolean::Value()")) return false;
3216 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3217 return obj->IsTrue();
3218}
3219
3220
3221int64_t Integer::Value() const {
3222 if (IsDeadCheck("v8::Integer::Value()")) return 0;
3223 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3224 if (obj->IsSmi()) {
3225 return i::Smi::cast(*obj)->value();
3226 } else {
3227 return static_cast<int64_t>(obj->Number());
3228 }
3229}
3230
3231
3232int32_t Int32::Value() const {
3233 if (IsDeadCheck("v8::Int32::Value()")) return 0;
3234 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3235 if (obj->IsSmi()) {
3236 return i::Smi::cast(*obj)->value();
3237 } else {
3238 return static_cast<int32_t>(obj->Number());
3239 }
3240}
3241
3242
Steve Block6ded16b2010-05-10 14:33:55 +01003243uint32_t Uint32::Value() const {
3244 if (IsDeadCheck("v8::Uint32::Value()")) return 0;
3245 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3246 if (obj->IsSmi()) {
3247 return i::Smi::cast(*obj)->value();
3248 } else {
3249 return static_cast<uint32_t>(obj->Number());
3250 }
3251}
3252
3253
Steve Blocka7e24c12009-10-30 11:49:00 +00003254int v8::Object::InternalFieldCount() {
3255 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
3256 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3257 return obj->GetInternalFieldCount();
3258}
3259
3260
3261Local<Value> v8::Object::CheckedGetInternalField(int index) {
3262 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
3263 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3264 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3265 "v8::Object::GetInternalField()",
3266 "Reading internal field out of bounds")) {
3267 return Local<Value>();
3268 }
3269 i::Handle<i::Object> value(obj->GetInternalField(index));
3270 Local<Value> result = Utils::ToLocal(value);
3271#ifdef DEBUG
3272 Local<Value> unchecked = UncheckedGetInternalField(index);
3273 ASSERT(unchecked.IsEmpty() || (unchecked == result));
3274#endif
3275 return result;
3276}
3277
3278
3279void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
3280 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
3281 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3282 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3283 "v8::Object::SetInternalField()",
3284 "Writing internal field out of bounds")) {
3285 return;
3286 }
3287 ENTER_V8;
3288 i::Handle<i::Object> val = Utils::OpenHandle(*value);
3289 obj->SetInternalField(index, *val);
3290}
3291
3292
Ben Murdochb8e0da22011-05-16 14:20:40 +01003293static bool CanBeEncodedAsSmi(void* ptr) {
Steve Block1e0659c2011-05-24 12:43:12 +01003294 const uintptr_t address = reinterpret_cast<uintptr_t>(ptr);
Ben Murdochb8e0da22011-05-16 14:20:40 +01003295 return ((address & i::kEncodablePointerMask) == 0);
3296}
3297
3298
3299static i::Smi* EncodeAsSmi(void* ptr) {
3300 ASSERT(CanBeEncodedAsSmi(ptr));
Steve Block1e0659c2011-05-24 12:43:12 +01003301 const uintptr_t address = reinterpret_cast<uintptr_t>(ptr);
Ben Murdochb8e0da22011-05-16 14:20:40 +01003302 i::Smi* result = reinterpret_cast<i::Smi*>(address << i::kPointerToSmiShift);
3303 ASSERT(i::Internals::HasSmiTag(result));
3304 ASSERT_EQ(result, i::Smi::FromInt(result->value()));
3305 ASSERT_EQ(ptr, i::Internals::GetExternalPointerFromSmi(result));
3306 return result;
3307}
3308
3309
Steve Blocka7e24c12009-10-30 11:49:00 +00003310void v8::Object::SetPointerInInternalField(int index, void* value) {
Steve Block6ded16b2010-05-10 14:33:55 +01003311 ENTER_V8;
Ben Murdochb8e0da22011-05-16 14:20:40 +01003312 if (CanBeEncodedAsSmi(value)) {
3313 Utils::OpenHandle(this)->SetInternalField(index, EncodeAsSmi(value));
3314 } else {
3315 HandleScope scope;
3316 i::Handle<i::Proxy> proxy =
3317 i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
3318 if (!proxy.is_null())
3319 Utils::OpenHandle(this)->SetInternalField(index, *proxy);
Steve Block3ce2e202009-11-05 08:53:23 +00003320 }
Ben Murdochb8e0da22011-05-16 14:20:40 +01003321 ASSERT_EQ(value, GetPointerFromInternalField(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00003322}
3323
3324
3325// --- E n v i r o n m e n t ---
3326
3327bool v8::V8::Initialize() {
3328 if (i::V8::IsRunning()) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003329 HandleScope scope;
Steve Blockd0582a62009-12-15 09:54:21 +00003330 if (i::Snapshot::Initialize()) return true;
3331 return i::V8::Initialize(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00003332}
3333
3334
3335bool v8::V8::Dispose() {
3336 i::V8::TearDown();
3337 return true;
3338}
3339
3340
Russell Brenner90bac252010-11-18 13:33:46 -08003341HeapStatistics::HeapStatistics(): total_heap_size_(0),
3342 total_heap_size_executable_(0),
Ben Murdochb8e0da22011-05-16 14:20:40 +01003343 used_heap_size_(0),
3344 heap_size_limit_(0) { }
Steve Block3ce2e202009-11-05 08:53:23 +00003345
3346
3347void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
3348 heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
Russell Brenner90bac252010-11-18 13:33:46 -08003349 heap_statistics->set_total_heap_size_executable(
3350 i::Heap::CommittedMemoryExecutable());
Steve Block3ce2e202009-11-05 08:53:23 +00003351 heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
Ben Murdochb8e0da22011-05-16 14:20:40 +01003352 heap_statistics->set_heap_size_limit(i::Heap::MaxReserved());
Steve Block3ce2e202009-11-05 08:53:23 +00003353}
3354
3355
3356bool v8::V8::IdleNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003357 // Returning true tells the caller that it need not
3358 // continue to call IdleNotification.
3359 if (!i::V8::IsRunning()) return true;
Steve Block3ce2e202009-11-05 08:53:23 +00003360 return i::V8::IdleNotification();
Steve Blocka7e24c12009-10-30 11:49:00 +00003361}
3362
3363
3364void v8::V8::LowMemoryNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003365 if (!i::V8::IsRunning()) return;
3366 i::Heap::CollectAllGarbage(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00003367}
3368
3369
Steve Block6ded16b2010-05-10 14:33:55 +01003370int v8::V8::ContextDisposedNotification() {
3371 if (!i::V8::IsRunning()) return 0;
3372 return i::Heap::NotifyContextDisposed();
3373}
3374
3375
Steve Blocka7e24c12009-10-30 11:49:00 +00003376const char* v8::V8::GetVersion() {
3377 static v8::internal::EmbeddedVector<char, 128> buffer;
3378 v8::internal::Version::GetString(buffer);
3379 return buffer.start();
3380}
3381
3382
3383static i::Handle<i::FunctionTemplateInfo>
3384 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
3385 if (templ->constructor()->IsUndefined()) {
3386 Local<FunctionTemplate> constructor = FunctionTemplate::New();
3387 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
3388 templ->set_constructor(*Utils::OpenHandle(*constructor));
3389 }
3390 return i::Handle<i::FunctionTemplateInfo>(
3391 i::FunctionTemplateInfo::cast(templ->constructor()));
3392}
3393
3394
3395Persistent<Context> v8::Context::New(
3396 v8::ExtensionConfiguration* extensions,
3397 v8::Handle<ObjectTemplate> global_template,
3398 v8::Handle<Value> global_object) {
3399 EnsureInitialized("v8::Context::New()");
3400 LOG_API("Context::New");
3401 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
3402
3403 // Enter V8 via an ENTER_V8 scope.
3404 i::Handle<i::Context> env;
3405 {
3406 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003407 v8::Handle<ObjectTemplate> proxy_template = global_template;
3408 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
3409 i::Handle<i::FunctionTemplateInfo> global_constructor;
3410
3411 if (!global_template.IsEmpty()) {
3412 // Make sure that the global_template has a constructor.
3413 global_constructor =
3414 EnsureConstructor(Utils::OpenHandle(*global_template));
3415
3416 // Create a fresh template for the global proxy object.
3417 proxy_template = ObjectTemplate::New();
3418 proxy_constructor =
3419 EnsureConstructor(Utils::OpenHandle(*proxy_template));
3420
3421 // Set the global template to be the prototype template of
3422 // global proxy template.
3423 proxy_constructor->set_prototype_template(
3424 *Utils::OpenHandle(*global_template));
3425
3426 // Migrate security handlers from global_template to
3427 // proxy_template. Temporarily removing access check
3428 // information from the global template.
3429 if (!global_constructor->access_check_info()->IsUndefined()) {
3430 proxy_constructor->set_access_check_info(
3431 global_constructor->access_check_info());
3432 proxy_constructor->set_needs_access_check(
3433 global_constructor->needs_access_check());
3434 global_constructor->set_needs_access_check(false);
3435 global_constructor->set_access_check_info(i::Heap::undefined_value());
3436 }
3437 }
3438
3439 // Create the environment.
3440 env = i::Bootstrapper::CreateEnvironment(
3441 Utils::OpenHandle(*global_object),
3442 proxy_template,
3443 extensions);
3444
3445 // Restore the access check info on the global template.
3446 if (!global_template.IsEmpty()) {
3447 ASSERT(!global_constructor.is_null());
3448 ASSERT(!proxy_constructor.is_null());
3449 global_constructor->set_access_check_info(
3450 proxy_constructor->access_check_info());
3451 global_constructor->set_needs_access_check(
3452 proxy_constructor->needs_access_check());
3453 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003454 i::RuntimeProfiler::Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00003455 }
3456 // Leave V8.
3457
3458 if (env.is_null())
3459 return Persistent<Context>();
3460 return Persistent<Context>(Utils::ToLocal(env));
3461}
3462
3463
3464void v8::Context::SetSecurityToken(Handle<Value> token) {
3465 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
3466 ENTER_V8;
3467 i::Handle<i::Context> env = Utils::OpenHandle(this);
3468 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
3469 env->set_security_token(*token_handle);
3470}
3471
3472
3473void v8::Context::UseDefaultSecurityToken() {
3474 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
3475 ENTER_V8;
3476 i::Handle<i::Context> env = Utils::OpenHandle(this);
3477 env->set_security_token(env->global());
3478}
3479
3480
3481Handle<Value> v8::Context::GetSecurityToken() {
3482 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
3483 i::Handle<i::Context> env = Utils::OpenHandle(this);
3484 i::Object* security_token = env->security_token();
3485 i::Handle<i::Object> token_handle(security_token);
3486 return Utils::ToLocal(token_handle);
3487}
3488
3489
3490bool Context::HasOutOfMemoryException() {
3491 i::Handle<i::Context> env = Utils::OpenHandle(this);
3492 return env->has_out_of_memory();
3493}
3494
3495
3496bool Context::InContext() {
3497 return i::Top::context() != NULL;
3498}
3499
3500
3501v8::Local<v8::Context> Context::GetEntered() {
3502 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
3503 i::Handle<i::Object> last = thread_local.LastEnteredContext();
3504 if (last.is_null()) return Local<Context>();
3505 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
3506 return Utils::ToLocal(context);
3507}
3508
3509
3510v8::Local<v8::Context> Context::GetCurrent() {
3511 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
Steve Block3ce2e202009-11-05 08:53:23 +00003512 i::Handle<i::Object> current = i::Top::global_context();
3513 if (current.is_null()) return Local<Context>();
3514 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
Steve Blocka7e24c12009-10-30 11:49:00 +00003515 return Utils::ToLocal(context);
3516}
3517
3518
3519v8::Local<v8::Context> Context::GetCalling() {
3520 if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
3521 i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
3522 if (calling.is_null()) return Local<Context>();
3523 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
3524 return Utils::ToLocal(context);
3525}
3526
3527
3528v8::Local<v8::Object> Context::Global() {
3529 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
3530 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3531 i::Handle<i::Context> context =
3532 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3533 i::Handle<i::Object> global(context->global_proxy());
3534 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
3535}
3536
3537
3538void Context::DetachGlobal() {
3539 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
3540 ENTER_V8;
3541 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3542 i::Handle<i::Context> context =
3543 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3544 i::Bootstrapper::DetachGlobal(context);
3545}
3546
3547
Andrei Popescu74b3c142010-03-29 12:03:09 +01003548void Context::ReattachGlobal(Handle<Object> global_object) {
3549 if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
3550 ENTER_V8;
3551 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3552 i::Handle<i::Context> context =
3553 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3554 i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
3555}
3556
3557
Steve Blocka7e24c12009-10-30 11:49:00 +00003558Local<v8::Object> ObjectTemplate::NewInstance() {
3559 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
3560 LOG_API("ObjectTemplate::NewInstance");
3561 ENTER_V8;
3562 EXCEPTION_PREAMBLE();
3563 i::Handle<i::Object> obj =
3564 i::Execution::InstantiateObject(Utils::OpenHandle(this),
3565 &has_pending_exception);
3566 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
3567 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3568}
3569
3570
3571Local<v8::Function> FunctionTemplate::GetFunction() {
3572 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
3573 return Local<v8::Function>());
3574 LOG_API("FunctionTemplate::GetFunction");
3575 ENTER_V8;
3576 EXCEPTION_PREAMBLE();
3577 i::Handle<i::Object> obj =
3578 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3579 &has_pending_exception);
3580 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
3581 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3582}
3583
3584
3585bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3586 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
3587 i::Object* obj = *Utils::OpenHandle(*value);
3588 return obj->IsInstanceOf(*Utils::OpenHandle(this));
3589}
3590
3591
3592static Local<External> ExternalNewImpl(void* data) {
3593 return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
3594}
3595
3596static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3597 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3598}
3599
3600
Steve Blocka7e24c12009-10-30 11:49:00 +00003601Local<Value> v8::External::Wrap(void* data) {
3602 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3603 LOG_API("External::Wrap");
3604 EnsureInitialized("v8::External::Wrap()");
3605 ENTER_V8;
Ben Murdochb8e0da22011-05-16 14:20:40 +01003606
3607 v8::Local<v8::Value> result = CanBeEncodedAsSmi(data)
3608 ? Utils::ToLocal(i::Handle<i::Object>(EncodeAsSmi(data)))
3609 : v8::Local<v8::Value>(ExternalNewImpl(data));
3610
3611 ASSERT_EQ(data, Unwrap(result));
3612 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003613}
3614
3615
Steve Block3ce2e202009-11-05 08:53:23 +00003616void* v8::Object::SlowGetPointerFromInternalField(int index) {
3617 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3618 i::Object* value = obj->GetInternalField(index);
3619 if (value->IsSmi()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01003620 return i::Internals::GetExternalPointerFromSmi(value);
Steve Block3ce2e202009-11-05 08:53:23 +00003621 } else if (value->IsProxy()) {
3622 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3623 } else {
3624 return NULL;
3625 }
3626}
3627
3628
Steve Blocka7e24c12009-10-30 11:49:00 +00003629void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3630 if (IsDeadCheck("v8::External::Unwrap()")) return 0;
3631 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3632 void* result;
3633 if (obj->IsSmi()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01003634 result = i::Internals::GetExternalPointerFromSmi(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003635 } else if (obj->IsProxy()) {
3636 result = ExternalValueImpl(obj);
3637 } else {
3638 result = NULL;
3639 }
3640 ASSERT_EQ(result, QuickUnwrap(wrapper));
3641 return result;
3642}
3643
3644
3645Local<External> v8::External::New(void* data) {
3646 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3647 LOG_API("External::New");
3648 EnsureInitialized("v8::External::New()");
3649 ENTER_V8;
3650 return ExternalNewImpl(data);
3651}
3652
3653
3654void* External::Value() const {
3655 if (IsDeadCheck("v8::External::Value()")) return 0;
3656 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3657 return ExternalValueImpl(obj);
3658}
3659
3660
3661Local<String> v8::String::Empty() {
3662 EnsureInitialized("v8::String::Empty()");
3663 LOG_API("String::Empty()");
3664 return Utils::ToLocal(i::Factory::empty_symbol());
3665}
3666
3667
3668Local<String> v8::String::New(const char* data, int length) {
3669 EnsureInitialized("v8::String::New()");
3670 LOG_API("String::New(char)");
3671 if (length == 0) return Empty();
3672 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003673 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003674 i::Handle<i::String> result =
3675 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3676 return Utils::ToLocal(result);
3677}
3678
3679
Steve Block3ce2e202009-11-05 08:53:23 +00003680Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3681 EnsureInitialized("v8::String::New()");
3682 LOG_API("String::New(char)");
3683 ENTER_V8;
3684 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3685 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3686 i::Handle<i::String> result = i::Factory::NewConsString(left_string,
3687 right_string);
3688 return Utils::ToLocal(result);
3689}
3690
3691
Steve Blocka7e24c12009-10-30 11:49:00 +00003692Local<String> v8::String::NewUndetectable(const char* data, int length) {
3693 EnsureInitialized("v8::String::NewUndetectable()");
3694 LOG_API("String::NewUndetectable(char)");
3695 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003696 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003697 i::Handle<i::String> result =
3698 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3699 result->MarkAsUndetectable();
3700 return Utils::ToLocal(result);
3701}
3702
3703
3704static int TwoByteStringLength(const uint16_t* data) {
3705 int length = 0;
3706 while (data[length] != '\0') length++;
3707 return length;
3708}
3709
3710
3711Local<String> v8::String::New(const uint16_t* data, int length) {
3712 EnsureInitialized("v8::String::New()");
3713 LOG_API("String::New(uint16_)");
3714 if (length == 0) return Empty();
3715 ENTER_V8;
3716 if (length == -1) length = TwoByteStringLength(data);
3717 i::Handle<i::String> result =
3718 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3719 return Utils::ToLocal(result);
3720}
3721
3722
3723Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
3724 EnsureInitialized("v8::String::NewUndetectable()");
3725 LOG_API("String::NewUndetectable(uint16_)");
3726 ENTER_V8;
3727 if (length == -1) length = TwoByteStringLength(data);
3728 i::Handle<i::String> result =
3729 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3730 result->MarkAsUndetectable();
3731 return Utils::ToLocal(result);
3732}
3733
3734
3735i::Handle<i::String> NewExternalStringHandle(
3736 v8::String::ExternalStringResource* resource) {
3737 i::Handle<i::String> result =
3738 i::Factory::NewExternalStringFromTwoByte(resource);
3739 return result;
3740}
3741
3742
3743i::Handle<i::String> NewExternalAsciiStringHandle(
3744 v8::String::ExternalAsciiStringResource* resource) {
3745 i::Handle<i::String> result =
3746 i::Factory::NewExternalStringFromAscii(resource);
3747 return result;
3748}
3749
3750
Steve Blocka7e24c12009-10-30 11:49:00 +00003751Local<String> v8::String::NewExternal(
3752 v8::String::ExternalStringResource* resource) {
3753 EnsureInitialized("v8::String::NewExternal()");
3754 LOG_API("String::NewExternal");
3755 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003756 i::Handle<i::String> result = NewExternalStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003757 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003758 return Utils::ToLocal(result);
3759}
3760
3761
3762bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3763 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3764 if (this->IsExternal()) return false; // Already an external string.
3765 ENTER_V8;
3766 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003767 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003768 bool result = obj->MakeExternal(resource);
3769 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003770 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003771 }
3772 return result;
3773}
3774
3775
3776Local<String> v8::String::NewExternal(
3777 v8::String::ExternalAsciiStringResource* resource) {
3778 EnsureInitialized("v8::String::NewExternal()");
3779 LOG_API("String::NewExternal");
3780 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003781 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003782 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003783 return Utils::ToLocal(result);
3784}
3785
3786
3787bool v8::String::MakeExternal(
3788 v8::String::ExternalAsciiStringResource* resource) {
3789 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3790 if (this->IsExternal()) return false; // Already an external string.
3791 ENTER_V8;
3792 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003793 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003794 bool result = obj->MakeExternal(resource);
3795 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003796 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003797 }
3798 return result;
3799}
3800
3801
3802bool v8::String::CanMakeExternal() {
3803 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3804 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003805 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003806 int size = obj->Size(); // Byte size of the original string.
3807 if (size < i::ExternalString::kSize)
3808 return false;
3809 i::StringShape shape(*obj);
3810 return !shape.IsExternal();
3811}
3812
3813
3814Local<v8::Object> v8::Object::New() {
3815 EnsureInitialized("v8::Object::New()");
3816 LOG_API("Object::New");
3817 ENTER_V8;
3818 i::Handle<i::JSObject> obj =
3819 i::Factory::NewJSObject(i::Top::object_function());
3820 return Utils::ToLocal(obj);
3821}
3822
3823
3824Local<v8::Value> v8::Date::New(double time) {
3825 EnsureInitialized("v8::Date::New()");
3826 LOG_API("Date::New");
Steve Blockd0582a62009-12-15 09:54:21 +00003827 if (isnan(time)) {
3828 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3829 time = i::OS::nan_value();
3830 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003831 ENTER_V8;
3832 EXCEPTION_PREAMBLE();
3833 i::Handle<i::Object> obj =
3834 i::Execution::NewDate(time, &has_pending_exception);
3835 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3836 return Utils::ToLocal(obj);
3837}
3838
3839
3840double v8::Date::NumberValue() const {
3841 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3842 LOG_API("Date::NumberValue");
3843 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3844 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3845 return jsvalue->value()->Number();
3846}
3847
3848
Ben Murdochb0fe1622011-05-05 13:52:32 +01003849void v8::Date::DateTimeConfigurationChangeNotification() {
3850 ON_BAILOUT("v8::Date::DateTimeConfigurationChangeNotification()", return);
3851 LOG_API("Date::DateTimeConfigurationChangeNotification");
3852 ENTER_V8;
3853
3854 HandleScope scope;
3855
3856 // Get the function ResetDateCache (defined in date-delay.js).
3857 i::Handle<i::String> func_name_str =
3858 i::Factory::LookupAsciiSymbol("ResetDateCache");
3859 i::MaybeObject* result = i::Top::builtins()->GetProperty(*func_name_str);
3860 i::Object* object_func;
3861 if (!result->ToObject(&object_func)) {
3862 return;
3863 }
3864
3865 if (object_func->IsJSFunction()) {
3866 i::Handle<i::JSFunction> func =
3867 i::Handle<i::JSFunction>(i::JSFunction::cast(object_func));
3868
3869 // Call ResetDateCache(0 but expect no exceptions:
3870 bool caught_exception = false;
3871 i::Handle<i::Object> result =
3872 i::Execution::TryCall(func, i::Top::builtins(), 0, NULL,
3873 &caught_exception);
3874 }
3875}
3876
3877
Ben Murdochf87a2032010-10-22 12:50:53 +01003878static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
3879 char flags_buf[3];
3880 int num_flags = 0;
3881 if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
3882 if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
3883 if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
3884 ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
3885 return i::Factory::LookupSymbol(
3886 i::Vector<const char>(flags_buf, num_flags));
3887}
3888
3889
3890Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
3891 Flags flags) {
3892 EnsureInitialized("v8::RegExp::New()");
3893 LOG_API("RegExp::New");
3894 ENTER_V8;
3895 EXCEPTION_PREAMBLE();
3896 i::Handle<i::JSRegExp> obj = i::Execution::NewJSRegExp(
3897 Utils::OpenHandle(*pattern),
3898 RegExpFlagsToString(flags),
3899 &has_pending_exception);
3900 EXCEPTION_BAILOUT_CHECK(Local<v8::RegExp>());
3901 return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
3902}
3903
3904
3905Local<v8::String> v8::RegExp::GetSource() const {
3906 if (IsDeadCheck("v8::RegExp::GetSource()")) return Local<v8::String>();
3907 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
3908 return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
3909}
3910
3911
3912// Assert that the static flags cast in GetFlags is valid.
3913#define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \
3914 STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \
3915 static_cast<int>(i::JSRegExp::internal_flag))
3916REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
3917REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
3918REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
3919REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
3920#undef REGEXP_FLAG_ASSERT_EQ
3921
3922v8::RegExp::Flags v8::RegExp::GetFlags() const {
3923 if (IsDeadCheck("v8::RegExp::GetFlags()")) return v8::RegExp::kNone;
3924 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
3925 return static_cast<RegExp::Flags>(obj->GetFlags().value());
3926}
3927
3928
Steve Blocka7e24c12009-10-30 11:49:00 +00003929Local<v8::Array> v8::Array::New(int length) {
3930 EnsureInitialized("v8::Array::New()");
3931 LOG_API("Array::New");
3932 ENTER_V8;
3933 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3934 return Utils::ToLocal(obj);
3935}
3936
3937
3938uint32_t v8::Array::Length() const {
3939 if (IsDeadCheck("v8::Array::Length()")) return 0;
3940 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3941 i::Object* length = obj->length();
3942 if (length->IsSmi()) {
3943 return i::Smi::cast(length)->value();
3944 } else {
3945 return static_cast<uint32_t>(length->Number());
3946 }
3947}
3948
3949
3950Local<Object> Array::CloneElementAt(uint32_t index) {
3951 ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3952 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3953 if (!self->HasFastElements()) {
3954 return Local<Object>();
3955 }
3956 i::FixedArray* elms = i::FixedArray::cast(self->elements());
3957 i::Object* paragon = elms->get(index);
3958 if (!paragon->IsJSObject()) {
3959 return Local<Object>();
3960 }
3961 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3962 EXCEPTION_PREAMBLE();
Steve Block6ded16b2010-05-10 14:33:55 +01003963 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003964 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3965 has_pending_exception = result.is_null();
3966 EXCEPTION_BAILOUT_CHECK(Local<Object>());
3967 return Utils::ToLocal(result);
3968}
3969
3970
3971Local<String> v8::String::NewSymbol(const char* data, int length) {
3972 EnsureInitialized("v8::String::NewSymbol()");
3973 LOG_API("String::NewSymbol(char)");
3974 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003975 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003976 i::Handle<i::String> result =
3977 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3978 return Utils::ToLocal(result);
3979}
3980
3981
3982Local<Number> v8::Number::New(double value) {
3983 EnsureInitialized("v8::Number::New()");
Steve Blockd0582a62009-12-15 09:54:21 +00003984 if (isnan(value)) {
3985 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3986 value = i::OS::nan_value();
3987 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003988 ENTER_V8;
3989 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3990 return Utils::NumberToLocal(result);
3991}
3992
3993
3994Local<Integer> v8::Integer::New(int32_t value) {
3995 EnsureInitialized("v8::Integer::New()");
3996 if (i::Smi::IsValid(value)) {
3997 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3998 }
3999 ENTER_V8;
4000 i::Handle<i::Object> result = i::Factory::NewNumber(value);
4001 return Utils::IntegerToLocal(result);
4002}
4003
4004
Steve Block3ce2e202009-11-05 08:53:23 +00004005Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
4006 bool fits_into_int32_t = (value & (1 << 31)) == 0;
4007 if (fits_into_int32_t) {
4008 return Integer::New(static_cast<int32_t>(value));
4009 }
4010 ENTER_V8;
4011 i::Handle<i::Object> result = i::Factory::NewNumber(value);
4012 return Utils::IntegerToLocal(result);
4013}
4014
4015
Steve Blocka7e24c12009-10-30 11:49:00 +00004016void V8::IgnoreOutOfMemoryException() {
4017 thread_local.set_ignore_out_of_memory(true);
4018}
4019
4020
4021bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
4022 EnsureInitialized("v8::V8::AddMessageListener()");
4023 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
4024 ENTER_V8;
4025 HandleScope scope;
4026 NeanderArray listeners(i::Factory::message_listeners());
4027 NeanderObject obj(2);
4028 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
4029 obj.set(1, data.IsEmpty() ?
4030 i::Heap::undefined_value() :
4031 *Utils::OpenHandle(*data));
4032 listeners.add(obj.value());
4033 return true;
4034}
4035
4036
4037void V8::RemoveMessageListeners(MessageCallback that) {
4038 EnsureInitialized("v8::V8::RemoveMessageListener()");
4039 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
4040 ENTER_V8;
4041 HandleScope scope;
4042 NeanderArray listeners(i::Factory::message_listeners());
4043 for (int i = 0; i < listeners.length(); i++) {
4044 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
4045
4046 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
4047 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
4048 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
4049 listeners.set(i, i::Heap::undefined_value());
4050 }
4051 }
4052}
4053
4054
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004055void V8::SetCaptureStackTraceForUncaughtExceptions(
4056 bool capture,
4057 int frame_limit,
4058 StackTrace::StackTraceOptions options) {
4059 i::Top::SetCaptureStackTraceForUncaughtExceptions(
4060 capture,
4061 frame_limit,
4062 options);
4063}
4064
4065
Steve Blocka7e24c12009-10-30 11:49:00 +00004066void V8::SetCounterFunction(CounterLookupCallback callback) {
4067 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
4068 i::StatsTable::SetCounterFunction(callback);
4069}
4070
4071void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
4072 if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
4073 i::StatsTable::SetCreateHistogramFunction(callback);
4074}
4075
4076void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
4077 if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
4078 i::StatsTable::SetAddHistogramSampleFunction(callback);
4079}
4080
4081void V8::EnableSlidingStateWindow() {
4082 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
4083 i::Logger::EnableSlidingStateWindow();
4084}
4085
4086
4087void V8::SetFailedAccessCheckCallbackFunction(
4088 FailedAccessCheckCallback callback) {
4089 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
4090 i::Top::SetFailedAccessCheckCallback(callback);
4091}
4092
4093
4094void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
4095 if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
4096 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
4097 i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
4098}
4099
4100
4101int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
4102 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
4103 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
4104}
4105
4106
4107void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
4108 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
4109 i::Heap::SetGlobalGCPrologueCallback(callback);
4110}
4111
4112
4113void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
4114 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
4115 i::Heap::SetGlobalGCEpilogueCallback(callback);
4116}
4117
4118
Steve Block6ded16b2010-05-10 14:33:55 +01004119void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
4120 if (IsDeadCheck("v8::V8::AddGCPrologueCallback()")) return;
4121 i::Heap::AddGCPrologueCallback(callback, gc_type);
4122}
4123
4124
4125void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
4126 if (IsDeadCheck("v8::V8::RemoveGCPrologueCallback()")) return;
4127 i::Heap::RemoveGCPrologueCallback(callback);
4128}
4129
4130
4131void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
4132 if (IsDeadCheck("v8::V8::AddGCEpilogueCallback()")) return;
4133 i::Heap::AddGCEpilogueCallback(callback, gc_type);
4134}
4135
4136
4137void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
4138 if (IsDeadCheck("v8::V8::RemoveGCEpilogueCallback()")) return;
4139 i::Heap::RemoveGCEpilogueCallback(callback);
4140}
4141
4142
Iain Merrick9ac36c92010-09-13 15:29:50 +01004143void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
4144 ObjectSpace space,
4145 AllocationAction action) {
4146 if (IsDeadCheck("v8::V8::AddMemoryAllocationCallback()")) return;
4147 i::MemoryAllocator::AddMemoryAllocationCallback(callback,
4148 space,
4149 action);
4150}
4151
4152
4153void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
4154 if (IsDeadCheck("v8::V8::RemoveMemoryAllocationCallback()")) return;
4155 i::MemoryAllocator::RemoveMemoryAllocationCallback(callback);
4156}
4157
4158
Steve Blocka7e24c12009-10-30 11:49:00 +00004159void V8::PauseProfiler() {
4160#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004161 PauseProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00004162#endif
4163}
4164
4165
4166void V8::ResumeProfiler() {
4167#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004168 ResumeProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00004169#endif
4170}
4171
4172
4173bool V8::IsProfilerPaused() {
4174#ifdef ENABLE_LOGGING_AND_PROFILING
4175 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
4176#else
4177 return true;
4178#endif
4179}
4180
4181
Andrei Popescu402d9372010-02-26 13:31:12 +00004182void V8::ResumeProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004183#ifdef ENABLE_LOGGING_AND_PROFILING
4184 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
4185 // Snapshot mode: resume modules, perform GC, then pause only
4186 // those modules which haven't been started prior to making a
4187 // snapshot.
4188
Steve Block6ded16b2010-05-10 14:33:55 +01004189 // Make a GC prior to taking a snapshot.
4190 i::Heap::CollectAllGarbage(false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004191 // Reset snapshot flag and CPU module flags.
4192 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
4193 const int current_flags = i::Logger::GetActiveProfilerModules();
Andrei Popescu402d9372010-02-26 13:31:12 +00004194 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004195 i::Heap::CollectAllGarbage(false);
Andrei Popescu402d9372010-02-26 13:31:12 +00004196 i::Logger::PauseProfiler(~current_flags & flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004197 } else {
Andrei Popescu402d9372010-02-26 13:31:12 +00004198 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004199 }
4200#endif
4201}
4202
4203
Andrei Popescu402d9372010-02-26 13:31:12 +00004204void V8::PauseProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004205#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004206 i::Logger::PauseProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004207#endif
4208}
4209
4210
4211int V8::GetActiveProfilerModules() {
4212#ifdef ENABLE_LOGGING_AND_PROFILING
4213 return i::Logger::GetActiveProfilerModules();
4214#else
4215 return PROFILER_MODULE_NONE;
4216#endif
4217}
4218
4219
4220int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
4221#ifdef ENABLE_LOGGING_AND_PROFILING
Steve Block6ded16b2010-05-10 14:33:55 +01004222 ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
Steve Blocka7e24c12009-10-30 11:49:00 +00004223 return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
4224#endif
4225 return 0;
4226}
4227
4228
4229int V8::GetCurrentThreadId() {
4230 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
4231 EnsureInitialized("V8::GetCurrentThreadId()");
4232 return i::Top::thread_id();
4233}
4234
4235
4236void V8::TerminateExecution(int thread_id) {
4237 if (!i::V8::IsRunning()) return;
4238 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
4239 // If the thread_id identifies the current thread just terminate
4240 // execution right away. Otherwise, ask the thread manager to
4241 // terminate the thread with the given id if any.
4242 if (thread_id == i::Top::thread_id()) {
4243 i::StackGuard::TerminateExecution();
4244 } else {
4245 i::ThreadManager::TerminateExecution(thread_id);
4246 }
4247}
4248
4249
4250void V8::TerminateExecution() {
4251 if (!i::V8::IsRunning()) return;
4252 i::StackGuard::TerminateExecution();
4253}
4254
4255
Steve Block6ded16b2010-05-10 14:33:55 +01004256bool V8::IsExecutionTerminating() {
4257 if (!i::V8::IsRunning()) return false;
4258 if (i::Top::has_scheduled_exception()) {
4259 return i::Top::scheduled_exception() == i::Heap::termination_exception();
4260 }
4261 return false;
4262}
4263
4264
Steve Blocka7e24c12009-10-30 11:49:00 +00004265String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
4266 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
4267 if (obj.IsEmpty()) {
4268 str_ = NULL;
4269 length_ = 0;
4270 return;
4271 }
4272 ENTER_V8;
4273 HandleScope scope;
4274 TryCatch try_catch;
4275 Handle<String> str = obj->ToString();
4276 if (str.IsEmpty()) {
4277 str_ = NULL;
4278 length_ = 0;
4279 } else {
4280 length_ = str->Utf8Length();
4281 str_ = i::NewArray<char>(length_ + 1);
4282 str->WriteUtf8(str_);
4283 }
4284}
4285
4286
4287String::Utf8Value::~Utf8Value() {
4288 i::DeleteArray(str_);
4289}
4290
4291
4292String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
4293 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
4294 if (obj.IsEmpty()) {
4295 str_ = NULL;
4296 length_ = 0;
4297 return;
4298 }
4299 ENTER_V8;
4300 HandleScope scope;
4301 TryCatch try_catch;
4302 Handle<String> str = obj->ToString();
4303 if (str.IsEmpty()) {
4304 str_ = NULL;
4305 length_ = 0;
4306 } else {
4307 length_ = str->Length();
4308 str_ = i::NewArray<char>(length_ + 1);
4309 str->WriteAscii(str_);
4310 }
4311}
4312
4313
4314String::AsciiValue::~AsciiValue() {
4315 i::DeleteArray(str_);
4316}
4317
4318
4319String::Value::Value(v8::Handle<v8::Value> obj) {
4320 EnsureInitialized("v8::String::Value::Value()");
4321 if (obj.IsEmpty()) {
4322 str_ = NULL;
4323 length_ = 0;
4324 return;
4325 }
4326 ENTER_V8;
4327 HandleScope scope;
4328 TryCatch try_catch;
4329 Handle<String> str = obj->ToString();
4330 if (str.IsEmpty()) {
4331 str_ = NULL;
4332 length_ = 0;
4333 } else {
4334 length_ = str->Length();
4335 str_ = i::NewArray<uint16_t>(length_ + 1);
4336 str->Write(str_);
4337 }
4338}
4339
4340
4341String::Value::~Value() {
4342 i::DeleteArray(str_);
4343}
4344
4345Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
4346 LOG_API("RangeError");
4347 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
4348 ENTER_V8;
4349 i::Object* error;
4350 {
4351 HandleScope scope;
4352 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4353 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
4354 error = *result;
4355 }
4356 i::Handle<i::Object> result(error);
4357 return Utils::ToLocal(result);
4358}
4359
4360Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
4361 LOG_API("ReferenceError");
4362 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
4363 ENTER_V8;
4364 i::Object* error;
4365 {
4366 HandleScope scope;
4367 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4368 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
4369 error = *result;
4370 }
4371 i::Handle<i::Object> result(error);
4372 return Utils::ToLocal(result);
4373}
4374
4375Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
4376 LOG_API("SyntaxError");
4377 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
4378 ENTER_V8;
4379 i::Object* error;
4380 {
4381 HandleScope scope;
4382 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4383 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
4384 error = *result;
4385 }
4386 i::Handle<i::Object> result(error);
4387 return Utils::ToLocal(result);
4388}
4389
4390Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
4391 LOG_API("TypeError");
4392 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
4393 ENTER_V8;
4394 i::Object* error;
4395 {
4396 HandleScope scope;
4397 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4398 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
4399 error = *result;
4400 }
4401 i::Handle<i::Object> result(error);
4402 return Utils::ToLocal(result);
4403}
4404
4405Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
4406 LOG_API("Error");
4407 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
4408 ENTER_V8;
4409 i::Object* error;
4410 {
4411 HandleScope scope;
4412 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4413 i::Handle<i::Object> result = i::Factory::NewError(message);
4414 error = *result;
4415 }
4416 i::Handle<i::Object> result(error);
4417 return Utils::ToLocal(result);
4418}
4419
4420
4421// --- D e b u g S u p p o r t ---
4422
4423#ifdef ENABLE_DEBUGGER_SUPPORT
Leon Clarkef7060e22010-06-03 12:02:55 +01004424
4425static v8::Debug::EventCallback event_callback = NULL;
4426
4427static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) {
4428 if (event_callback) {
4429 event_callback(event_details.GetEvent(),
4430 event_details.GetExecutionState(),
4431 event_details.GetEventData(),
4432 event_details.GetCallbackData());
4433 }
4434}
4435
4436
Steve Blocka7e24c12009-10-30 11:49:00 +00004437bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
4438 EnsureInitialized("v8::Debug::SetDebugEventListener()");
4439 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4440 ENTER_V8;
Leon Clarkef7060e22010-06-03 12:02:55 +01004441
4442 event_callback = that;
4443
4444 HandleScope scope;
4445 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4446 if (that != NULL) {
4447 proxy = i::Factory::NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
4448 }
4449 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4450 return true;
4451}
4452
4453
4454bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
4455 EnsureInitialized("v8::Debug::SetDebugEventListener2()");
4456 ON_BAILOUT("v8::Debug::SetDebugEventListener2()", return false);
4457 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004458 HandleScope scope;
4459 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4460 if (that != NULL) {
4461 proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
4462 }
4463 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4464 return true;
4465}
4466
4467
4468bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
4469 Handle<Value> data) {
4470 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4471 ENTER_V8;
4472 i::Debugger::SetEventListener(Utils::OpenHandle(*that),
4473 Utils::OpenHandle(*data));
4474 return true;
4475}
4476
4477
4478void Debug::DebugBreak() {
4479 if (!i::V8::IsRunning()) return;
4480 i::StackGuard::DebugBreak();
4481}
4482
4483
Ben Murdochf87a2032010-10-22 12:50:53 +01004484void Debug::CancelDebugBreak() {
4485 i::StackGuard::Continue(i::DEBUGBREAK);
4486}
4487
4488
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004489void Debug::DebugBreakForCommand(ClientData* data) {
4490 if (!i::V8::IsRunning()) return;
4491 i::Debugger::EnqueueDebugCommand(data);
4492}
4493
4494
Steve Blocka7e24c12009-10-30 11:49:00 +00004495static v8::Debug::MessageHandler message_handler = NULL;
4496
4497static void MessageHandlerWrapper(const v8::Debug::Message& message) {
4498 if (message_handler) {
4499 v8::String::Value json(message.GetJSON());
4500 message_handler(*json, json.length(), message.GetClientData());
4501 }
4502}
4503
4504
4505void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
4506 bool message_handler_thread) {
4507 EnsureInitialized("v8::Debug::SetMessageHandler");
4508 ENTER_V8;
4509 // Message handler thread not supported any more. Parameter temporally left in
4510 // the API for client compatability reasons.
4511 CHECK(!message_handler_thread);
4512
4513 // TODO(sgjesse) support the old message handler API through a simple wrapper.
4514 message_handler = handler;
4515 if (message_handler != NULL) {
4516 i::Debugger::SetMessageHandler(MessageHandlerWrapper);
4517 } else {
4518 i::Debugger::SetMessageHandler(NULL);
4519 }
4520}
4521
4522
4523void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
4524 EnsureInitialized("v8::Debug::SetMessageHandler");
4525 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004526 i::Debugger::SetMessageHandler(handler);
4527}
4528
4529
4530void Debug::SendCommand(const uint16_t* command, int length,
4531 ClientData* client_data) {
4532 if (!i::V8::IsRunning()) return;
4533 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
4534 client_data);
4535}
4536
4537
4538void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
4539 int period) {
4540 EnsureInitialized("v8::Debug::SetHostDispatchHandler");
4541 ENTER_V8;
4542 i::Debugger::SetHostDispatchHandler(handler, period);
4543}
4544
4545
Steve Blockd0582a62009-12-15 09:54:21 +00004546void Debug::SetDebugMessageDispatchHandler(
Leon Clarkee46be812010-01-19 14:06:41 +00004547 DebugMessageDispatchHandler handler, bool provide_locker) {
Steve Blockd0582a62009-12-15 09:54:21 +00004548 EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
4549 ENTER_V8;
Leon Clarkee46be812010-01-19 14:06:41 +00004550 i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
Steve Blockd0582a62009-12-15 09:54:21 +00004551}
4552
4553
Steve Blocka7e24c12009-10-30 11:49:00 +00004554Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
4555 v8::Handle<v8::Value> data) {
4556 if (!i::V8::IsRunning()) return Local<Value>();
4557 ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
4558 ENTER_V8;
4559 i::Handle<i::Object> result;
4560 EXCEPTION_PREAMBLE();
4561 if (data.IsEmpty()) {
4562 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4563 i::Factory::undefined_value(),
4564 &has_pending_exception);
4565 } else {
4566 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4567 Utils::OpenHandle(*data),
4568 &has_pending_exception);
4569 }
4570 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4571 return Utils::ToLocal(result);
4572}
4573
4574
4575Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
4576 if (!i::V8::IsRunning()) return Local<Value>();
4577 ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
4578 ENTER_V8;
4579 v8::HandleScope scope;
4580 i::Debug::Load();
4581 i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
4582 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
4583 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
4584 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
4585 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
4586 const int kArgc = 1;
4587 v8::Handle<v8::Value> argv[kArgc] = { obj };
4588 EXCEPTION_PREAMBLE();
4589 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
4590 kArgc,
4591 argv);
4592 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4593 return scope.Close(result);
4594}
4595
4596
Leon Clarkee46be812010-01-19 14:06:41 +00004597bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
4598 return i::Debugger::StartAgent(name, port, wait_for_connection);
Steve Blocka7e24c12009-10-30 11:49:00 +00004599}
Leon Clarkee46be812010-01-19 14:06:41 +00004600
4601void Debug::ProcessDebugMessages() {
4602 i::Execution::ProcessDebugMesssages(true);
4603}
4604
Steve Block6ded16b2010-05-10 14:33:55 +01004605Local<Context> Debug::GetDebugContext() {
4606 EnsureInitialized("v8::Debug::GetDebugContext()");
4607 ENTER_V8;
4608 return Utils::ToLocal(i::Debugger::GetDebugContext());
4609}
4610
Steve Blocka7e24c12009-10-30 11:49:00 +00004611#endif // ENABLE_DEBUGGER_SUPPORT
4612
Steve Block6ded16b2010-05-10 14:33:55 +01004613
4614#ifdef ENABLE_LOGGING_AND_PROFILING
4615
4616Handle<String> CpuProfileNode::GetFunctionName() const {
4617 IsDeadCheck("v8::CpuProfileNode::GetFunctionName");
4618 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4619 const i::CodeEntry* entry = node->entry();
4620 if (!entry->has_name_prefix()) {
4621 return Handle<String>(ToApi<String>(
4622 i::Factory::LookupAsciiSymbol(entry->name())));
4623 } else {
4624 return Handle<String>(ToApi<String>(i::Factory::NewConsString(
4625 i::Factory::LookupAsciiSymbol(entry->name_prefix()),
4626 i::Factory::LookupAsciiSymbol(entry->name()))));
4627 }
4628}
4629
4630
4631Handle<String> CpuProfileNode::GetScriptResourceName() const {
4632 IsDeadCheck("v8::CpuProfileNode::GetScriptResourceName");
4633 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4634 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4635 node->entry()->resource_name())));
4636}
4637
4638
4639int CpuProfileNode::GetLineNumber() const {
4640 IsDeadCheck("v8::CpuProfileNode::GetLineNumber");
4641 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
4642}
4643
4644
4645double CpuProfileNode::GetTotalTime() const {
4646 IsDeadCheck("v8::CpuProfileNode::GetTotalTime");
4647 return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis();
4648}
4649
4650
4651double CpuProfileNode::GetSelfTime() const {
4652 IsDeadCheck("v8::CpuProfileNode::GetSelfTime");
4653 return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis();
4654}
4655
4656
4657double CpuProfileNode::GetTotalSamplesCount() const {
4658 IsDeadCheck("v8::CpuProfileNode::GetTotalSamplesCount");
4659 return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
4660}
4661
4662
4663double CpuProfileNode::GetSelfSamplesCount() const {
4664 IsDeadCheck("v8::CpuProfileNode::GetSelfSamplesCount");
4665 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
4666}
4667
4668
4669unsigned CpuProfileNode::GetCallUid() const {
4670 IsDeadCheck("v8::CpuProfileNode::GetCallUid");
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004671 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
Steve Block6ded16b2010-05-10 14:33:55 +01004672}
4673
4674
4675int CpuProfileNode::GetChildrenCount() const {
4676 IsDeadCheck("v8::CpuProfileNode::GetChildrenCount");
4677 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
4678}
4679
4680
4681const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
4682 IsDeadCheck("v8::CpuProfileNode::GetChild");
4683 const i::ProfileNode* child =
4684 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
4685 return reinterpret_cast<const CpuProfileNode*>(child);
4686}
4687
4688
4689unsigned CpuProfile::GetUid() const {
4690 IsDeadCheck("v8::CpuProfile::GetUid");
4691 return reinterpret_cast<const i::CpuProfile*>(this)->uid();
4692}
4693
4694
4695Handle<String> CpuProfile::GetTitle() const {
4696 IsDeadCheck("v8::CpuProfile::GetTitle");
4697 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4698 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4699 profile->title())));
4700}
4701
4702
4703const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
4704 IsDeadCheck("v8::CpuProfile::GetBottomUpRoot");
4705 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4706 return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
4707}
4708
4709
4710const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
4711 IsDeadCheck("v8::CpuProfile::GetTopDownRoot");
4712 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4713 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
4714}
4715
4716
4717int CpuProfiler::GetProfilesCount() {
4718 IsDeadCheck("v8::CpuProfiler::GetProfilesCount");
4719 return i::CpuProfiler::GetProfilesCount();
4720}
4721
4722
Leon Clarkef7060e22010-06-03 12:02:55 +01004723const CpuProfile* CpuProfiler::GetProfile(int index,
4724 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004725 IsDeadCheck("v8::CpuProfiler::GetProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004726 return reinterpret_cast<const CpuProfile*>(
4727 i::CpuProfiler::GetProfile(
4728 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4729 index));
Steve Block6ded16b2010-05-10 14:33:55 +01004730}
4731
4732
Leon Clarkef7060e22010-06-03 12:02:55 +01004733const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
4734 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004735 IsDeadCheck("v8::CpuProfiler::FindProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004736 return reinterpret_cast<const CpuProfile*>(
4737 i::CpuProfiler::FindProfile(
4738 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4739 uid));
Steve Block6ded16b2010-05-10 14:33:55 +01004740}
4741
4742
4743void CpuProfiler::StartProfiling(Handle<String> title) {
4744 IsDeadCheck("v8::CpuProfiler::StartProfiling");
4745 i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
4746}
4747
4748
Leon Clarkef7060e22010-06-03 12:02:55 +01004749const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
4750 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004751 IsDeadCheck("v8::CpuProfiler::StopProfiling");
4752 return reinterpret_cast<const CpuProfile*>(
Leon Clarkef7060e22010-06-03 12:02:55 +01004753 i::CpuProfiler::StopProfiling(
4754 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4755 *Utils::OpenHandle(*title)));
Steve Block6ded16b2010-05-10 14:33:55 +01004756}
4757
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004758
Iain Merrick75681382010-08-19 15:07:18 +01004759static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
4760 return const_cast<i::HeapGraphEdge*>(
4761 reinterpret_cast<const i::HeapGraphEdge*>(edge));
4762}
4763
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004764HeapGraphEdge::Type HeapGraphEdge::GetType() const {
4765 IsDeadCheck("v8::HeapGraphEdge::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004766 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004767}
4768
4769
4770Handle<Value> HeapGraphEdge::GetName() const {
4771 IsDeadCheck("v8::HeapGraphEdge::GetName");
Iain Merrick75681382010-08-19 15:07:18 +01004772 i::HeapGraphEdge* edge = ToInternal(this);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004773 switch (edge->type()) {
Iain Merrick75681382010-08-19 15:07:18 +01004774 case i::HeapGraphEdge::kContextVariable:
4775 case i::HeapGraphEdge::kInternal:
4776 case i::HeapGraphEdge::kProperty:
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004777 case i::HeapGraphEdge::kShortcut:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004778 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4779 edge->name())));
Iain Merrick75681382010-08-19 15:07:18 +01004780 case i::HeapGraphEdge::kElement:
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004781 case i::HeapGraphEdge::kHidden:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004782 return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt(
4783 edge->index())));
4784 default: UNREACHABLE();
4785 }
4786 return ImplementationUtilities::Undefined();
4787}
4788
4789
4790const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
4791 IsDeadCheck("v8::HeapGraphEdge::GetFromNode");
Iain Merrick75681382010-08-19 15:07:18 +01004792 const i::HeapEntry* from = ToInternal(this)->From();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004793 return reinterpret_cast<const HeapGraphNode*>(from);
4794}
4795
4796
4797const HeapGraphNode* HeapGraphEdge::GetToNode() const {
4798 IsDeadCheck("v8::HeapGraphEdge::GetToNode");
Iain Merrick75681382010-08-19 15:07:18 +01004799 const i::HeapEntry* to = ToInternal(this)->to();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004800 return reinterpret_cast<const HeapGraphNode*>(to);
4801}
4802
4803
Iain Merrick75681382010-08-19 15:07:18 +01004804static i::HeapGraphPath* ToInternal(const HeapGraphPath* path) {
4805 return const_cast<i::HeapGraphPath*>(
4806 reinterpret_cast<const i::HeapGraphPath*>(path));
4807}
4808
4809
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004810int HeapGraphPath::GetEdgesCount() const {
Iain Merrick75681382010-08-19 15:07:18 +01004811 return ToInternal(this)->path()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004812}
4813
4814
4815const HeapGraphEdge* HeapGraphPath::GetEdge(int index) const {
4816 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004817 ToInternal(this)->path()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004818}
4819
4820
4821const HeapGraphNode* HeapGraphPath::GetFromNode() const {
4822 return GetEdgesCount() > 0 ? GetEdge(0)->GetFromNode() : NULL;
4823}
4824
4825
4826const HeapGraphNode* HeapGraphPath::GetToNode() const {
4827 const int count = GetEdgesCount();
4828 return count > 0 ? GetEdge(count - 1)->GetToNode() : NULL;
4829}
4830
4831
Iain Merrick75681382010-08-19 15:07:18 +01004832static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
4833 return const_cast<i::HeapEntry*>(
4834 reinterpret_cast<const i::HeapEntry*>(entry));
4835}
4836
4837
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004838HeapGraphNode::Type HeapGraphNode::GetType() const {
4839 IsDeadCheck("v8::HeapGraphNode::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004840 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004841}
4842
4843
4844Handle<String> HeapGraphNode::GetName() const {
4845 IsDeadCheck("v8::HeapGraphNode::GetName");
4846 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004847 ToInternal(this)->name())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004848}
4849
4850
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004851uint64_t HeapGraphNode::GetId() const {
4852 IsDeadCheck("v8::HeapGraphNode::GetId");
Steve Block791712a2010-08-27 10:21:07 +01004853 ASSERT(ToInternal(this)->snapshot()->type() != i::HeapSnapshot::kAggregated);
Iain Merrick75681382010-08-19 15:07:18 +01004854 return ToInternal(this)->id();
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004855}
4856
4857
Steve Block791712a2010-08-27 10:21:07 +01004858int HeapGraphNode::GetInstancesCount() const {
4859 IsDeadCheck("v8::HeapGraphNode::GetInstancesCount");
4860 ASSERT(ToInternal(this)->snapshot()->type() == i::HeapSnapshot::kAggregated);
4861 return static_cast<int>(ToInternal(this)->id());
4862}
4863
4864
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004865int HeapGraphNode::GetSelfSize() const {
4866 IsDeadCheck("v8::HeapGraphNode::GetSelfSize");
Iain Merrick75681382010-08-19 15:07:18 +01004867 return ToInternal(this)->self_size();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004868}
4869
4870
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004871int HeapGraphNode::GetRetainedSize(bool exact) const {
Iain Merrick75681382010-08-19 15:07:18 +01004872 IsDeadCheck("v8::HeapSnapshot::GetRetainedSize");
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004873 return ToInternal(this)->RetainedSize(exact);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004874}
4875
4876
4877int HeapGraphNode::GetChildrenCount() const {
4878 IsDeadCheck("v8::HeapSnapshot::GetChildrenCount");
Iain Merrick75681382010-08-19 15:07:18 +01004879 return ToInternal(this)->children().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004880}
4881
4882
4883const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
4884 IsDeadCheck("v8::HeapSnapshot::GetChild");
4885 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004886 &ToInternal(this)->children()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004887}
4888
4889
4890int HeapGraphNode::GetRetainersCount() const {
4891 IsDeadCheck("v8::HeapSnapshot::GetRetainersCount");
Iain Merrick75681382010-08-19 15:07:18 +01004892 return ToInternal(this)->retainers().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004893}
4894
4895
4896const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const {
4897 IsDeadCheck("v8::HeapSnapshot::GetRetainer");
4898 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004899 ToInternal(this)->retainers()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004900}
4901
4902
4903int HeapGraphNode::GetRetainingPathsCount() const {
4904 IsDeadCheck("v8::HeapSnapshot::GetRetainingPathsCount");
Iain Merrick75681382010-08-19 15:07:18 +01004905 return ToInternal(this)->GetRetainingPaths()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004906}
4907
4908
4909const HeapGraphPath* HeapGraphNode::GetRetainingPath(int index) const {
4910 IsDeadCheck("v8::HeapSnapshot::GetRetainingPath");
4911 return reinterpret_cast<const HeapGraphPath*>(
Iain Merrick75681382010-08-19 15:07:18 +01004912 ToInternal(this)->GetRetainingPaths()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004913}
4914
4915
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004916const HeapGraphNode* HeapGraphNode::GetDominatorNode() const {
4917 IsDeadCheck("v8::HeapSnapshot::GetDominatorNode");
4918 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->dominator());
4919}
4920
4921
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004922const HeapGraphNode* HeapSnapshotsDiff::GetAdditionsRoot() const {
4923 IsDeadCheck("v8::HeapSnapshotsDiff::GetAdditionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004924 i::HeapSnapshotsDiff* diff =
4925 const_cast<i::HeapSnapshotsDiff*>(
4926 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004927 return reinterpret_cast<const HeapGraphNode*>(diff->additions_root());
4928}
4929
4930
4931const HeapGraphNode* HeapSnapshotsDiff::GetDeletionsRoot() const {
4932 IsDeadCheck("v8::HeapSnapshotsDiff::GetDeletionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004933 i::HeapSnapshotsDiff* diff =
4934 const_cast<i::HeapSnapshotsDiff*>(
4935 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004936 return reinterpret_cast<const HeapGraphNode*>(diff->deletions_root());
4937}
4938
4939
Iain Merrick75681382010-08-19 15:07:18 +01004940static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
4941 return const_cast<i::HeapSnapshot*>(
4942 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
4943}
4944
4945
Steve Block791712a2010-08-27 10:21:07 +01004946HeapSnapshot::Type HeapSnapshot::GetType() const {
4947 IsDeadCheck("v8::HeapSnapshot::GetType");
4948 return static_cast<HeapSnapshot::Type>(ToInternal(this)->type());
4949}
4950
4951
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004952unsigned HeapSnapshot::GetUid() const {
4953 IsDeadCheck("v8::HeapSnapshot::GetUid");
Iain Merrick75681382010-08-19 15:07:18 +01004954 return ToInternal(this)->uid();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004955}
4956
4957
4958Handle<String> HeapSnapshot::GetTitle() const {
4959 IsDeadCheck("v8::HeapSnapshot::GetTitle");
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004960 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004961 ToInternal(this)->title())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004962}
4963
4964
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004965const HeapGraphNode* HeapSnapshot::GetRoot() const {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004966 IsDeadCheck("v8::HeapSnapshot::GetHead");
Iain Merrick75681382010-08-19 15:07:18 +01004967 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004968}
4969
4970
Ben Murdochb0fe1622011-05-05 13:52:32 +01004971const HeapGraphNode* HeapSnapshot::GetNodeById(uint64_t id) const {
4972 IsDeadCheck("v8::HeapSnapshot::GetNodeById");
4973 return reinterpret_cast<const HeapGraphNode*>(
4974 ToInternal(this)->GetEntryById(id));
4975}
4976
4977
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004978const HeapSnapshotsDiff* HeapSnapshot::CompareWith(
4979 const HeapSnapshot* snapshot) const {
4980 IsDeadCheck("v8::HeapSnapshot::CompareWith");
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004981 return reinterpret_cast<const HeapSnapshotsDiff*>(
Iain Merrick75681382010-08-19 15:07:18 +01004982 ToInternal(this)->CompareWith(ToInternal(snapshot)));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004983}
4984
4985
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004986void HeapSnapshot::Serialize(OutputStream* stream,
4987 HeapSnapshot::SerializationFormat format) const {
4988 IsDeadCheck("v8::HeapSnapshot::Serialize");
4989 ApiCheck(format == kJSON,
4990 "v8::HeapSnapshot::Serialize",
4991 "Unknown serialization format");
4992 ApiCheck(stream->GetOutputEncoding() == OutputStream::kAscii,
4993 "v8::HeapSnapshot::Serialize",
4994 "Unsupported output encoding");
4995 ApiCheck(stream->GetChunkSize() > 0,
4996 "v8::HeapSnapshot::Serialize",
4997 "Invalid stream chunk size");
4998 i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
4999 serializer.Serialize(stream);
5000}
5001
5002
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005003int HeapProfiler::GetSnapshotsCount() {
5004 IsDeadCheck("v8::HeapProfiler::GetSnapshotsCount");
5005 return i::HeapProfiler::GetSnapshotsCount();
5006}
5007
5008
5009const HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
5010 IsDeadCheck("v8::HeapProfiler::GetSnapshot");
5011 return reinterpret_cast<const HeapSnapshot*>(
5012 i::HeapProfiler::GetSnapshot(index));
5013}
5014
5015
5016const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
5017 IsDeadCheck("v8::HeapProfiler::FindSnapshot");
5018 return reinterpret_cast<const HeapSnapshot*>(
5019 i::HeapProfiler::FindSnapshot(uid));
5020}
5021
5022
Steve Block791712a2010-08-27 10:21:07 +01005023const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title,
Ben Murdochb0fe1622011-05-05 13:52:32 +01005024 HeapSnapshot::Type type,
5025 ActivityControl* control) {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005026 IsDeadCheck("v8::HeapProfiler::TakeSnapshot");
Steve Block791712a2010-08-27 10:21:07 +01005027 i::HeapSnapshot::Type internal_type = i::HeapSnapshot::kFull;
5028 switch (type) {
5029 case HeapSnapshot::kFull:
5030 internal_type = i::HeapSnapshot::kFull;
5031 break;
5032 case HeapSnapshot::kAggregated:
5033 internal_type = i::HeapSnapshot::kAggregated;
5034 break;
5035 default:
5036 UNREACHABLE();
5037 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005038 return reinterpret_cast<const HeapSnapshot*>(
Ben Murdochb0fe1622011-05-05 13:52:32 +01005039 i::HeapProfiler::TakeSnapshot(
5040 *Utils::OpenHandle(*title), internal_type, control));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005041}
5042
Steve Block6ded16b2010-05-10 14:33:55 +01005043#endif // ENABLE_LOGGING_AND_PROFILING
5044
5045
Ben Murdochb0fe1622011-05-05 13:52:32 +01005046v8::Testing::StressType internal::Testing::stress_type_ =
5047 v8::Testing::kStressTypeOpt;
5048
5049
5050void Testing::SetStressRunType(Testing::StressType type) {
5051 internal::Testing::set_stress_type(type);
5052}
5053
5054int Testing::GetStressRuns() {
5055 if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs;
5056#ifdef DEBUG
5057 // In debug mode the code runs much slower so stressing will only make two
5058 // runs.
5059 return 2;
5060#else
5061 return 5;
5062#endif
5063}
5064
5065
5066static void SetFlagsFromString(const char* flags) {
5067 V8::SetFlagsFromString(flags, i::StrLength(flags));
5068}
5069
5070
5071void Testing::PrepareStressRun(int run) {
5072 static const char* kLazyOptimizations =
5073 "--prepare-always-opt --nolimit-inlining "
5074 "--noalways-opt --noopt-eagerly";
5075 static const char* kEagerOptimizations = "--opt-eagerly";
5076 static const char* kForcedOptimizations = "--always-opt";
5077
5078 // If deoptimization stressed turn on frequent deoptimization. If no value
5079 // is spefified through --deopt-every-n-times use a default default value.
5080 static const char* kDeoptEvery13Times = "--deopt-every-n-times=13";
5081 if (internal::Testing::stress_type() == Testing::kStressTypeDeopt &&
5082 internal::FLAG_deopt_every_n_times == 0) {
5083 SetFlagsFromString(kDeoptEvery13Times);
5084 }
5085
5086#ifdef DEBUG
5087 // As stressing in debug mode only make two runs skip the deopt stressing
5088 // here.
5089 if (run == GetStressRuns() - 1) {
5090 SetFlagsFromString(kForcedOptimizations);
5091 } else {
5092 SetFlagsFromString(kEagerOptimizations);
5093 SetFlagsFromString(kLazyOptimizations);
5094 }
5095#else
5096 if (run == GetStressRuns() - 1) {
5097 SetFlagsFromString(kForcedOptimizations);
5098 } else if (run == GetStressRuns() - 2) {
5099 SetFlagsFromString(kEagerOptimizations);
5100 } else {
5101 SetFlagsFromString(kLazyOptimizations);
5102 }
5103#endif
5104}
5105
5106
Steve Blocka7e24c12009-10-30 11:49:00 +00005107namespace internal {
5108
5109
5110HandleScopeImplementer* HandleScopeImplementer::instance() {
5111 return &thread_local;
5112}
5113
5114
5115void HandleScopeImplementer::FreeThreadResources() {
5116 thread_local.Free();
5117}
5118
5119
5120char* HandleScopeImplementer::ArchiveThread(char* storage) {
5121 return thread_local.ArchiveThreadHelper(storage);
5122}
5123
5124
5125char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
5126 v8::ImplementationUtilities::HandleScopeData* current =
5127 v8::ImplementationUtilities::CurrentHandleScope();
5128 handle_scope_data_ = *current;
5129 memcpy(storage, this, sizeof(*this));
5130
5131 ResetAfterArchive();
5132 current->Initialize();
5133
5134 return storage + ArchiveSpacePerThread();
5135}
5136
5137
5138int HandleScopeImplementer::ArchiveSpacePerThread() {
5139 return sizeof(thread_local);
5140}
5141
5142
5143char* HandleScopeImplementer::RestoreThread(char* storage) {
5144 return thread_local.RestoreThreadHelper(storage);
5145}
5146
5147
5148char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
5149 memcpy(this, storage, sizeof(*this));
5150 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
5151 return storage + ArchiveSpacePerThread();
5152}
5153
5154
5155void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
5156 // Iterate over all handles in the blocks except for the last.
5157 for (int i = blocks()->length() - 2; i >= 0; --i) {
5158 Object** block = blocks()->at(i);
5159 v->VisitPointers(block, &block[kHandleBlockSize]);
5160 }
5161
5162 // Iterate over live handles in the last block (if any).
5163 if (!blocks()->is_empty()) {
5164 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
5165 }
5166
5167 if (!saved_contexts_.is_empty()) {
5168 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
5169 v->VisitPointers(start, start + saved_contexts_.length());
5170 }
5171}
5172
5173
5174void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
5175 v8::ImplementationUtilities::HandleScopeData* current =
5176 v8::ImplementationUtilities::CurrentHandleScope();
5177 thread_local.handle_scope_data_ = *current;
5178 thread_local.IterateThis(v);
5179}
5180
5181
5182char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
5183 HandleScopeImplementer* thread_local =
5184 reinterpret_cast<HandleScopeImplementer*>(storage);
5185 thread_local->IterateThis(v);
5186 return storage + ArchiveSpacePerThread();
5187}
5188
5189} } // namespace v8::internal