blob: 073306f071a2a260029750d82317014e0067f84f [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) {
118 ENTER_V8;
119 API_Fatal(location, message);
120}
121
122
Steve Blocka7e24c12009-10-30 11:49:00 +0000123static FatalErrorCallback& GetFatalErrorHandler() {
124 if (exception_behavior == NULL) {
125 exception_behavior = DefaultFatalErrorHandler;
126 }
127 return exception_behavior;
128}
129
130
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800131void i::FatalProcessOutOfMemory(const char* location) {
132 i::V8::FatalProcessOutOfMemory(location, false);
133}
134
Steve Blocka7e24c12009-10-30 11:49:00 +0000135
136// When V8 cannot allocated memory FatalProcessOutOfMemory is called.
137// The default fatal error handler is called and execution is stopped.
Ben Murdochbb769b22010-08-11 14:56:33 +0100138void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
Steve Blockd0582a62009-12-15 09:54:21 +0000139 i::HeapStats heap_stats;
140 int start_marker;
141 heap_stats.start_marker = &start_marker;
142 int new_space_size;
143 heap_stats.new_space_size = &new_space_size;
144 int new_space_capacity;
145 heap_stats.new_space_capacity = &new_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100146 intptr_t old_pointer_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000147 heap_stats.old_pointer_space_size = &old_pointer_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100148 intptr_t old_pointer_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000149 heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100150 intptr_t old_data_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000151 heap_stats.old_data_space_size = &old_data_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100152 intptr_t old_data_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000153 heap_stats.old_data_space_capacity = &old_data_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100154 intptr_t code_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000155 heap_stats.code_space_size = &code_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100156 intptr_t code_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000157 heap_stats.code_space_capacity = &code_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100158 intptr_t map_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000159 heap_stats.map_space_size = &map_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100160 intptr_t map_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000161 heap_stats.map_space_capacity = &map_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100162 intptr_t cell_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000163 heap_stats.cell_space_size = &cell_space_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100164 intptr_t cell_space_capacity;
Steve Blockd0582a62009-12-15 09:54:21 +0000165 heap_stats.cell_space_capacity = &cell_space_capacity;
Ben Murdochf87a2032010-10-22 12:50:53 +0100166 intptr_t lo_space_size;
Steve Blockd0582a62009-12-15 09:54:21 +0000167 heap_stats.lo_space_size = &lo_space_size;
168 int global_handle_count;
169 heap_stats.global_handle_count = &global_handle_count;
170 int weak_global_handle_count;
171 heap_stats.weak_global_handle_count = &weak_global_handle_count;
172 int pending_global_handle_count;
173 heap_stats.pending_global_handle_count = &pending_global_handle_count;
174 int near_death_global_handle_count;
175 heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
176 int destroyed_global_handle_count;
177 heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count;
Ben Murdochf87a2032010-10-22 12:50:53 +0100178 intptr_t memory_allocator_size;
Ben Murdochbb769b22010-08-11 14:56:33 +0100179 heap_stats.memory_allocator_size = &memory_allocator_size;
Ben Murdochf87a2032010-10-22 12:50:53 +0100180 intptr_t memory_allocator_capacity;
Ben Murdochbb769b22010-08-11 14:56:33 +0100181 heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
182 int objects_per_type[LAST_TYPE + 1] = {0};
183 heap_stats.objects_per_type = objects_per_type;
184 int size_per_type[LAST_TYPE + 1] = {0};
185 heap_stats.size_per_type = size_per_type;
Iain Merrick75681382010-08-19 15:07:18 +0100186 int os_error;
187 heap_stats.os_error = &os_error;
Steve Blockd0582a62009-12-15 09:54:21 +0000188 int end_marker;
189 heap_stats.end_marker = &end_marker;
Ben Murdochbb769b22010-08-11 14:56:33 +0100190 i::Heap::RecordStats(&heap_stats, take_snapshot);
Steve Blocka7e24c12009-10-30 11:49:00 +0000191 i::V8::SetFatalError();
192 FatalErrorCallback callback = GetFatalErrorHandler();
193 {
194 LEAVE_V8;
195 callback(location, "Allocation failed - process out of memory");
196 }
197 // If the callback returns, we stop execution.
198 UNREACHABLE();
199}
200
201
202void V8::SetFatalErrorHandler(FatalErrorCallback that) {
203 exception_behavior = that;
204}
205
206
207bool Utils::ReportApiFailure(const char* location, const char* message) {
208 FatalErrorCallback callback = GetFatalErrorHandler();
209 callback(location, message);
210 i::V8::SetFatalError();
211 return false;
212}
213
214
215bool V8::IsDead() {
216 return i::V8::IsDead();
217}
218
219
220static inline bool ApiCheck(bool condition,
221 const char* location,
222 const char* message) {
223 return condition ? true : Utils::ReportApiFailure(location, message);
224}
225
226
227static bool ReportV8Dead(const char* location) {
228 FatalErrorCallback callback = GetFatalErrorHandler();
229 callback(location, "V8 is no longer usable");
230 return true;
231}
232
233
234static bool ReportEmptyHandle(const char* location) {
235 FatalErrorCallback callback = GetFatalErrorHandler();
236 callback(location, "Reading from empty handle");
237 return true;
238}
239
240
241/**
242 * IsDeadCheck checks that the vm is usable. If, for instance, the vm has been
243 * out of memory at some point this check will fail. It should be called on
244 * entry to all methods that touch anything in the heap, except destructors
245 * which you sometimes can't avoid calling after the vm has crashed. Functions
246 * that call EnsureInitialized or ON_BAILOUT don't have to also call
247 * IsDeadCheck. ON_BAILOUT has the advantage over EnsureInitialized that you
248 * can arrange to return if the VM is dead. This is needed to ensure that no VM
249 * heap allocations are attempted on a dead VM. EnsureInitialized has the
250 * advantage over ON_BAILOUT that it actually initializes the VM if this has not
251 * yet been done.
252 */
253static inline bool IsDeadCheck(const char* location) {
254 return !i::V8::IsRunning()
255 && i::V8::IsDead() ? ReportV8Dead(location) : false;
256}
257
258
259static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
260 return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
261}
262
263
264static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
265 return (obj == 0) ? ReportEmptyHandle(location) : false;
266}
267
268// --- S t a t i c s ---
269
270
271static i::StringInputBuffer write_input_buffer;
272
273
274static inline bool EnsureInitialized(const char* location) {
275 if (i::V8::IsRunning()) {
276 return true;
277 }
278 if (IsDeadCheck(location)) {
279 return false;
280 }
281 return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
282}
283
284
285ImplementationUtilities::HandleScopeData*
286 ImplementationUtilities::CurrentHandleScope() {
287 return &i::HandleScope::current_;
288}
289
290
291#ifdef DEBUG
292void ImplementationUtilities::ZapHandleRange(i::Object** begin,
293 i::Object** end) {
294 i::HandleScope::ZapRange(begin, end);
295}
296#endif
297
298
299v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
300 if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
301 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
302}
303
304
305v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
306 if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
307 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
308}
309
310
311v8::Handle<v8::Boolean> ImplementationUtilities::True() {
312 if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
313 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
314}
315
316
317v8::Handle<v8::Boolean> ImplementationUtilities::False() {
318 if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
319 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
320}
321
322
323void V8::SetFlagsFromString(const char* str, int length) {
324 i::FlagList::SetFlagsFromString(str, length);
325}
326
327
328void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
329 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
330}
331
332
333v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
334 if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
335 ENTER_V8;
336 // If we're passed an empty handle, we throw an undefined exception
337 // to deal more gracefully with out of memory situations.
338 if (value.IsEmpty()) {
339 i::Top::ScheduleThrow(i::Heap::undefined_value());
340 } else {
341 i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
342 }
343 return v8::Undefined();
344}
345
346
347RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
348
349
350RegisteredExtension::RegisteredExtension(Extension* extension)
351 : extension_(extension), state_(UNVISITED) { }
352
353
354void RegisteredExtension::Register(RegisteredExtension* that) {
355 that->next_ = RegisteredExtension::first_extension_;
356 RegisteredExtension::first_extension_ = that;
357}
358
359
360void RegisterExtension(Extension* that) {
361 RegisteredExtension* extension = new RegisteredExtension(that);
362 RegisteredExtension::Register(extension);
363}
364
365
366Extension::Extension(const char* name,
367 const char* source,
368 int dep_count,
369 const char** deps)
370 : name_(name),
371 source_(source),
372 dep_count_(dep_count),
373 deps_(deps),
374 auto_enable_(false) { }
375
376
377v8::Handle<Primitive> Undefined() {
378 LOG_API("Undefined");
379 return ImplementationUtilities::Undefined();
380}
381
382
383v8::Handle<Primitive> Null() {
384 LOG_API("Null");
385 return ImplementationUtilities::Null();
386}
387
388
389v8::Handle<Boolean> True() {
390 LOG_API("True");
391 return ImplementationUtilities::True();
392}
393
394
395v8::Handle<Boolean> False() {
396 LOG_API("False");
397 return ImplementationUtilities::False();
398}
399
400
401ResourceConstraints::ResourceConstraints()
402 : max_young_space_size_(0),
403 max_old_space_size_(0),
Russell Brenner90bac252010-11-18 13:33:46 -0800404 max_executable_size_(0),
Steve Blocka7e24c12009-10-30 11:49:00 +0000405 stack_limit_(NULL) { }
406
407
408bool SetResourceConstraints(ResourceConstraints* constraints) {
Steve Block3ce2e202009-11-05 08:53:23 +0000409 int young_space_size = constraints->max_young_space_size();
Steve Blocka7e24c12009-10-30 11:49:00 +0000410 int old_gen_size = constraints->max_old_space_size();
Russell Brenner90bac252010-11-18 13:33:46 -0800411 int max_executable_size = constraints->max_executable_size();
412 if (young_space_size != 0 || old_gen_size != 0 || max_executable_size != 0) {
413 bool result = i::Heap::ConfigureHeap(young_space_size / 2,
414 old_gen_size,
415 max_executable_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000416 if (!result) return false;
417 }
418 if (constraints->stack_limit() != NULL) {
419 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
420 i::StackGuard::SetStackLimit(limit);
421 }
422 return true;
423}
424
425
426i::Object** V8::GlobalizeReference(i::Object** obj) {
427 if (IsDeadCheck("V8::Persistent::New")) return NULL;
428 LOG_API("Persistent::New");
429 i::Handle<i::Object> result =
430 i::GlobalHandles::Create(*obj);
431 return result.location();
432}
433
434
435void V8::MakeWeak(i::Object** object, void* parameters,
436 WeakReferenceCallback callback) {
437 LOG_API("MakeWeak");
438 i::GlobalHandles::MakeWeak(object, parameters, callback);
439}
440
441
442void V8::ClearWeak(i::Object** obj) {
443 LOG_API("ClearWeak");
444 i::GlobalHandles::ClearWeakness(obj);
445}
446
447
448bool V8::IsGlobalNearDeath(i::Object** obj) {
449 LOG_API("IsGlobalNearDeath");
450 if (!i::V8::IsRunning()) return false;
451 return i::GlobalHandles::IsNearDeath(obj);
452}
453
454
455bool V8::IsGlobalWeak(i::Object** obj) {
456 LOG_API("IsGlobalWeak");
457 if (!i::V8::IsRunning()) return false;
458 return i::GlobalHandles::IsWeak(obj);
459}
460
461
462void V8::DisposeGlobal(i::Object** obj) {
463 LOG_API("DisposeGlobal");
464 if (!i::V8::IsRunning()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000465 i::GlobalHandles::Destroy(obj);
466}
467
468// --- H a n d l e s ---
469
470
John Reck59135872010-11-02 12:39:01 -0700471HandleScope::HandleScope()
472 : prev_next_(i::HandleScope::current_.next),
473 prev_limit_(i::HandleScope::current_.limit),
474 is_closed_(false) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000475 API_ENTRY_CHECK("HandleScope::HandleScope");
John Reck59135872010-11-02 12:39:01 -0700476 i::HandleScope::current_.level++;
Steve Blocka7e24c12009-10-30 11:49:00 +0000477}
478
479
480HandleScope::~HandleScope() {
481 if (!is_closed_) {
John Reck59135872010-11-02 12:39:01 -0700482 Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +0000483 }
484}
485
486
John Reck59135872010-11-02 12:39:01 -0700487void HandleScope::Leave() {
488 i::HandleScope::current_.level--;
489 ASSERT(i::HandleScope::current_.level >= 0);
490 i::HandleScope::current_.next = prev_next_;
491 if (i::HandleScope::current_.limit != prev_limit_) {
492 i::HandleScope::current_.limit = prev_limit_;
493 i::HandleScope::DeleteExtensions();
494 }
495
496#ifdef DEBUG
497 i::HandleScope::ZapRange(prev_next_, prev_limit_);
498#endif
499}
500
501
Steve Blocka7e24c12009-10-30 11:49:00 +0000502int HandleScope::NumberOfHandles() {
503 return i::HandleScope::NumberOfHandles();
504}
505
506
507i::Object** v8::HandleScope::CreateHandle(i::Object* value) {
508 return i::HandleScope::CreateHandle(value);
509}
510
511
512void Context::Enter() {
513 if (IsDeadCheck("v8::Context::Enter()")) return;
514 ENTER_V8;
515 i::Handle<i::Context> env = Utils::OpenHandle(this);
516 thread_local.EnterContext(env);
517
518 thread_local.SaveContext(i::Top::context());
519 i::Top::set_context(*env);
520}
521
522
523void Context::Exit() {
524 if (!i::V8::IsRunning()) return;
525 if (!ApiCheck(thread_local.LeaveLastContext(),
526 "v8::Context::Exit()",
527 "Cannot exit non-entered context")) {
528 return;
529 }
530
531 // Content of 'last_context' could be NULL.
532 i::Context* last_context = thread_local.RestoreContext();
533 i::Top::set_context(last_context);
534}
535
536
Steve Blockd0582a62009-12-15 09:54:21 +0000537void Context::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000538 if (IsDeadCheck("v8::Context::SetData()")) return;
539 ENTER_V8;
540 {
541 HandleScope scope;
542 i::Handle<i::Context> env = Utils::OpenHandle(this);
543 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
544 ASSERT(env->IsGlobalContext());
545 if (env->IsGlobalContext()) {
546 env->set_data(*raw_data);
547 }
548 }
549}
550
551
552v8::Local<v8::Value> Context::GetData() {
553 if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
554 ENTER_V8;
555 i::Object* raw_result = NULL;
556 {
557 HandleScope scope;
558 i::Handle<i::Context> env = Utils::OpenHandle(this);
559 ASSERT(env->IsGlobalContext());
560 if (env->IsGlobalContext()) {
561 raw_result = env->data();
562 } else {
563 return Local<Value>();
564 }
565 }
566 i::Handle<i::Object> result(raw_result);
567 return Utils::ToLocal(result);
568}
569
570
571i::Object** v8::HandleScope::RawClose(i::Object** value) {
572 if (!ApiCheck(!is_closed_,
573 "v8::HandleScope::Close()",
574 "Local scope has already been closed")) {
575 return 0;
576 }
577 LOG_API("CloseHandleScope");
578
579 // Read the result before popping the handle block.
Steve Block6ded16b2010-05-10 14:33:55 +0100580 i::Object* result = NULL;
581 if (value != NULL) {
582 result = *value;
583 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000584 is_closed_ = true;
John Reck59135872010-11-02 12:39:01 -0700585 Leave();
Steve Blocka7e24c12009-10-30 11:49:00 +0000586
Steve Block6ded16b2010-05-10 14:33:55 +0100587 if (value == NULL) {
588 return NULL;
589 }
590
Steve Blocka7e24c12009-10-30 11:49:00 +0000591 // Allocate a new handle on the previous handle block.
592 i::Handle<i::Object> handle(result);
593 return handle.location();
594}
595
596
597// --- N e a n d e r ---
598
599
600// A constructor cannot easily return an error value, therefore it is necessary
601// to check for a dead VM with ON_BAILOUT before constructing any Neander
602// objects. To remind you about this there is no HandleScope in the
603// NeanderObject constructor. When you add one to the site calling the
604// constructor you should check that you ensured the VM was not dead first.
605NeanderObject::NeanderObject(int size) {
606 EnsureInitialized("v8::Nowhere");
607 ENTER_V8;
608 value_ = i::Factory::NewNeanderObject();
609 i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
610 value_->set_elements(*elements);
611}
612
613
614int NeanderObject::size() {
615 return i::FixedArray::cast(value_->elements())->length();
616}
617
618
619NeanderArray::NeanderArray() : obj_(2) {
620 obj_.set(0, i::Smi::FromInt(0));
621}
622
623
624int NeanderArray::length() {
625 return i::Smi::cast(obj_.get(0))->value();
626}
627
628
629i::Object* NeanderArray::get(int offset) {
630 ASSERT(0 <= offset);
631 ASSERT(offset < length());
632 return obj_.get(offset + 1);
633}
634
635
636// This method cannot easily return an error value, therefore it is necessary
637// to check for a dead VM with ON_BAILOUT before calling it. To remind you
638// about this there is no HandleScope in this method. When you add one to the
639// site calling this method you should check that you ensured the VM was not
640// dead first.
641void NeanderArray::add(i::Handle<i::Object> value) {
642 int length = this->length();
643 int size = obj_.size();
644 if (length == size - 1) {
645 i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
646 for (int i = 0; i < length; i++)
647 new_elms->set(i + 1, get(i));
648 obj_.value()->set_elements(*new_elms);
649 }
650 obj_.set(length + 1, *value);
651 obj_.set(0, i::Smi::FromInt(length + 1));
652}
653
654
655void NeanderArray::set(int index, i::Object* value) {
656 if (index < 0 || index >= this->length()) return;
657 obj_.set(index + 1, value);
658}
659
660
661// --- T e m p l a t e ---
662
663
664static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
665 that->set_tag(i::Smi::FromInt(type));
666}
667
668
669void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
670 v8::PropertyAttribute attribute) {
671 if (IsDeadCheck("v8::Template::SetProperty()")) return;
672 ENTER_V8;
673 HandleScope scope;
674 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
675 if (list->IsUndefined()) {
676 list = NeanderArray().value();
677 Utils::OpenHandle(this)->set_property_list(*list);
678 }
679 NeanderArray array(list);
680 array.add(Utils::OpenHandle(*name));
681 array.add(Utils::OpenHandle(*value));
682 array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
683}
684
685
686// --- F u n c t i o n T e m p l a t e ---
687static void InitializeFunctionTemplate(
688 i::Handle<i::FunctionTemplateInfo> info) {
689 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
690 info->set_flag(0);
691}
692
693
694Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
695 if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
696 return Local<ObjectTemplate>();
697 }
698 ENTER_V8;
699 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
700 if (result->IsUndefined()) {
701 result = Utils::OpenHandle(*ObjectTemplate::New());
702 Utils::OpenHandle(this)->set_prototype_template(*result);
703 }
704 return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
705}
706
707
708void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
709 if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
710 ENTER_V8;
711 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
712}
713
714
715// To distinguish the function templates, so that we can find them in the
716// function cache of the global context.
717static int next_serial_number = 0;
718
719
720Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
721 v8::Handle<Value> data, v8::Handle<Signature> signature) {
722 EnsureInitialized("v8::FunctionTemplate::New()");
723 LOG_API("FunctionTemplate::New");
724 ENTER_V8;
725 i::Handle<i::Struct> struct_obj =
726 i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
727 i::Handle<i::FunctionTemplateInfo> obj =
728 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
729 InitializeFunctionTemplate(obj);
730 obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
731 if (callback != 0) {
732 if (data.IsEmpty()) data = v8::Undefined();
733 Utils::ToLocal(obj)->SetCallHandler(callback, data);
734 }
735 obj->set_undetectable(false);
736 obj->set_needs_access_check(false);
737
738 if (!signature.IsEmpty())
739 obj->set_signature(*Utils::OpenHandle(*signature));
740 return Utils::ToLocal(obj);
741}
742
743
744Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
745 int argc, Handle<FunctionTemplate> argv[]) {
746 EnsureInitialized("v8::Signature::New()");
747 LOG_API("Signature::New");
748 ENTER_V8;
749 i::Handle<i::Struct> struct_obj =
750 i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
751 i::Handle<i::SignatureInfo> obj =
752 i::Handle<i::SignatureInfo>::cast(struct_obj);
753 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
754 if (argc > 0) {
755 i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
756 for (int i = 0; i < argc; i++) {
757 if (!argv[i].IsEmpty())
758 args->set(i, *Utils::OpenHandle(*argv[i]));
759 }
760 obj->set_args(*args);
761 }
762 return Utils::ToLocal(obj);
763}
764
765
766Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
767 Handle<FunctionTemplate> types[1] = { type };
768 return TypeSwitch::New(1, types);
769}
770
771
772Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
773 EnsureInitialized("v8::TypeSwitch::New()");
774 LOG_API("TypeSwitch::New");
775 ENTER_V8;
776 i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
777 for (int i = 0; i < argc; i++)
778 vector->set(i, *Utils::OpenHandle(*types[i]));
779 i::Handle<i::Struct> struct_obj =
780 i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
781 i::Handle<i::TypeSwitchInfo> obj =
782 i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
783 obj->set_types(*vector);
784 return Utils::ToLocal(obj);
785}
786
787
788int TypeSwitch::match(v8::Handle<Value> value) {
789 LOG_API("TypeSwitch::match");
790 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
791 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
792 i::FixedArray* types = i::FixedArray::cast(info->types());
793 for (int i = 0; i < types->length(); i++) {
794 if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
795 return i + 1;
796 }
797 return 0;
798}
799
800
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100801#define SET_FIELD_WRAPPED(obj, setter, cdata) do { \
802 i::Handle<i::Object> proxy = FromCData(cdata); \
803 (obj)->setter(*proxy); \
804 } while (false)
805
806
Steve Blocka7e24c12009-10-30 11:49:00 +0000807void FunctionTemplate::SetCallHandler(InvocationCallback callback,
808 v8::Handle<Value> data) {
809 if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
810 ENTER_V8;
811 HandleScope scope;
812 i::Handle<i::Struct> struct_obj =
813 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
814 i::Handle<i::CallHandlerInfo> obj =
815 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100816 SET_FIELD_WRAPPED(obj, set_callback, callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000817 if (data.IsEmpty()) data = v8::Undefined();
818 obj->set_data(*Utils::OpenHandle(*data));
819 Utils::OpenHandle(this)->set_call_code(*obj);
820}
821
822
Leon Clarkef7060e22010-06-03 12:02:55 +0100823static i::Handle<i::AccessorInfo> MakeAccessorInfo(
824 v8::Handle<String> name,
825 AccessorGetter getter,
826 AccessorSetter setter,
827 v8::Handle<Value> data,
828 v8::AccessControl settings,
829 v8::PropertyAttribute attributes) {
830 i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
831 ASSERT(getter != NULL);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100832 SET_FIELD_WRAPPED(obj, set_getter, getter);
833 SET_FIELD_WRAPPED(obj, set_setter, setter);
Leon Clarkef7060e22010-06-03 12:02:55 +0100834 if (data.IsEmpty()) data = v8::Undefined();
835 obj->set_data(*Utils::OpenHandle(*data));
836 obj->set_name(*Utils::OpenHandle(*name));
837 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
838 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
839 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
840 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
841 return obj;
842}
843
844
Steve Blocka7e24c12009-10-30 11:49:00 +0000845void FunctionTemplate::AddInstancePropertyAccessor(
846 v8::Handle<String> name,
847 AccessorGetter getter,
848 AccessorSetter setter,
849 v8::Handle<Value> data,
850 v8::AccessControl settings,
851 v8::PropertyAttribute attributes) {
852 if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
853 return;
854 }
855 ENTER_V8;
856 HandleScope scope;
Steve Blocka7e24c12009-10-30 11:49:00 +0000857
Leon Clarkef7060e22010-06-03 12:02:55 +0100858 i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name,
859 getter, setter, data,
860 settings, attributes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000861 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
862 if (list->IsUndefined()) {
863 list = NeanderArray().value();
864 Utils::OpenHandle(this)->set_property_accessors(*list);
865 }
866 NeanderArray array(list);
867 array.add(obj);
868}
869
870
871Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
872 if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
873 || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
874 return Local<ObjectTemplate>();
875 ENTER_V8;
876 if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
877 Local<ObjectTemplate> templ =
878 ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
879 Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
880 }
881 i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
882 Utils::OpenHandle(this)->instance_template()));
883 return Utils::ToLocal(result);
884}
885
886
887void FunctionTemplate::SetClassName(Handle<String> name) {
888 if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
889 ENTER_V8;
890 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
891}
892
893
894void FunctionTemplate::SetHiddenPrototype(bool value) {
895 if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
896 ENTER_V8;
897 Utils::OpenHandle(this)->set_hidden_prototype(value);
898}
899
900
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100901void FunctionTemplate::SetNamedInstancePropertyHandler(
Steve Blocka7e24c12009-10-30 11:49:00 +0000902 NamedPropertyGetter getter,
903 NamedPropertySetter setter,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +0100904 NamedPropertyQuery query,
Steve Blocka7e24c12009-10-30 11:49:00 +0000905 NamedPropertyDeleter remover,
906 NamedPropertyEnumerator enumerator,
907 Handle<Value> data) {
908 if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
909 return;
910 }
911 ENTER_V8;
912 HandleScope scope;
913 i::Handle<i::Struct> struct_obj =
914 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
915 i::Handle<i::InterceptorInfo> obj =
916 i::Handle<i::InterceptorInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100917
918 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
919 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
920 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
921 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
922 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
923
Steve Blocka7e24c12009-10-30 11:49:00 +0000924 if (data.IsEmpty()) data = v8::Undefined();
925 obj->set_data(*Utils::OpenHandle(*data));
926 Utils::OpenHandle(this)->set_named_property_handler(*obj);
927}
928
929
930void FunctionTemplate::SetIndexedInstancePropertyHandler(
931 IndexedPropertyGetter getter,
932 IndexedPropertySetter setter,
933 IndexedPropertyQuery query,
934 IndexedPropertyDeleter remover,
935 IndexedPropertyEnumerator enumerator,
936 Handle<Value> data) {
937 if (IsDeadCheck(
938 "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
939 return;
940 }
941 ENTER_V8;
942 HandleScope scope;
943 i::Handle<i::Struct> struct_obj =
944 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
945 i::Handle<i::InterceptorInfo> obj =
946 i::Handle<i::InterceptorInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100947
948 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
949 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
950 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
951 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
952 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
953
Steve Blocka7e24c12009-10-30 11:49:00 +0000954 if (data.IsEmpty()) data = v8::Undefined();
955 obj->set_data(*Utils::OpenHandle(*data));
956 Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
957}
958
959
960void FunctionTemplate::SetInstanceCallAsFunctionHandler(
961 InvocationCallback callback,
962 Handle<Value> data) {
963 if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
964 return;
965 }
966 ENTER_V8;
967 HandleScope scope;
968 i::Handle<i::Struct> struct_obj =
969 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
970 i::Handle<i::CallHandlerInfo> obj =
971 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100972 SET_FIELD_WRAPPED(obj, set_callback, callback);
Steve Blocka7e24c12009-10-30 11:49:00 +0000973 if (data.IsEmpty()) data = v8::Undefined();
974 obj->set_data(*Utils::OpenHandle(*data));
975 Utils::OpenHandle(this)->set_instance_call_handler(*obj);
976}
977
978
979// --- O b j e c t T e m p l a t e ---
980
981
982Local<ObjectTemplate> ObjectTemplate::New() {
983 return New(Local<FunctionTemplate>());
984}
985
986
987Local<ObjectTemplate> ObjectTemplate::New(
988 v8::Handle<FunctionTemplate> constructor) {
989 if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
990 EnsureInitialized("v8::ObjectTemplate::New()");
991 LOG_API("ObjectTemplate::New");
992 ENTER_V8;
993 i::Handle<i::Struct> struct_obj =
994 i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
995 i::Handle<i::ObjectTemplateInfo> obj =
996 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
997 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
998 if (!constructor.IsEmpty())
999 obj->set_constructor(*Utils::OpenHandle(*constructor));
1000 obj->set_internal_field_count(i::Smi::FromInt(0));
1001 return Utils::ToLocal(obj);
1002}
1003
1004
1005// Ensure that the object template has a constructor. If no
1006// constructor is available we create one.
1007static void EnsureConstructor(ObjectTemplate* object_template) {
1008 if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
1009 Local<FunctionTemplate> templ = FunctionTemplate::New();
1010 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
1011 constructor->set_instance_template(*Utils::OpenHandle(object_template));
1012 Utils::OpenHandle(object_template)->set_constructor(*constructor);
1013 }
1014}
1015
1016
1017void ObjectTemplate::SetAccessor(v8::Handle<String> name,
1018 AccessorGetter getter,
1019 AccessorSetter setter,
1020 v8::Handle<Value> data,
1021 AccessControl settings,
1022 PropertyAttribute attribute) {
1023 if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
1024 ENTER_V8;
1025 HandleScope scope;
1026 EnsureConstructor(this);
1027 i::FunctionTemplateInfo* constructor =
1028 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1029 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1030 Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
1031 getter,
1032 setter,
1033 data,
1034 settings,
1035 attribute);
1036}
1037
1038
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001039void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
1040 NamedPropertySetter setter,
1041 NamedPropertyQuery query,
1042 NamedPropertyDeleter remover,
1043 NamedPropertyEnumerator enumerator,
1044 Handle<Value> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001045 if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
1046 ENTER_V8;
1047 HandleScope scope;
1048 EnsureConstructor(this);
1049 i::FunctionTemplateInfo* constructor =
1050 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1051 i::Handle<i::FunctionTemplateInfo> cons(constructor);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001052 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
1053 setter,
1054 query,
1055 remover,
1056 enumerator,
1057 data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001058}
1059
1060
1061void ObjectTemplate::MarkAsUndetectable() {
1062 if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
1063 ENTER_V8;
1064 HandleScope scope;
1065 EnsureConstructor(this);
1066 i::FunctionTemplateInfo* constructor =
1067 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1068 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1069 cons->set_undetectable(true);
1070}
1071
1072
1073void ObjectTemplate::SetAccessCheckCallbacks(
1074 NamedSecurityCallback named_callback,
1075 IndexedSecurityCallback indexed_callback,
1076 Handle<Value> data,
1077 bool turned_on_by_default) {
1078 if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
1079 ENTER_V8;
1080 HandleScope scope;
1081 EnsureConstructor(this);
1082
1083 i::Handle<i::Struct> struct_info =
1084 i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1085 i::Handle<i::AccessCheckInfo> info =
1086 i::Handle<i::AccessCheckInfo>::cast(struct_info);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001087
1088 SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
1089 SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
1090
Steve Blocka7e24c12009-10-30 11:49:00 +00001091 if (data.IsEmpty()) data = v8::Undefined();
1092 info->set_data(*Utils::OpenHandle(*data));
1093
1094 i::FunctionTemplateInfo* constructor =
1095 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1096 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1097 cons->set_access_check_info(*info);
1098 cons->set_needs_access_check(turned_on_by_default);
1099}
1100
1101
1102void ObjectTemplate::SetIndexedPropertyHandler(
1103 IndexedPropertyGetter getter,
1104 IndexedPropertySetter setter,
1105 IndexedPropertyQuery query,
1106 IndexedPropertyDeleter remover,
1107 IndexedPropertyEnumerator enumerator,
1108 Handle<Value> data) {
1109 if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
1110 ENTER_V8;
1111 HandleScope scope;
1112 EnsureConstructor(this);
1113 i::FunctionTemplateInfo* constructor =
1114 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1115 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1116 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
1117 setter,
1118 query,
1119 remover,
1120 enumerator,
1121 data);
1122}
1123
1124
1125void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1126 Handle<Value> data) {
1127 if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
1128 ENTER_V8;
1129 HandleScope scope;
1130 EnsureConstructor(this);
1131 i::FunctionTemplateInfo* constructor =
1132 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1133 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1134 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1135}
1136
1137
1138int ObjectTemplate::InternalFieldCount() {
1139 if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
1140 return 0;
1141 }
1142 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1143}
1144
1145
1146void ObjectTemplate::SetInternalFieldCount(int value) {
1147 if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
1148 if (!ApiCheck(i::Smi::IsValid(value),
1149 "v8::ObjectTemplate::SetInternalFieldCount()",
1150 "Invalid internal field count")) {
1151 return;
1152 }
1153 ENTER_V8;
1154 if (value > 0) {
1155 // The internal field count is set by the constructor function's
1156 // construct code, so we ensure that there is a constructor
1157 // function to do the setting.
1158 EnsureConstructor(this);
1159 }
1160 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1161}
1162
1163
1164// --- S c r i p t D a t a ---
1165
1166
1167ScriptData* ScriptData::PreCompile(const char* input, int length) {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001168 i::Utf8ToUC16CharacterStream stream(
1169 reinterpret_cast<const unsigned char*>(input), length);
1170 return i::ParserApi::PreParse(&stream, NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00001171}
1172
1173
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001174ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
1175 i::Handle<i::String> str = Utils::OpenHandle(*source);
Ben Murdochb0fe1622011-05-05 13:52:32 +01001176 if (str->IsExternalTwoByteString()) {
1177 i::ExternalTwoByteStringUC16CharacterStream stream(
1178 i::Handle<i::ExternalTwoByteString>::cast(str), 0, str->length());
1179 return i::ParserApi::PreParse(&stream, NULL);
1180 } else {
1181 i::GenericStringUC16CharacterStream stream(str, 0, str->length());
1182 return i::ParserApi::PreParse(&stream, NULL);
1183 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001184}
1185
1186
Leon Clarkef7060e22010-06-03 12:02:55 +01001187ScriptData* ScriptData::New(const char* data, int length) {
1188 // Return an empty ScriptData if the length is obviously invalid.
1189 if (length % sizeof(unsigned) != 0) {
Iain Merrick9ac36c92010-09-13 15:29:50 +01001190 return new i::ScriptDataImpl();
Leon Clarkef7060e22010-06-03 12:02:55 +01001191 }
1192
1193 // Copy the data to ensure it is properly aligned.
1194 int deserialized_data_length = length / sizeof(unsigned);
Iain Merrick9ac36c92010-09-13 15:29:50 +01001195 // If aligned, don't create a copy of the data.
1196 if (reinterpret_cast<intptr_t>(data) % sizeof(unsigned) == 0) {
1197 return new i::ScriptDataImpl(data, length);
1198 }
1199 // Copy the data to align it.
Leon Clarkef7060e22010-06-03 12:02:55 +01001200 unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
Iain Merrick9ac36c92010-09-13 15:29:50 +01001201 i::MemCopy(deserialized_data, data, length);
Leon Clarkef7060e22010-06-03 12:02:55 +01001202
1203 return new i::ScriptDataImpl(
1204 i::Vector<unsigned>(deserialized_data, deserialized_data_length));
Steve Blocka7e24c12009-10-30 11:49:00 +00001205}
1206
1207
1208// --- S c r i p t ---
1209
1210
1211Local<Script> Script::New(v8::Handle<String> source,
1212 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001213 v8::ScriptData* pre_data,
1214 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001215 ON_BAILOUT("v8::Script::New()", return Local<Script>());
1216 LOG_API("Script::New");
1217 ENTER_V8;
1218 i::Handle<i::String> str = Utils::OpenHandle(*source);
1219 i::Handle<i::Object> name_obj;
1220 int line_offset = 0;
1221 int column_offset = 0;
1222 if (origin != NULL) {
1223 if (!origin->ResourceName().IsEmpty()) {
1224 name_obj = Utils::OpenHandle(*origin->ResourceName());
1225 }
1226 if (!origin->ResourceLineOffset().IsEmpty()) {
1227 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1228 }
1229 if (!origin->ResourceColumnOffset().IsEmpty()) {
1230 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1231 }
1232 }
1233 EXCEPTION_PREAMBLE();
Andrei Popescu402d9372010-02-26 13:31:12 +00001234 i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001235 // We assert that the pre-data is sane, even though we can actually
1236 // handle it if it turns out not to be in release mode.
Andrei Popescu402d9372010-02-26 13:31:12 +00001237 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
Steve Blocka7e24c12009-10-30 11:49:00 +00001238 // If the pre-data isn't sane we simply ignore it
Andrei Popescu402d9372010-02-26 13:31:12 +00001239 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
1240 pre_data_impl = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001241 }
Steve Block6ded16b2010-05-10 14:33:55 +01001242 i::Handle<i::SharedFunctionInfo> result =
Andrei Popescu31002712010-02-23 13:46:05 +00001243 i::Compiler::Compile(str,
1244 name_obj,
1245 line_offset,
1246 column_offset,
1247 NULL,
Andrei Popescu402d9372010-02-26 13:31:12 +00001248 pre_data_impl,
1249 Utils::OpenHandle(*script_data),
Andrei Popescu31002712010-02-23 13:46:05 +00001250 i::NOT_NATIVES_CODE);
Steve Block6ded16b2010-05-10 14:33:55 +01001251 has_pending_exception = result.is_null();
Steve Blocka7e24c12009-10-30 11:49:00 +00001252 EXCEPTION_BAILOUT_CHECK(Local<Script>());
Steve Block6ded16b2010-05-10 14:33:55 +01001253 return Local<Script>(ToApi<Script>(result));
Steve Blocka7e24c12009-10-30 11:49:00 +00001254}
1255
1256
1257Local<Script> Script::New(v8::Handle<String> source,
1258 v8::Handle<Value> file_name) {
1259 ScriptOrigin origin(file_name);
1260 return New(source, &origin);
1261}
1262
1263
1264Local<Script> Script::Compile(v8::Handle<String> source,
1265 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001266 v8::ScriptData* pre_data,
1267 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001268 ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1269 LOG_API("Script::Compile");
1270 ENTER_V8;
Andrei Popescu402d9372010-02-26 13:31:12 +00001271 Local<Script> generic = New(source, origin, pre_data, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001272 if (generic.IsEmpty())
1273 return generic;
Steve Block6ded16b2010-05-10 14:33:55 +01001274 i::Handle<i::Object> obj = Utils::OpenHandle(*generic);
1275 i::Handle<i::SharedFunctionInfo> function =
1276 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001277 i::Handle<i::JSFunction> result =
Steve Block6ded16b2010-05-10 14:33:55 +01001278 i::Factory::NewFunctionFromSharedFunctionInfo(function,
1279 i::Top::global_context());
Steve Blocka7e24c12009-10-30 11:49:00 +00001280 return Local<Script>(ToApi<Script>(result));
1281}
1282
1283
1284Local<Script> Script::Compile(v8::Handle<String> source,
Andrei Popescu402d9372010-02-26 13:31:12 +00001285 v8::Handle<Value> file_name,
1286 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001287 ScriptOrigin origin(file_name);
Andrei Popescu402d9372010-02-26 13:31:12 +00001288 return Compile(source, &origin, 0, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001289}
1290
1291
1292Local<Value> Script::Run() {
1293 ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1294 LOG_API("Script::Run");
1295 ENTER_V8;
1296 i::Object* raw_result = NULL;
1297 {
1298 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001299 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1300 i::Handle<i::JSFunction> fun;
1301 if (obj->IsSharedFunctionInfo()) {
1302 i::Handle<i::SharedFunctionInfo>
1303 function_info(i::SharedFunctionInfo::cast(*obj));
1304 fun = i::Factory::NewFunctionFromSharedFunctionInfo(
1305 function_info, i::Top::global_context());
1306 } else {
1307 fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj));
Steve Blocka7e24c12009-10-30 11:49:00 +00001308 }
1309 EXCEPTION_PREAMBLE();
1310 i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
1311 i::Handle<i::Object> result =
1312 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
1313 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1314 raw_result = *result;
1315 }
1316 i::Handle<i::Object> result(raw_result);
1317 return Utils::ToLocal(result);
1318}
1319
1320
Steve Block6ded16b2010-05-10 14:33:55 +01001321static i::Handle<i::SharedFunctionInfo> OpenScript(Script* script) {
1322 i::Handle<i::Object> obj = Utils::OpenHandle(script);
1323 i::Handle<i::SharedFunctionInfo> result;
1324 if (obj->IsSharedFunctionInfo()) {
1325 result =
1326 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
1327 } else {
1328 result =
1329 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared());
1330 }
1331 return result;
1332}
1333
1334
Steve Blocka7e24c12009-10-30 11:49:00 +00001335Local<Value> Script::Id() {
1336 ON_BAILOUT("v8::Script::Id()", return Local<Value>());
1337 LOG_API("Script::Id");
1338 i::Object* raw_id = NULL;
1339 {
1340 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001341 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1342 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001343 i::Handle<i::Object> id(script->id());
1344 raw_id = *id;
1345 }
1346 i::Handle<i::Object> id(raw_id);
1347 return Utils::ToLocal(id);
1348}
1349
1350
Steve Blockd0582a62009-12-15 09:54:21 +00001351void Script::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001352 ON_BAILOUT("v8::Script::SetData()", return);
1353 LOG_API("Script::SetData");
1354 {
1355 HandleScope scope;
Steve Block6ded16b2010-05-10 14:33:55 +01001356 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
Steve Blocka7e24c12009-10-30 11:49:00 +00001357 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
Steve Block6ded16b2010-05-10 14:33:55 +01001358 i::Handle<i::Script> script(i::Script::cast(function_info->script()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001359 script->set_data(*raw_data);
1360 }
1361}
1362
1363
1364// --- E x c e p t i o n s ---
1365
1366
1367v8::TryCatch::TryCatch()
Steve Blockd0582a62009-12-15 09:54:21 +00001368 : next_(i::Top::try_catch_handler_address()),
Steve Blocka7e24c12009-10-30 11:49:00 +00001369 exception_(i::Heap::the_hole_value()),
1370 message_(i::Smi::FromInt(0)),
1371 is_verbose_(false),
1372 can_continue_(true),
1373 capture_message_(true),
Steve Blockd0582a62009-12-15 09:54:21 +00001374 rethrow_(false) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001375 i::Top::RegisterTryCatchHandler(this);
1376}
1377
1378
1379v8::TryCatch::~TryCatch() {
Steve Blockd0582a62009-12-15 09:54:21 +00001380 if (rethrow_) {
1381 v8::HandleScope scope;
1382 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
1383 i::Top::UnregisterTryCatchHandler(this);
1384 v8::ThrowException(exc);
1385 } else {
1386 i::Top::UnregisterTryCatchHandler(this);
1387 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001388}
1389
1390
1391bool v8::TryCatch::HasCaught() const {
1392 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1393}
1394
1395
1396bool v8::TryCatch::CanContinue() const {
1397 return can_continue_;
1398}
1399
1400
Steve Blockd0582a62009-12-15 09:54:21 +00001401v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1402 if (!HasCaught()) return v8::Local<v8::Value>();
1403 rethrow_ = true;
1404 return v8::Undefined();
1405}
1406
1407
Steve Blocka7e24c12009-10-30 11:49:00 +00001408v8::Local<Value> v8::TryCatch::Exception() const {
1409 if (HasCaught()) {
1410 // Check for out of memory exception.
1411 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1412 return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1413 } else {
1414 return v8::Local<Value>();
1415 }
1416}
1417
1418
1419v8::Local<Value> v8::TryCatch::StackTrace() const {
1420 if (HasCaught()) {
1421 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1422 if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1423 v8::HandleScope scope;
1424 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
1425 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
1426 if (!obj->HasProperty(*name))
1427 return v8::Local<Value>();
1428 return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
1429 } else {
1430 return v8::Local<Value>();
1431 }
1432}
1433
1434
1435v8::Local<v8::Message> v8::TryCatch::Message() const {
1436 if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1437 i::Object* message = reinterpret_cast<i::Object*>(message_);
1438 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1439 } else {
1440 return v8::Local<v8::Message>();
1441 }
1442}
1443
1444
1445void v8::TryCatch::Reset() {
1446 exception_ = i::Heap::the_hole_value();
1447 message_ = i::Smi::FromInt(0);
1448}
1449
1450
1451void v8::TryCatch::SetVerbose(bool value) {
1452 is_verbose_ = value;
1453}
1454
1455
1456void v8::TryCatch::SetCaptureMessage(bool value) {
1457 capture_message_ = value;
1458}
1459
1460
1461// --- M e s s a g e ---
1462
1463
1464Local<String> Message::Get() const {
1465 ON_BAILOUT("v8::Message::Get()", return Local<String>());
1466 ENTER_V8;
1467 HandleScope scope;
1468 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1469 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1470 Local<String> result = Utils::ToLocal(raw_result);
1471 return scope.Close(result);
1472}
1473
1474
1475v8::Handle<Value> Message::GetScriptResourceName() const {
1476 if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1477 return Local<String>();
1478 }
1479 ENTER_V8;
1480 HandleScope scope;
1481 i::Handle<i::JSObject> obj =
1482 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1483 // Return this.script.name.
1484 i::Handle<i::JSValue> script =
1485 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1486 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
1487 return scope.Close(Utils::ToLocal(resource_name));
1488}
1489
1490
1491v8::Handle<Value> Message::GetScriptData() const {
1492 if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
1493 return Local<Value>();
1494 }
1495 ENTER_V8;
1496 HandleScope scope;
1497 i::Handle<i::JSObject> obj =
1498 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1499 // Return this.script.data.
1500 i::Handle<i::JSValue> script =
1501 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1502 i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1503 return scope.Close(Utils::ToLocal(data));
1504}
1505
1506
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001507v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
1508 if (IsDeadCheck("v8::Message::GetStackTrace()")) {
1509 return Local<v8::StackTrace>();
1510 }
1511 ENTER_V8;
1512 HandleScope scope;
1513 i::Handle<i::JSObject> obj =
1514 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1515 i::Handle<i::Object> stackFramesObj = GetProperty(obj, "stackFrames");
1516 if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
1517 i::Handle<i::JSArray> stackTrace =
1518 i::Handle<i::JSArray>::cast(stackFramesObj);
1519 return scope.Close(Utils::StackTraceToLocal(stackTrace));
1520}
1521
1522
Steve Blocka7e24c12009-10-30 11:49:00 +00001523static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1524 i::Handle<i::Object> recv,
1525 int argc,
1526 i::Object** argv[],
1527 bool* has_pending_exception) {
1528 i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
John Reck59135872010-11-02 12:39:01 -07001529 i::Object* object_fun =
1530 i::Top::builtins()->GetPropertyNoExceptionThrown(*fmt_str);
Steve Blocka7e24c12009-10-30 11:49:00 +00001531 i::Handle<i::JSFunction> fun =
1532 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1533 i::Handle<i::Object> value =
1534 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1535 return value;
1536}
1537
1538
1539static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1540 i::Handle<i::Object> data,
1541 bool* has_pending_exception) {
1542 i::Object** argv[1] = { data.location() };
1543 return CallV8HeapFunction(name,
1544 i::Top::builtins(),
1545 1,
1546 argv,
1547 has_pending_exception);
1548}
1549
1550
1551int Message::GetLineNumber() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001552 ON_BAILOUT("v8::Message::GetLineNumber()", return kNoLineNumberInfo);
Steve Blocka7e24c12009-10-30 11:49:00 +00001553 ENTER_V8;
1554 HandleScope scope;
1555 EXCEPTION_PREAMBLE();
1556 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1557 Utils::OpenHandle(this),
1558 &has_pending_exception);
1559 EXCEPTION_BAILOUT_CHECK(0);
1560 return static_cast<int>(result->Number());
1561}
1562
1563
1564int Message::GetStartPosition() const {
1565 if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1566 ENTER_V8;
1567 HandleScope scope;
1568
1569 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1570 return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1571}
1572
1573
1574int Message::GetEndPosition() const {
1575 if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1576 ENTER_V8;
1577 HandleScope scope;
1578 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1579 return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1580}
1581
1582
1583int Message::GetStartColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001584 if (IsDeadCheck("v8::Message::GetStartColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001585 ENTER_V8;
1586 HandleScope scope;
1587 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1588 EXCEPTION_PREAMBLE();
1589 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1590 "GetPositionInLine",
1591 data_obj,
1592 &has_pending_exception);
1593 EXCEPTION_BAILOUT_CHECK(0);
1594 return static_cast<int>(start_col_obj->Number());
1595}
1596
1597
1598int Message::GetEndColumn() const {
Kristian Monsen25f61362010-05-21 11:50:48 +01001599 if (IsDeadCheck("v8::Message::GetEndColumn()")) return kNoColumnInfo;
Steve Blocka7e24c12009-10-30 11:49:00 +00001600 ENTER_V8;
1601 HandleScope scope;
1602 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1603 EXCEPTION_PREAMBLE();
1604 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1605 "GetPositionInLine",
1606 data_obj,
1607 &has_pending_exception);
1608 EXCEPTION_BAILOUT_CHECK(0);
1609 int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1610 int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1611 return static_cast<int>(start_col_obj->Number()) + (end - start);
1612}
1613
1614
1615Local<String> Message::GetSourceLine() const {
1616 ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
1617 ENTER_V8;
1618 HandleScope scope;
1619 EXCEPTION_PREAMBLE();
1620 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1621 Utils::OpenHandle(this),
1622 &has_pending_exception);
1623 EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1624 if (result->IsString()) {
1625 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1626 } else {
1627 return Local<String>();
1628 }
1629}
1630
1631
1632void Message::PrintCurrentStackTrace(FILE* out) {
1633 if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1634 ENTER_V8;
1635 i::Top::PrintCurrentStackTrace(out);
1636}
1637
1638
Kristian Monsen25f61362010-05-21 11:50:48 +01001639// --- S t a c k T r a c e ---
1640
1641Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
1642 if (IsDeadCheck("v8::StackTrace::GetFrame()")) return Local<StackFrame>();
1643 ENTER_V8;
1644 HandleScope scope;
1645 i::Handle<i::JSArray> self = Utils::OpenHandle(this);
John Reck59135872010-11-02 12:39:01 -07001646 i::Object* raw_object = self->GetElementNoExceptionThrown(index);
1647 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_object));
Kristian Monsen25f61362010-05-21 11:50:48 +01001648 return scope.Close(Utils::StackFrameToLocal(obj));
1649}
1650
1651
1652int StackTrace::GetFrameCount() const {
1653 if (IsDeadCheck("v8::StackTrace::GetFrameCount()")) return -1;
1654 ENTER_V8;
1655 return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
1656}
1657
1658
1659Local<Array> StackTrace::AsArray() {
1660 if (IsDeadCheck("v8::StackTrace::AsArray()")) Local<Array>();
1661 ENTER_V8;
1662 return Utils::ToLocal(Utils::OpenHandle(this));
1663}
1664
1665
1666Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
1667 StackTraceOptions options) {
1668 if (IsDeadCheck("v8::StackTrace::CurrentStackTrace()")) Local<StackTrace>();
1669 ENTER_V8;
Ben Murdoch3bec4d22010-07-22 14:51:16 +01001670 i::Handle<i::JSArray> stackTrace =
1671 i::Top::CaptureCurrentStackTrace(frame_limit, options);
1672 return Utils::StackTraceToLocal(stackTrace);
Kristian Monsen25f61362010-05-21 11:50:48 +01001673}
1674
1675
1676// --- S t a c k F r a m e ---
1677
1678int StackFrame::GetLineNumber() const {
1679 if (IsDeadCheck("v8::StackFrame::GetLineNumber()")) {
1680 return Message::kNoLineNumberInfo;
1681 }
1682 ENTER_V8;
1683 i::HandleScope scope;
1684 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1685 i::Handle<i::Object> line = GetProperty(self, "lineNumber");
1686 if (!line->IsSmi()) {
1687 return Message::kNoLineNumberInfo;
1688 }
1689 return i::Smi::cast(*line)->value();
1690}
1691
1692
1693int StackFrame::GetColumn() const {
1694 if (IsDeadCheck("v8::StackFrame::GetColumn()")) {
1695 return Message::kNoColumnInfo;
1696 }
1697 ENTER_V8;
1698 i::HandleScope scope;
1699 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1700 i::Handle<i::Object> column = GetProperty(self, "column");
1701 if (!column->IsSmi()) {
1702 return Message::kNoColumnInfo;
1703 }
1704 return i::Smi::cast(*column)->value();
1705}
1706
1707
1708Local<String> StackFrame::GetScriptName() const {
1709 if (IsDeadCheck("v8::StackFrame::GetScriptName()")) return Local<String>();
1710 ENTER_V8;
1711 HandleScope scope;
1712 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1713 i::Handle<i::Object> name = GetProperty(self, "scriptName");
1714 if (!name->IsString()) {
1715 return Local<String>();
1716 }
1717 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1718}
1719
1720
Ben Murdochf87a2032010-10-22 12:50:53 +01001721Local<String> StackFrame::GetScriptNameOrSourceURL() const {
1722 if (IsDeadCheck("v8::StackFrame::GetScriptNameOrSourceURL()")) {
1723 return Local<String>();
1724 }
1725 ENTER_V8;
1726 HandleScope scope;
1727 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1728 i::Handle<i::Object> name = GetProperty(self, "scriptNameOrSourceURL");
1729 if (!name->IsString()) {
1730 return Local<String>();
1731 }
1732 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1733}
1734
1735
Kristian Monsen25f61362010-05-21 11:50:48 +01001736Local<String> StackFrame::GetFunctionName() const {
1737 if (IsDeadCheck("v8::StackFrame::GetFunctionName()")) return Local<String>();
1738 ENTER_V8;
1739 HandleScope scope;
1740 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1741 i::Handle<i::Object> name = GetProperty(self, "functionName");
1742 if (!name->IsString()) {
1743 return Local<String>();
1744 }
1745 return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
1746}
1747
1748
1749bool StackFrame::IsEval() const {
1750 if (IsDeadCheck("v8::StackFrame::IsEval()")) return false;
1751 ENTER_V8;
1752 i::HandleScope scope;
1753 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1754 i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
1755 return is_eval->IsTrue();
1756}
1757
1758
1759bool StackFrame::IsConstructor() const {
1760 if (IsDeadCheck("v8::StackFrame::IsConstructor()")) return false;
1761 ENTER_V8;
1762 i::HandleScope scope;
1763 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1764 i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
1765 return is_constructor->IsTrue();
1766}
1767
1768
Steve Blocka7e24c12009-10-30 11:49:00 +00001769// --- D a t a ---
1770
1771bool Value::IsUndefined() const {
1772 if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1773 return Utils::OpenHandle(this)->IsUndefined();
1774}
1775
1776
1777bool Value::IsNull() const {
1778 if (IsDeadCheck("v8::Value::IsNull()")) return false;
1779 return Utils::OpenHandle(this)->IsNull();
1780}
1781
1782
1783bool Value::IsTrue() const {
1784 if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1785 return Utils::OpenHandle(this)->IsTrue();
1786}
1787
1788
1789bool Value::IsFalse() const {
1790 if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1791 return Utils::OpenHandle(this)->IsFalse();
1792}
1793
1794
1795bool Value::IsFunction() const {
1796 if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1797 return Utils::OpenHandle(this)->IsJSFunction();
1798}
1799
1800
1801bool Value::FullIsString() const {
1802 if (IsDeadCheck("v8::Value::IsString()")) return false;
1803 bool result = Utils::OpenHandle(this)->IsString();
1804 ASSERT_EQ(result, QuickIsString());
1805 return result;
1806}
1807
1808
1809bool Value::IsArray() const {
1810 if (IsDeadCheck("v8::Value::IsArray()")) return false;
1811 return Utils::OpenHandle(this)->IsJSArray();
1812}
1813
1814
1815bool Value::IsObject() const {
1816 if (IsDeadCheck("v8::Value::IsObject()")) return false;
1817 return Utils::OpenHandle(this)->IsJSObject();
1818}
1819
1820
1821bool Value::IsNumber() const {
1822 if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1823 return Utils::OpenHandle(this)->IsNumber();
1824}
1825
1826
1827bool Value::IsBoolean() const {
1828 if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1829 return Utils::OpenHandle(this)->IsBoolean();
1830}
1831
1832
1833bool Value::IsExternal() const {
1834 if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1835 return Utils::OpenHandle(this)->IsProxy();
1836}
1837
1838
1839bool Value::IsInt32() const {
1840 if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1841 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1842 if (obj->IsSmi()) return true;
1843 if (obj->IsNumber()) {
1844 double value = obj->Number();
1845 return i::FastI2D(i::FastD2I(value)) == value;
1846 }
1847 return false;
1848}
1849
1850
Steve Block6ded16b2010-05-10 14:33:55 +01001851bool Value::IsUint32() const {
1852 if (IsDeadCheck("v8::Value::IsUint32()")) return false;
1853 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1854 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
1855 if (obj->IsNumber()) {
1856 double value = obj->Number();
1857 return i::FastUI2D(i::FastD2UI(value)) == value;
1858 }
1859 return false;
1860}
1861
1862
Steve Blocka7e24c12009-10-30 11:49:00 +00001863bool Value::IsDate() const {
1864 if (IsDeadCheck("v8::Value::IsDate()")) return false;
1865 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1866 return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1867}
1868
1869
Iain Merrick75681382010-08-19 15:07:18 +01001870bool Value::IsRegExp() const {
1871 if (IsDeadCheck("v8::Value::IsRegExp()")) return false;
1872 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1873 return obj->IsJSRegExp();
1874}
1875
1876
Steve Blocka7e24c12009-10-30 11:49:00 +00001877Local<String> Value::ToString() const {
1878 if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1879 LOG_API("ToString");
1880 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1881 i::Handle<i::Object> str;
1882 if (obj->IsString()) {
1883 str = obj;
1884 } else {
1885 ENTER_V8;
1886 EXCEPTION_PREAMBLE();
1887 str = i::Execution::ToString(obj, &has_pending_exception);
1888 EXCEPTION_BAILOUT_CHECK(Local<String>());
1889 }
1890 return Local<String>(ToApi<String>(str));
1891}
1892
1893
1894Local<String> Value::ToDetailString() const {
1895 if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1896 LOG_API("ToDetailString");
1897 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1898 i::Handle<i::Object> str;
1899 if (obj->IsString()) {
1900 str = obj;
1901 } else {
1902 ENTER_V8;
1903 EXCEPTION_PREAMBLE();
1904 str = i::Execution::ToDetailString(obj, &has_pending_exception);
1905 EXCEPTION_BAILOUT_CHECK(Local<String>());
1906 }
1907 return Local<String>(ToApi<String>(str));
1908}
1909
1910
1911Local<v8::Object> Value::ToObject() const {
1912 if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1913 LOG_API("ToObject");
1914 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1915 i::Handle<i::Object> val;
1916 if (obj->IsJSObject()) {
1917 val = obj;
1918 } else {
1919 ENTER_V8;
1920 EXCEPTION_PREAMBLE();
1921 val = i::Execution::ToObject(obj, &has_pending_exception);
1922 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1923 }
1924 return Local<v8::Object>(ToApi<Object>(val));
1925}
1926
1927
1928Local<Boolean> Value::ToBoolean() const {
1929 if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1930 LOG_API("ToBoolean");
1931 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1932 if (obj->IsBoolean()) {
1933 return Local<Boolean>(ToApi<Boolean>(obj));
1934 } else {
1935 ENTER_V8;
1936 i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1937 return Local<Boolean>(ToApi<Boolean>(val));
1938 }
1939}
1940
1941
1942Local<Number> Value::ToNumber() const {
1943 if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1944 LOG_API("ToNumber");
1945 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1946 i::Handle<i::Object> num;
1947 if (obj->IsNumber()) {
1948 num = obj;
1949 } else {
1950 ENTER_V8;
1951 EXCEPTION_PREAMBLE();
1952 num = i::Execution::ToNumber(obj, &has_pending_exception);
1953 EXCEPTION_BAILOUT_CHECK(Local<Number>());
1954 }
1955 return Local<Number>(ToApi<Number>(num));
1956}
1957
1958
1959Local<Integer> Value::ToInteger() const {
1960 if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1961 LOG_API("ToInteger");
1962 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1963 i::Handle<i::Object> num;
1964 if (obj->IsSmi()) {
1965 num = obj;
1966 } else {
1967 ENTER_V8;
1968 EXCEPTION_PREAMBLE();
1969 num = i::Execution::ToInteger(obj, &has_pending_exception);
1970 EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1971 }
1972 return Local<Integer>(ToApi<Integer>(num));
1973}
1974
1975
1976void External::CheckCast(v8::Value* that) {
1977 if (IsDeadCheck("v8::External::Cast()")) return;
1978 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1979 ApiCheck(obj->IsProxy(),
1980 "v8::External::Cast()",
1981 "Could not convert to external");
1982}
1983
1984
1985void v8::Object::CheckCast(Value* that) {
1986 if (IsDeadCheck("v8::Object::Cast()")) return;
1987 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1988 ApiCheck(obj->IsJSObject(),
1989 "v8::Object::Cast()",
1990 "Could not convert to object");
1991}
1992
1993
1994void v8::Function::CheckCast(Value* that) {
1995 if (IsDeadCheck("v8::Function::Cast()")) return;
1996 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1997 ApiCheck(obj->IsJSFunction(),
1998 "v8::Function::Cast()",
1999 "Could not convert to function");
2000}
2001
2002
2003void v8::String::CheckCast(v8::Value* that) {
2004 if (IsDeadCheck("v8::String::Cast()")) return;
2005 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2006 ApiCheck(obj->IsString(),
2007 "v8::String::Cast()",
2008 "Could not convert to string");
2009}
2010
2011
2012void v8::Number::CheckCast(v8::Value* that) {
2013 if (IsDeadCheck("v8::Number::Cast()")) return;
2014 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2015 ApiCheck(obj->IsNumber(),
2016 "v8::Number::Cast()",
2017 "Could not convert to number");
2018}
2019
2020
2021void v8::Integer::CheckCast(v8::Value* that) {
2022 if (IsDeadCheck("v8::Integer::Cast()")) return;
2023 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2024 ApiCheck(obj->IsNumber(),
2025 "v8::Integer::Cast()",
2026 "Could not convert to number");
2027}
2028
2029
2030void v8::Array::CheckCast(Value* that) {
2031 if (IsDeadCheck("v8::Array::Cast()")) return;
2032 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2033 ApiCheck(obj->IsJSArray(),
2034 "v8::Array::Cast()",
2035 "Could not convert to array");
2036}
2037
2038
2039void v8::Date::CheckCast(v8::Value* that) {
2040 if (IsDeadCheck("v8::Date::Cast()")) return;
2041 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2042 ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
2043 "v8::Date::Cast()",
2044 "Could not convert to date");
2045}
2046
2047
Ben Murdochf87a2032010-10-22 12:50:53 +01002048void v8::RegExp::CheckCast(v8::Value* that) {
2049 if (IsDeadCheck("v8::RegExp::Cast()")) return;
2050 i::Handle<i::Object> obj = Utils::OpenHandle(that);
2051 ApiCheck(obj->IsJSRegExp(),
2052 "v8::RegExp::Cast()",
2053 "Could not convert to regular expression");
2054}
2055
2056
Steve Blocka7e24c12009-10-30 11:49:00 +00002057bool Value::BooleanValue() const {
2058 if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
2059 LOG_API("BooleanValue");
2060 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2061 if (obj->IsBoolean()) {
2062 return obj->IsTrue();
2063 } else {
2064 ENTER_V8;
2065 i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
2066 return value->IsTrue();
2067 }
2068}
2069
2070
2071double Value::NumberValue() const {
2072 if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
2073 LOG_API("NumberValue");
2074 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2075 i::Handle<i::Object> num;
2076 if (obj->IsNumber()) {
2077 num = obj;
2078 } else {
2079 ENTER_V8;
2080 EXCEPTION_PREAMBLE();
2081 num = i::Execution::ToNumber(obj, &has_pending_exception);
2082 EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
2083 }
2084 return num->Number();
2085}
2086
2087
2088int64_t Value::IntegerValue() const {
2089 if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
2090 LOG_API("IntegerValue");
2091 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2092 i::Handle<i::Object> num;
2093 if (obj->IsNumber()) {
2094 num = obj;
2095 } else {
2096 ENTER_V8;
2097 EXCEPTION_PREAMBLE();
2098 num = i::Execution::ToInteger(obj, &has_pending_exception);
2099 EXCEPTION_BAILOUT_CHECK(0);
2100 }
2101 if (num->IsSmi()) {
2102 return i::Smi::cast(*num)->value();
2103 } else {
2104 return static_cast<int64_t>(num->Number());
2105 }
2106}
2107
2108
2109Local<Int32> Value::ToInt32() const {
2110 if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
2111 LOG_API("ToInt32");
2112 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2113 i::Handle<i::Object> num;
2114 if (obj->IsSmi()) {
2115 num = obj;
2116 } else {
2117 ENTER_V8;
2118 EXCEPTION_PREAMBLE();
2119 num = i::Execution::ToInt32(obj, &has_pending_exception);
2120 EXCEPTION_BAILOUT_CHECK(Local<Int32>());
2121 }
2122 return Local<Int32>(ToApi<Int32>(num));
2123}
2124
2125
2126Local<Uint32> Value::ToUint32() const {
2127 if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
2128 LOG_API("ToUInt32");
2129 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2130 i::Handle<i::Object> num;
2131 if (obj->IsSmi()) {
2132 num = obj;
2133 } else {
2134 ENTER_V8;
2135 EXCEPTION_PREAMBLE();
2136 num = i::Execution::ToUint32(obj, &has_pending_exception);
2137 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2138 }
2139 return Local<Uint32>(ToApi<Uint32>(num));
2140}
2141
2142
2143Local<Uint32> Value::ToArrayIndex() const {
2144 if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
2145 LOG_API("ToArrayIndex");
2146 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2147 if (obj->IsSmi()) {
2148 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2149 return Local<Uint32>();
2150 }
2151 ENTER_V8;
2152 EXCEPTION_PREAMBLE();
2153 i::Handle<i::Object> string_obj =
2154 i::Execution::ToString(obj, &has_pending_exception);
2155 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
2156 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2157 uint32_t index;
2158 if (str->AsArrayIndex(&index)) {
2159 i::Handle<i::Object> value;
2160 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2161 value = i::Handle<i::Object>(i::Smi::FromInt(index));
2162 } else {
2163 value = i::Factory::NewNumber(index);
2164 }
2165 return Utils::Uint32ToLocal(value);
2166 }
2167 return Local<Uint32>();
2168}
2169
2170
2171int32_t Value::Int32Value() const {
2172 if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
2173 LOG_API("Int32Value");
2174 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2175 if (obj->IsSmi()) {
2176 return i::Smi::cast(*obj)->value();
2177 } else {
2178 LOG_API("Int32Value (slow)");
2179 ENTER_V8;
2180 EXCEPTION_PREAMBLE();
2181 i::Handle<i::Object> num =
2182 i::Execution::ToInt32(obj, &has_pending_exception);
2183 EXCEPTION_BAILOUT_CHECK(0);
2184 if (num->IsSmi()) {
2185 return i::Smi::cast(*num)->value();
2186 } else {
2187 return static_cast<int32_t>(num->Number());
2188 }
2189 }
2190}
2191
2192
2193bool Value::Equals(Handle<Value> that) const {
2194 if (IsDeadCheck("v8::Value::Equals()")
2195 || EmptyCheck("v8::Value::Equals()", this)
2196 || EmptyCheck("v8::Value::Equals()", that)) {
2197 return false;
2198 }
2199 LOG_API("Equals");
2200 ENTER_V8;
2201 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2202 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2203 i::Object** args[1] = { other.location() };
2204 EXCEPTION_PREAMBLE();
2205 i::Handle<i::Object> result =
2206 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
2207 EXCEPTION_BAILOUT_CHECK(false);
2208 return *result == i::Smi::FromInt(i::EQUAL);
2209}
2210
2211
2212bool Value::StrictEquals(Handle<Value> that) const {
2213 if (IsDeadCheck("v8::Value::StrictEquals()")
2214 || EmptyCheck("v8::Value::StrictEquals()", this)
2215 || EmptyCheck("v8::Value::StrictEquals()", that)) {
2216 return false;
2217 }
2218 LOG_API("StrictEquals");
2219 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2220 i::Handle<i::Object> other = Utils::OpenHandle(*that);
2221 // Must check HeapNumber first, since NaN !== NaN.
2222 if (obj->IsHeapNumber()) {
2223 if (!other->IsNumber()) return false;
2224 double x = obj->Number();
2225 double y = other->Number();
2226 // Must check explicitly for NaN:s on Windows, but -0 works fine.
2227 return x == y && !isnan(x) && !isnan(y);
2228 } else if (*obj == *other) { // Also covers Booleans.
2229 return true;
2230 } else if (obj->IsSmi()) {
2231 return other->IsNumber() && obj->Number() == other->Number();
2232 } else if (obj->IsString()) {
2233 return other->IsString() &&
2234 i::String::cast(*obj)->Equals(i::String::cast(*other));
2235 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2236 return other->IsUndefined() || other->IsUndetectableObject();
2237 } else {
2238 return false;
2239 }
2240}
2241
2242
2243uint32_t Value::Uint32Value() const {
2244 if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
2245 LOG_API("Uint32Value");
2246 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2247 if (obj->IsSmi()) {
2248 return i::Smi::cast(*obj)->value();
2249 } else {
2250 ENTER_V8;
2251 EXCEPTION_PREAMBLE();
2252 i::Handle<i::Object> num =
2253 i::Execution::ToUint32(obj, &has_pending_exception);
2254 EXCEPTION_BAILOUT_CHECK(0);
2255 if (num->IsSmi()) {
2256 return i::Smi::cast(*num)->value();
2257 } else {
2258 return static_cast<uint32_t>(num->Number());
2259 }
2260 }
2261}
2262
2263
2264bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
2265 v8::PropertyAttribute attribs) {
2266 ON_BAILOUT("v8::Object::Set()", return false);
2267 ENTER_V8;
2268 HandleScope scope;
2269 i::Handle<i::Object> self = Utils::OpenHandle(this);
2270 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2271 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2272 EXCEPTION_PREAMBLE();
2273 i::Handle<i::Object> obj = i::SetProperty(
2274 self,
2275 key_obj,
2276 value_obj,
2277 static_cast<PropertyAttributes>(attribs));
2278 has_pending_exception = obj.is_null();
2279 EXCEPTION_BAILOUT_CHECK(false);
2280 return true;
2281}
2282
2283
Steve Block6ded16b2010-05-10 14:33:55 +01002284bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
2285 ON_BAILOUT("v8::Object::Set()", return false);
2286 ENTER_V8;
2287 HandleScope scope;
2288 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2289 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2290 EXCEPTION_PREAMBLE();
2291 i::Handle<i::Object> obj = i::SetElement(
2292 self,
2293 index,
2294 value_obj);
2295 has_pending_exception = obj.is_null();
2296 EXCEPTION_BAILOUT_CHECK(false);
2297 return true;
2298}
2299
2300
Steve Blocka7e24c12009-10-30 11:49:00 +00002301bool v8::Object::ForceSet(v8::Handle<Value> key,
2302 v8::Handle<Value> value,
2303 v8::PropertyAttribute attribs) {
2304 ON_BAILOUT("v8::Object::ForceSet()", return false);
2305 ENTER_V8;
2306 HandleScope scope;
2307 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2308 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2309 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2310 EXCEPTION_PREAMBLE();
2311 i::Handle<i::Object> obj = i::ForceSetProperty(
2312 self,
2313 key_obj,
2314 value_obj,
2315 static_cast<PropertyAttributes>(attribs));
2316 has_pending_exception = obj.is_null();
2317 EXCEPTION_BAILOUT_CHECK(false);
2318 return true;
2319}
2320
2321
2322bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2323 ON_BAILOUT("v8::Object::ForceDelete()", return false);
2324 ENTER_V8;
2325 HandleScope scope;
2326 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2327 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002328
2329 // When turning on access checks for a global object deoptimize all functions
2330 // as optimized code does not always handle access checks.
2331 i::Deoptimizer::DeoptimizeGlobalObject(*self);
2332
Steve Blocka7e24c12009-10-30 11:49:00 +00002333 EXCEPTION_PREAMBLE();
2334 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2335 has_pending_exception = obj.is_null();
2336 EXCEPTION_BAILOUT_CHECK(false);
2337 return obj->IsTrue();
2338}
2339
2340
2341Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2342 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2343 ENTER_V8;
2344 i::Handle<i::Object> self = Utils::OpenHandle(this);
2345 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2346 EXCEPTION_PREAMBLE();
2347 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2348 has_pending_exception = result.is_null();
2349 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2350 return Utils::ToLocal(result);
2351}
2352
2353
Steve Block6ded16b2010-05-10 14:33:55 +01002354Local<Value> v8::Object::Get(uint32_t index) {
2355 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2356 ENTER_V8;
2357 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2358 EXCEPTION_PREAMBLE();
2359 i::Handle<i::Object> result = i::GetElement(self, index);
2360 has_pending_exception = result.is_null();
2361 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2362 return Utils::ToLocal(result);
2363}
2364
2365
Steve Blocka7e24c12009-10-30 11:49:00 +00002366Local<Value> v8::Object::GetPrototype() {
2367 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
2368 ENTER_V8;
2369 i::Handle<i::Object> self = Utils::OpenHandle(this);
2370 i::Handle<i::Object> result = i::GetPrototype(self);
2371 return Utils::ToLocal(result);
2372}
2373
2374
Andrei Popescu402d9372010-02-26 13:31:12 +00002375bool v8::Object::SetPrototype(Handle<Value> value) {
2376 ON_BAILOUT("v8::Object::SetPrototype()", return false);
2377 ENTER_V8;
2378 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2379 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2380 EXCEPTION_PREAMBLE();
2381 i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2382 has_pending_exception = result.is_null();
2383 EXCEPTION_BAILOUT_CHECK(false);
2384 return true;
2385}
2386
2387
Steve Blocka7e24c12009-10-30 11:49:00 +00002388Local<Object> v8::Object::FindInstanceInPrototypeChain(
2389 v8::Handle<FunctionTemplate> tmpl) {
2390 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
2391 return Local<v8::Object>());
2392 ENTER_V8;
2393 i::JSObject* object = *Utils::OpenHandle(this);
2394 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2395 while (!object->IsInstanceOf(tmpl_info)) {
2396 i::Object* prototype = object->GetPrototype();
2397 if (!prototype->IsJSObject()) return Local<Object>();
2398 object = i::JSObject::cast(prototype);
2399 }
2400 return Utils::ToLocal(i::Handle<i::JSObject>(object));
2401}
2402
2403
2404Local<Array> v8::Object::GetPropertyNames() {
2405 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
2406 ENTER_V8;
2407 v8::HandleScope scope;
2408 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2409 i::Handle<i::FixedArray> value =
2410 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2411 // Because we use caching to speed up enumeration it is important
2412 // to never change the result of the basic enumeration function so
2413 // we clone the result.
2414 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
2415 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
2416 return scope.Close(Utils::ToLocal(result));
2417}
2418
2419
2420Local<String> v8::Object::ObjectProtoToString() {
2421 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2422 ENTER_V8;
2423 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2424
2425 i::Handle<i::Object> name(self->class_name());
2426
2427 // Native implementation of Object.prototype.toString (v8natives.js):
2428 // var c = %ClassOf(this);
2429 // if (c === 'Arguments') c = 'Object';
2430 // return "[object " + c + "]";
2431
2432 if (!name->IsString()) {
2433 return v8::String::New("[object ]");
2434
2435 } else {
2436 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2437 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2438 return v8::String::New("[object Object]");
2439
2440 } else {
2441 const char* prefix = "[object ";
2442 Local<String> str = Utils::ToLocal(class_name);
2443 const char* postfix = "]";
2444
Steve Blockd0582a62009-12-15 09:54:21 +00002445 int prefix_len = i::StrLength(prefix);
2446 int str_len = str->Length();
2447 int postfix_len = i::StrLength(postfix);
Steve Blocka7e24c12009-10-30 11:49:00 +00002448
Steve Blockd0582a62009-12-15 09:54:21 +00002449 int buf_len = prefix_len + str_len + postfix_len;
Kristian Monsen25f61362010-05-21 11:50:48 +01002450 i::ScopedVector<char> buf(buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002451
2452 // Write prefix.
Kristian Monsen25f61362010-05-21 11:50:48 +01002453 char* ptr = buf.start();
Steve Blocka7e24c12009-10-30 11:49:00 +00002454 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2455 ptr += prefix_len;
2456
2457 // Write real content.
2458 str->WriteAscii(ptr, 0, str_len);
2459 ptr += str_len;
2460
2461 // Write postfix.
2462 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2463
2464 // Copy the buffer into a heap-allocated string and return it.
Kristian Monsen25f61362010-05-21 11:50:48 +01002465 Local<String> result = v8::String::New(buf.start(), buf_len);
Steve Blocka7e24c12009-10-30 11:49:00 +00002466 return result;
2467 }
2468 }
2469}
2470
2471
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08002472Local<String> v8::Object::GetConstructorName() {
2473 ON_BAILOUT("v8::Object::GetConstructorName()", return Local<v8::String>());
2474 ENTER_V8;
2475 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2476 i::Handle<i::String> name(self->constructor_name());
2477 return Utils::ToLocal(name);
2478}
2479
2480
Steve Blocka7e24c12009-10-30 11:49:00 +00002481bool v8::Object::Delete(v8::Handle<String> key) {
2482 ON_BAILOUT("v8::Object::Delete()", return false);
2483 ENTER_V8;
2484 HandleScope scope;
2485 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2486 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2487 return i::DeleteProperty(self, key_obj)->IsTrue();
2488}
2489
2490
2491bool v8::Object::Has(v8::Handle<String> key) {
2492 ON_BAILOUT("v8::Object::Has()", return false);
2493 ENTER_V8;
2494 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2495 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2496 return self->HasProperty(*key_obj);
2497}
2498
2499
2500bool v8::Object::Delete(uint32_t index) {
2501 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2502 ENTER_V8;
2503 HandleScope scope;
2504 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2505 return i::DeleteElement(self, index)->IsTrue();
2506}
2507
2508
2509bool v8::Object::Has(uint32_t index) {
2510 ON_BAILOUT("v8::Object::HasProperty()", return false);
2511 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2512 return self->HasElement(index);
2513}
2514
2515
Leon Clarkef7060e22010-06-03 12:02:55 +01002516bool Object::SetAccessor(Handle<String> name,
2517 AccessorGetter getter,
2518 AccessorSetter setter,
2519 v8::Handle<Value> data,
2520 AccessControl settings,
2521 PropertyAttribute attributes) {
2522 ON_BAILOUT("v8::Object::SetAccessor()", return false);
2523 ENTER_V8;
2524 HandleScope scope;
2525 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name,
2526 getter, setter, data,
2527 settings, attributes);
2528 i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info);
2529 return !result.is_null() && !result->IsUndefined();
2530}
2531
2532
Steve Blocka7e24c12009-10-30 11:49:00 +00002533bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2534 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2535 return Utils::OpenHandle(this)->HasRealNamedProperty(
2536 *Utils::OpenHandle(*key));
2537}
2538
2539
2540bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2541 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2542 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2543}
2544
2545
2546bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2547 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2548 ENTER_V8;
2549 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2550 *Utils::OpenHandle(*key));
2551}
2552
2553
2554bool v8::Object::HasNamedLookupInterceptor() {
2555 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2556 return Utils::OpenHandle(this)->HasNamedInterceptor();
2557}
2558
2559
2560bool v8::Object::HasIndexedLookupInterceptor() {
2561 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2562 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2563}
2564
2565
2566Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2567 Handle<String> key) {
2568 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2569 return Local<Value>());
2570 ENTER_V8;
2571 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2572 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2573 i::LookupResult lookup;
2574 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002575 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002576 PropertyAttributes attributes;
John Reck59135872010-11-02 12:39:01 -07002577 i::Object* property =
2578 self_obj->GetProperty(*self_obj,
2579 &lookup,
2580 *key_obj,
2581 &attributes)->ToObjectUnchecked();
2582 i::Handle<i::Object> result(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00002583 return Utils::ToLocal(result);
2584 }
2585 return Local<Value>(); // No real property was found in prototype chain.
2586}
2587
2588
2589Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2590 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
2591 ENTER_V8;
2592 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2593 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2594 i::LookupResult lookup;
2595 self_obj->LookupRealNamedProperty(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002596 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002597 PropertyAttributes attributes;
John Reck59135872010-11-02 12:39:01 -07002598 i::Object* property =
2599 self_obj->GetProperty(*self_obj,
2600 &lookup,
2601 *key_obj,
2602 &attributes)->ToObjectUnchecked();
2603 i::Handle<i::Object> result(property);
Steve Blocka7e24c12009-10-30 11:49:00 +00002604 return Utils::ToLocal(result);
2605 }
2606 return Local<Value>(); // No real property was found in prototype chain.
2607}
2608
2609
2610// Turns on access checks by copying the map and setting the check flag.
2611// Because the object gets a new map, existing inline cache caching
2612// the old map of this object will fail.
2613void v8::Object::TurnOnAccessCheck() {
2614 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2615 ENTER_V8;
2616 HandleScope scope;
2617 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2618
Ben Murdochb0fe1622011-05-05 13:52:32 +01002619 // When turning on access checks for a global object deoptimize all functions
2620 // as optimized code does not always handle access checks.
2621 i::Deoptimizer::DeoptimizeGlobalObject(*obj);
2622
Steve Blocka7e24c12009-10-30 11:49:00 +00002623 i::Handle<i::Map> new_map =
2624 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2625 new_map->set_is_access_check_needed(true);
2626 obj->set_map(*new_map);
2627}
2628
2629
2630bool v8::Object::IsDirty() {
2631 return Utils::OpenHandle(this)->IsDirty();
2632}
2633
2634
2635Local<v8::Object> v8::Object::Clone() {
2636 ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2637 ENTER_V8;
2638 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2639 EXCEPTION_PREAMBLE();
2640 i::Handle<i::JSObject> result = i::Copy(self);
2641 has_pending_exception = result.is_null();
2642 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2643 return Utils::ToLocal(result);
2644}
2645
2646
2647int v8::Object::GetIdentityHash() {
2648 ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2649 ENTER_V8;
2650 HandleScope scope;
2651 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2652 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2653 i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
2654 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2655 int hash_value;
2656 if (hash->IsSmi()) {
2657 hash_value = i::Smi::cast(*hash)->value();
2658 } else {
2659 int attempts = 0;
2660 do {
2661 // Generate a random 32-bit hash value but limit range to fit
2662 // within a smi.
2663 hash_value = i::V8::Random() & i::Smi::kMaxValue;
2664 attempts++;
2665 } while (hash_value == 0 && attempts < 30);
2666 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
2667 i::SetProperty(hidden_props,
2668 hash_symbol,
2669 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2670 static_cast<PropertyAttributes>(None));
2671 }
2672 return hash_value;
2673}
2674
2675
2676bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2677 v8::Handle<v8::Value> value) {
2678 ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
2679 ENTER_V8;
2680 HandleScope scope;
2681 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2682 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2683 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2684 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2685 EXCEPTION_PREAMBLE();
2686 i::Handle<i::Object> obj = i::SetProperty(
2687 hidden_props,
2688 key_obj,
2689 value_obj,
2690 static_cast<PropertyAttributes>(None));
2691 has_pending_exception = obj.is_null();
2692 EXCEPTION_BAILOUT_CHECK(false);
2693 return true;
2694}
2695
2696
2697v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2698 ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2699 ENTER_V8;
2700 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2701 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2702 if (hidden_props->IsUndefined()) {
2703 return v8::Local<v8::Value>();
2704 }
2705 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2706 EXCEPTION_PREAMBLE();
2707 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2708 has_pending_exception = result.is_null();
2709 EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2710 if (result->IsUndefined()) {
2711 return v8::Local<v8::Value>();
2712 }
2713 return Utils::ToLocal(result);
2714}
2715
2716
2717bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2718 ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2719 ENTER_V8;
2720 HandleScope scope;
2721 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2722 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2723 if (hidden_props->IsUndefined()) {
2724 return true;
2725 }
2726 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2727 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2728 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2729}
2730
2731
2732void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2733 ON_BAILOUT("v8::SetElementsToPixelData()", return);
2734 ENTER_V8;
2735 HandleScope scope;
Steve Block3ce2e202009-11-05 08:53:23 +00002736 if (!ApiCheck(length <= i::PixelArray::kMaxLength,
Steve Blocka7e24c12009-10-30 11:49:00 +00002737 "v8::Object::SetIndexedPropertiesToPixelData()",
2738 "length exceeds max acceptable value")) {
2739 return;
2740 }
2741 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2742 if (!ApiCheck(!self->IsJSArray(),
2743 "v8::Object::SetIndexedPropertiesToPixelData()",
2744 "JSArray is not supported")) {
2745 return;
2746 }
2747 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002748 i::Handle<i::Map> slow_map =
2749 i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map()));
2750 self->set_map(*slow_map);
Steve Blocka7e24c12009-10-30 11:49:00 +00002751 self->set_elements(*pixels);
2752}
2753
2754
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002755bool v8::Object::HasIndexedPropertiesInPixelData() {
2756 ON_BAILOUT("v8::HasIndexedPropertiesInPixelData()", return false);
2757 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2758 return self->HasPixelElements();
2759}
2760
2761
2762uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
2763 ON_BAILOUT("v8::GetIndexedPropertiesPixelData()", return NULL);
2764 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2765 if (self->HasPixelElements()) {
2766 return i::PixelArray::cast(self->elements())->external_pointer();
2767 } else {
2768 return NULL;
2769 }
2770}
2771
2772
2773int v8::Object::GetIndexedPropertiesPixelDataLength() {
2774 ON_BAILOUT("v8::GetIndexedPropertiesPixelDataLength()", return -1);
2775 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2776 if (self->HasPixelElements()) {
2777 return i::PixelArray::cast(self->elements())->length();
2778 } else {
2779 return -1;
2780 }
2781}
2782
2783
Steve Block3ce2e202009-11-05 08:53:23 +00002784void v8::Object::SetIndexedPropertiesToExternalArrayData(
2785 void* data,
2786 ExternalArrayType array_type,
2787 int length) {
2788 ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
2789 ENTER_V8;
2790 HandleScope scope;
2791 if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
2792 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2793 "length exceeds max acceptable value")) {
2794 return;
2795 }
2796 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2797 if (!ApiCheck(!self->IsJSArray(),
2798 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2799 "JSArray is not supported")) {
2800 return;
2801 }
2802 i::Handle<i::ExternalArray> array =
2803 i::Factory::NewExternalArray(length, array_type, data);
Kristian Monsen0d5e1162010-09-30 15:31:59 +01002804 i::Handle<i::Map> slow_map =
2805 i::Factory::GetSlowElementsMap(i::Handle<i::Map>(self->map()));
2806 self->set_map(*slow_map);
Steve Block3ce2e202009-11-05 08:53:23 +00002807 self->set_elements(*array);
2808}
2809
2810
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01002811bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
2812 ON_BAILOUT("v8::HasIndexedPropertiesInExternalArrayData()", return false);
2813 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2814 return self->HasExternalArrayElements();
2815}
2816
2817
2818void* v8::Object::GetIndexedPropertiesExternalArrayData() {
2819 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayData()", return NULL);
2820 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2821 if (self->HasExternalArrayElements()) {
2822 return i::ExternalArray::cast(self->elements())->external_pointer();
2823 } else {
2824 return NULL;
2825 }
2826}
2827
2828
2829ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
2830 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataType()",
2831 return static_cast<ExternalArrayType>(-1));
2832 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2833 switch (self->elements()->map()->instance_type()) {
2834 case i::EXTERNAL_BYTE_ARRAY_TYPE:
2835 return kExternalByteArray;
2836 case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
2837 return kExternalUnsignedByteArray;
2838 case i::EXTERNAL_SHORT_ARRAY_TYPE:
2839 return kExternalShortArray;
2840 case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
2841 return kExternalUnsignedShortArray;
2842 case i::EXTERNAL_INT_ARRAY_TYPE:
2843 return kExternalIntArray;
2844 case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
2845 return kExternalUnsignedIntArray;
2846 case i::EXTERNAL_FLOAT_ARRAY_TYPE:
2847 return kExternalFloatArray;
2848 default:
2849 return static_cast<ExternalArrayType>(-1);
2850 }
2851}
2852
2853
2854int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
2855 ON_BAILOUT("v8::GetIndexedPropertiesExternalArrayDataLength()", return 0);
2856 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2857 if (self->HasExternalArrayElements()) {
2858 return i::ExternalArray::cast(self->elements())->length();
2859 } else {
2860 return -1;
2861 }
2862}
2863
2864
Steve Blocka7e24c12009-10-30 11:49:00 +00002865Local<v8::Object> Function::NewInstance() const {
2866 return NewInstance(0, NULL);
2867}
2868
2869
2870Local<v8::Object> Function::NewInstance(int argc,
2871 v8::Handle<v8::Value> argv[]) const {
2872 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2873 LOG_API("Function::NewInstance");
2874 ENTER_V8;
2875 HandleScope scope;
2876 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2877 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2878 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2879 EXCEPTION_PREAMBLE();
2880 i::Handle<i::Object> returned =
2881 i::Execution::New(function, argc, args, &has_pending_exception);
2882 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2883 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2884}
2885
2886
2887Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2888 v8::Handle<v8::Value> argv[]) {
2889 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2890 LOG_API("Function::Call");
2891 ENTER_V8;
2892 i::Object* raw_result = NULL;
2893 {
2894 HandleScope scope;
2895 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2896 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2897 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2898 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2899 EXCEPTION_PREAMBLE();
2900 i::Handle<i::Object> returned =
2901 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2902 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2903 raw_result = *returned;
2904 }
2905 i::Handle<i::Object> result(raw_result);
2906 return Utils::ToLocal(result);
2907}
2908
2909
2910void Function::SetName(v8::Handle<v8::String> name) {
2911 ENTER_V8;
2912 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2913 func->shared()->set_name(*Utils::OpenHandle(*name));
2914}
2915
2916
2917Handle<Value> Function::GetName() const {
2918 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2919 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2920}
2921
2922
Andrei Popescu402d9372010-02-26 13:31:12 +00002923ScriptOrigin Function::GetScriptOrigin() const {
2924 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2925 if (func->shared()->script()->IsScript()) {
2926 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2927 v8::ScriptOrigin origin(
2928 Utils::ToLocal(i::Handle<i::Object>(script->name())),
2929 v8::Integer::New(script->line_offset()->value()),
2930 v8::Integer::New(script->column_offset()->value()));
2931 return origin;
2932 }
2933 return v8::ScriptOrigin(Handle<Value>());
2934}
2935
2936
2937const int Function::kLineOffsetNotFound = -1;
2938
2939
2940int Function::GetScriptLineNumber() const {
2941 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2942 if (func->shared()->script()->IsScript()) {
2943 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2944 return i::GetScriptLineNumber(script, func->shared()->start_position());
2945 }
2946 return kLineOffsetNotFound;
2947}
2948
2949
2950namespace {
2951
2952// Tracks string usage to help make better decisions when
2953// externalizing strings.
2954//
2955// Implementation note: internally this class only tracks fresh
2956// strings and keeps a single use counter for them.
2957class StringTracker {
2958 public:
2959 // Records that the given string's characters were copied to some
2960 // external buffer. If this happens often we should honor
2961 // externalization requests for the string.
2962 static void RecordWrite(i::Handle<i::String> string) {
2963 i::Address address = reinterpret_cast<i::Address>(*string);
2964 i::Address top = i::Heap::NewSpaceTop();
2965 if (IsFreshString(address, top)) {
2966 IncrementUseCount(top);
2967 }
2968 }
2969
2970 // Estimates freshness and use frequency of the given string based
2971 // on how close it is to the new space top and the recorded usage
2972 // history.
2973 static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
2974 i::Address address = reinterpret_cast<i::Address>(*string);
2975 i::Address top = i::Heap::NewSpaceTop();
2976 return IsFreshString(address, top) && IsUseCountLow(top);
2977 }
2978
2979 private:
2980 static inline bool IsFreshString(i::Address string, i::Address top) {
2981 return top - kFreshnessLimit <= string && string <= top;
2982 }
2983
2984 static inline bool IsUseCountLow(i::Address top) {
2985 if (last_top_ != top) return true;
2986 return use_count_ < kUseLimit;
2987 }
2988
2989 static inline void IncrementUseCount(i::Address top) {
2990 if (last_top_ != top) {
2991 use_count_ = 0;
2992 last_top_ = top;
2993 }
2994 ++use_count_;
2995 }
2996
2997 // How close to the new space top a fresh string has to be.
2998 static const int kFreshnessLimit = 1024;
2999
3000 // The number of uses required to consider a string useful.
3001 static const int kUseLimit = 32;
3002
3003 // Single use counter shared by all fresh strings.
3004 static int use_count_;
3005
3006 // Last new space top when the use count above was valid.
3007 static i::Address last_top_;
3008};
3009
3010int StringTracker::use_count_ = 0;
3011i::Address StringTracker::last_top_ = NULL;
3012
3013} // namespace
3014
3015
Steve Blocka7e24c12009-10-30 11:49:00 +00003016int String::Length() const {
3017 if (IsDeadCheck("v8::String::Length()")) return 0;
3018 return Utils::OpenHandle(this)->length();
3019}
3020
3021
3022int String::Utf8Length() const {
3023 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
3024 return Utils::OpenHandle(this)->Utf8Length();
3025}
3026
3027
Steve Block6ded16b2010-05-10 14:33:55 +01003028int String::WriteUtf8(char* buffer,
3029 int capacity,
3030 int* nchars_ref,
3031 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003032 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
3033 LOG_API("String::WriteUtf8");
3034 ENTER_V8;
3035 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003036 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003037 if (hints & HINT_MANY_WRITES_EXPECTED) {
3038 // Flatten the string for efficiency. This applies whether we are
3039 // using StringInputBuffer or Get(i) to access the characters.
3040 str->TryFlatten();
3041 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003042 write_input_buffer.Reset(0, *str);
3043 int len = str->length();
3044 // Encode the first K - 3 bytes directly into the buffer since we
3045 // know there's room for them. If no capacity is given we copy all
3046 // of them here.
3047 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
3048 int i;
3049 int pos = 0;
Steve Block6ded16b2010-05-10 14:33:55 +01003050 int nchars = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +00003051 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
3052 i::uc32 c = write_input_buffer.GetNext();
3053 int written = unibrow::Utf8::Encode(buffer + pos, c);
3054 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01003055 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00003056 }
3057 if (i < len) {
3058 // For the last characters we need to check the length for each one
3059 // because they may be longer than the remaining space in the
3060 // buffer.
3061 char intermediate[unibrow::Utf8::kMaxEncodedSize];
3062 for (; i < len && pos < capacity; i++) {
3063 i::uc32 c = write_input_buffer.GetNext();
3064 int written = unibrow::Utf8::Encode(intermediate, c);
3065 if (pos + written <= capacity) {
3066 for (int j = 0; j < written; j++)
3067 buffer[pos + j] = intermediate[j];
3068 pos += written;
Steve Block6ded16b2010-05-10 14:33:55 +01003069 nchars++;
Steve Blocka7e24c12009-10-30 11:49:00 +00003070 } else {
3071 // We've reached the end of the buffer
3072 break;
3073 }
3074 }
3075 }
Steve Block6ded16b2010-05-10 14:33:55 +01003076 if (nchars_ref != NULL) *nchars_ref = nchars;
Steve Blocka7e24c12009-10-30 11:49:00 +00003077 if (i == len && (capacity == -1 || pos < capacity))
3078 buffer[pos++] = '\0';
3079 return pos;
3080}
3081
3082
Steve Block6ded16b2010-05-10 14:33:55 +01003083int String::WriteAscii(char* buffer,
3084 int start,
3085 int length,
3086 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003087 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
3088 LOG_API("String::WriteAscii");
3089 ENTER_V8;
3090 ASSERT(start >= 0 && length >= -1);
3091 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003092 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003093 if (hints & HINT_MANY_WRITES_EXPECTED) {
3094 // Flatten the string for efficiency. This applies whether we are
3095 // using StringInputBuffer or Get(i) to access the characters.
3096 str->TryFlatten();
3097 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003098 int end = length;
3099 if ( (length == -1) || (length > str->length() - start) )
3100 end = str->length() - start;
3101 if (end < 0) return 0;
3102 write_input_buffer.Reset(start, *str);
3103 int i;
3104 for (i = 0; i < end; i++) {
3105 char c = static_cast<char>(write_input_buffer.GetNext());
3106 if (c == '\0') c = ' ';
3107 buffer[i] = c;
3108 }
3109 if (length == -1 || i < length)
3110 buffer[i] = '\0';
3111 return i;
3112}
3113
3114
Steve Block6ded16b2010-05-10 14:33:55 +01003115int String::Write(uint16_t* buffer,
3116 int start,
3117 int length,
3118 WriteHints hints) const {
Steve Blocka7e24c12009-10-30 11:49:00 +00003119 if (IsDeadCheck("v8::String::Write()")) return 0;
3120 LOG_API("String::Write");
3121 ENTER_V8;
3122 ASSERT(start >= 0 && length >= -1);
3123 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003124 StringTracker::RecordWrite(str);
Steve Block6ded16b2010-05-10 14:33:55 +01003125 if (hints & HINT_MANY_WRITES_EXPECTED) {
3126 // Flatten the string for efficiency. This applies whether we are
3127 // using StringInputBuffer or Get(i) to access the characters.
3128 str->TryFlatten();
3129 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003130 int end = start + length;
3131 if ((length == -1) || (length > str->length() - start) )
3132 end = str->length();
Steve Blocka7e24c12009-10-30 11:49:00 +00003133 if (end < 0) return 0;
3134 i::String::WriteToFlat(*str, buffer, start, end);
Ben Murdochb0fe1622011-05-05 13:52:32 +01003135 if (length == -1 || end - start < length) {
3136 buffer[end - start] = '\0';
3137 }
3138 return end - start;
Steve Blocka7e24c12009-10-30 11:49:00 +00003139}
3140
3141
3142bool v8::String::IsExternal() const {
3143 EnsureInitialized("v8::String::IsExternal()");
3144 i::Handle<i::String> str = Utils::OpenHandle(this);
3145 return i::StringShape(*str).IsExternalTwoByte();
3146}
3147
3148
3149bool v8::String::IsExternalAscii() const {
3150 EnsureInitialized("v8::String::IsExternalAscii()");
3151 i::Handle<i::String> str = Utils::OpenHandle(this);
3152 return i::StringShape(*str).IsExternalAscii();
3153}
3154
3155
3156void v8::String::VerifyExternalStringResource(
3157 v8::String::ExternalStringResource* value) const {
3158 i::Handle<i::String> str = Utils::OpenHandle(this);
3159 v8::String::ExternalStringResource* expected;
3160 if (i::StringShape(*str).IsExternalTwoByte()) {
3161 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
3162 expected = reinterpret_cast<ExternalStringResource*>(resource);
3163 } else {
3164 expected = NULL;
3165 }
3166 CHECK_EQ(expected, value);
3167}
3168
3169
3170v8::String::ExternalAsciiStringResource*
3171 v8::String::GetExternalAsciiStringResource() const {
3172 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
3173 i::Handle<i::String> str = Utils::OpenHandle(this);
3174 if (i::StringShape(*str).IsExternalAscii()) {
3175 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
3176 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
3177 } else {
3178 return NULL;
3179 }
3180}
3181
3182
3183double Number::Value() const {
3184 if (IsDeadCheck("v8::Number::Value()")) return 0;
3185 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3186 return obj->Number();
3187}
3188
3189
3190bool Boolean::Value() const {
3191 if (IsDeadCheck("v8::Boolean::Value()")) return false;
3192 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3193 return obj->IsTrue();
3194}
3195
3196
3197int64_t Integer::Value() const {
3198 if (IsDeadCheck("v8::Integer::Value()")) return 0;
3199 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3200 if (obj->IsSmi()) {
3201 return i::Smi::cast(*obj)->value();
3202 } else {
3203 return static_cast<int64_t>(obj->Number());
3204 }
3205}
3206
3207
3208int32_t Int32::Value() const {
3209 if (IsDeadCheck("v8::Int32::Value()")) return 0;
3210 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3211 if (obj->IsSmi()) {
3212 return i::Smi::cast(*obj)->value();
3213 } else {
3214 return static_cast<int32_t>(obj->Number());
3215 }
3216}
3217
3218
Steve Block6ded16b2010-05-10 14:33:55 +01003219uint32_t Uint32::Value() const {
3220 if (IsDeadCheck("v8::Uint32::Value()")) return 0;
3221 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3222 if (obj->IsSmi()) {
3223 return i::Smi::cast(*obj)->value();
3224 } else {
3225 return static_cast<uint32_t>(obj->Number());
3226 }
3227}
3228
3229
Steve Blocka7e24c12009-10-30 11:49:00 +00003230int v8::Object::InternalFieldCount() {
3231 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
3232 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3233 return obj->GetInternalFieldCount();
3234}
3235
3236
3237Local<Value> v8::Object::CheckedGetInternalField(int index) {
3238 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
3239 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3240 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3241 "v8::Object::GetInternalField()",
3242 "Reading internal field out of bounds")) {
3243 return Local<Value>();
3244 }
3245 i::Handle<i::Object> value(obj->GetInternalField(index));
3246 Local<Value> result = Utils::ToLocal(value);
3247#ifdef DEBUG
3248 Local<Value> unchecked = UncheckedGetInternalField(index);
3249 ASSERT(unchecked.IsEmpty() || (unchecked == result));
3250#endif
3251 return result;
3252}
3253
3254
3255void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
3256 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
3257 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3258 if (!ApiCheck(index < obj->GetInternalFieldCount(),
3259 "v8::Object::SetInternalField()",
3260 "Writing internal field out of bounds")) {
3261 return;
3262 }
3263 ENTER_V8;
3264 i::Handle<i::Object> val = Utils::OpenHandle(*value);
3265 obj->SetInternalField(index, *val);
3266}
3267
3268
Ben Murdochb8e0da22011-05-16 14:20:40 +01003269static bool CanBeEncodedAsSmi(void* ptr) {
3270 const intptr_t address = reinterpret_cast<intptr_t>(ptr);
3271 return ((address & i::kEncodablePointerMask) == 0);
3272}
3273
3274
3275static i::Smi* EncodeAsSmi(void* ptr) {
3276 ASSERT(CanBeEncodedAsSmi(ptr));
3277 const intptr_t address = reinterpret_cast<intptr_t>(ptr);
3278 i::Smi* result = reinterpret_cast<i::Smi*>(address << i::kPointerToSmiShift);
3279 ASSERT(i::Internals::HasSmiTag(result));
3280 ASSERT_EQ(result, i::Smi::FromInt(result->value()));
3281 ASSERT_EQ(ptr, i::Internals::GetExternalPointerFromSmi(result));
3282 return result;
3283}
3284
3285
Steve Blocka7e24c12009-10-30 11:49:00 +00003286void v8::Object::SetPointerInInternalField(int index, void* value) {
Steve Block6ded16b2010-05-10 14:33:55 +01003287 ENTER_V8;
Ben Murdochb8e0da22011-05-16 14:20:40 +01003288 if (CanBeEncodedAsSmi(value)) {
3289 Utils::OpenHandle(this)->SetInternalField(index, EncodeAsSmi(value));
3290 } else {
3291 HandleScope scope;
3292 i::Handle<i::Proxy> proxy =
3293 i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
3294 if (!proxy.is_null())
3295 Utils::OpenHandle(this)->SetInternalField(index, *proxy);
Steve Block3ce2e202009-11-05 08:53:23 +00003296 }
Ben Murdochb8e0da22011-05-16 14:20:40 +01003297 ASSERT_EQ(value, GetPointerFromInternalField(index));
Steve Blocka7e24c12009-10-30 11:49:00 +00003298}
3299
3300
3301// --- E n v i r o n m e n t ---
3302
3303bool v8::V8::Initialize() {
3304 if (i::V8::IsRunning()) return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00003305 HandleScope scope;
Steve Blockd0582a62009-12-15 09:54:21 +00003306 if (i::Snapshot::Initialize()) return true;
3307 return i::V8::Initialize(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00003308}
3309
3310
3311bool v8::V8::Dispose() {
3312 i::V8::TearDown();
3313 return true;
3314}
3315
3316
Russell Brenner90bac252010-11-18 13:33:46 -08003317HeapStatistics::HeapStatistics(): total_heap_size_(0),
3318 total_heap_size_executable_(0),
Ben Murdochb8e0da22011-05-16 14:20:40 +01003319 used_heap_size_(0),
3320 heap_size_limit_(0) { }
Steve Block3ce2e202009-11-05 08:53:23 +00003321
3322
3323void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
3324 heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
Russell Brenner90bac252010-11-18 13:33:46 -08003325 heap_statistics->set_total_heap_size_executable(
3326 i::Heap::CommittedMemoryExecutable());
Steve Block3ce2e202009-11-05 08:53:23 +00003327 heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
Ben Murdochb8e0da22011-05-16 14:20:40 +01003328 heap_statistics->set_heap_size_limit(i::Heap::MaxReserved());
Steve Block3ce2e202009-11-05 08:53:23 +00003329}
3330
3331
3332bool v8::V8::IdleNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003333 // Returning true tells the caller that it need not
3334 // continue to call IdleNotification.
3335 if (!i::V8::IsRunning()) return true;
Steve Block3ce2e202009-11-05 08:53:23 +00003336 return i::V8::IdleNotification();
Steve Blocka7e24c12009-10-30 11:49:00 +00003337}
3338
3339
3340void v8::V8::LowMemoryNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00003341 if (!i::V8::IsRunning()) return;
3342 i::Heap::CollectAllGarbage(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00003343}
3344
3345
Steve Block6ded16b2010-05-10 14:33:55 +01003346int v8::V8::ContextDisposedNotification() {
3347 if (!i::V8::IsRunning()) return 0;
3348 return i::Heap::NotifyContextDisposed();
3349}
3350
3351
Steve Blocka7e24c12009-10-30 11:49:00 +00003352const char* v8::V8::GetVersion() {
3353 static v8::internal::EmbeddedVector<char, 128> buffer;
3354 v8::internal::Version::GetString(buffer);
3355 return buffer.start();
3356}
3357
3358
3359static i::Handle<i::FunctionTemplateInfo>
3360 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
3361 if (templ->constructor()->IsUndefined()) {
3362 Local<FunctionTemplate> constructor = FunctionTemplate::New();
3363 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
3364 templ->set_constructor(*Utils::OpenHandle(*constructor));
3365 }
3366 return i::Handle<i::FunctionTemplateInfo>(
3367 i::FunctionTemplateInfo::cast(templ->constructor()));
3368}
3369
3370
3371Persistent<Context> v8::Context::New(
3372 v8::ExtensionConfiguration* extensions,
3373 v8::Handle<ObjectTemplate> global_template,
3374 v8::Handle<Value> global_object) {
3375 EnsureInitialized("v8::Context::New()");
3376 LOG_API("Context::New");
3377 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
3378
3379 // Enter V8 via an ENTER_V8 scope.
3380 i::Handle<i::Context> env;
3381 {
3382 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003383 v8::Handle<ObjectTemplate> proxy_template = global_template;
3384 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
3385 i::Handle<i::FunctionTemplateInfo> global_constructor;
3386
3387 if (!global_template.IsEmpty()) {
3388 // Make sure that the global_template has a constructor.
3389 global_constructor =
3390 EnsureConstructor(Utils::OpenHandle(*global_template));
3391
3392 // Create a fresh template for the global proxy object.
3393 proxy_template = ObjectTemplate::New();
3394 proxy_constructor =
3395 EnsureConstructor(Utils::OpenHandle(*proxy_template));
3396
3397 // Set the global template to be the prototype template of
3398 // global proxy template.
3399 proxy_constructor->set_prototype_template(
3400 *Utils::OpenHandle(*global_template));
3401
3402 // Migrate security handlers from global_template to
3403 // proxy_template. Temporarily removing access check
3404 // information from the global template.
3405 if (!global_constructor->access_check_info()->IsUndefined()) {
3406 proxy_constructor->set_access_check_info(
3407 global_constructor->access_check_info());
3408 proxy_constructor->set_needs_access_check(
3409 global_constructor->needs_access_check());
3410 global_constructor->set_needs_access_check(false);
3411 global_constructor->set_access_check_info(i::Heap::undefined_value());
3412 }
3413 }
3414
3415 // Create the environment.
3416 env = i::Bootstrapper::CreateEnvironment(
3417 Utils::OpenHandle(*global_object),
3418 proxy_template,
3419 extensions);
3420
3421 // Restore the access check info on the global template.
3422 if (!global_template.IsEmpty()) {
3423 ASSERT(!global_constructor.is_null());
3424 ASSERT(!proxy_constructor.is_null());
3425 global_constructor->set_access_check_info(
3426 proxy_constructor->access_check_info());
3427 global_constructor->set_needs_access_check(
3428 proxy_constructor->needs_access_check());
3429 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01003430 i::RuntimeProfiler::Reset();
Steve Blocka7e24c12009-10-30 11:49:00 +00003431 }
3432 // Leave V8.
3433
3434 if (env.is_null())
3435 return Persistent<Context>();
3436 return Persistent<Context>(Utils::ToLocal(env));
3437}
3438
3439
3440void v8::Context::SetSecurityToken(Handle<Value> token) {
3441 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
3442 ENTER_V8;
3443 i::Handle<i::Context> env = Utils::OpenHandle(this);
3444 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
3445 env->set_security_token(*token_handle);
3446}
3447
3448
3449void v8::Context::UseDefaultSecurityToken() {
3450 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
3451 ENTER_V8;
3452 i::Handle<i::Context> env = Utils::OpenHandle(this);
3453 env->set_security_token(env->global());
3454}
3455
3456
3457Handle<Value> v8::Context::GetSecurityToken() {
3458 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
3459 i::Handle<i::Context> env = Utils::OpenHandle(this);
3460 i::Object* security_token = env->security_token();
3461 i::Handle<i::Object> token_handle(security_token);
3462 return Utils::ToLocal(token_handle);
3463}
3464
3465
3466bool Context::HasOutOfMemoryException() {
3467 i::Handle<i::Context> env = Utils::OpenHandle(this);
3468 return env->has_out_of_memory();
3469}
3470
3471
3472bool Context::InContext() {
3473 return i::Top::context() != NULL;
3474}
3475
3476
3477v8::Local<v8::Context> Context::GetEntered() {
3478 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
3479 i::Handle<i::Object> last = thread_local.LastEnteredContext();
3480 if (last.is_null()) return Local<Context>();
3481 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
3482 return Utils::ToLocal(context);
3483}
3484
3485
3486v8::Local<v8::Context> Context::GetCurrent() {
3487 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
Steve Block3ce2e202009-11-05 08:53:23 +00003488 i::Handle<i::Object> current = i::Top::global_context();
3489 if (current.is_null()) return Local<Context>();
3490 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
Steve Blocka7e24c12009-10-30 11:49:00 +00003491 return Utils::ToLocal(context);
3492}
3493
3494
3495v8::Local<v8::Context> Context::GetCalling() {
3496 if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
3497 i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
3498 if (calling.is_null()) return Local<Context>();
3499 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
3500 return Utils::ToLocal(context);
3501}
3502
3503
3504v8::Local<v8::Object> Context::Global() {
3505 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
3506 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3507 i::Handle<i::Context> context =
3508 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3509 i::Handle<i::Object> global(context->global_proxy());
3510 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
3511}
3512
3513
3514void Context::DetachGlobal() {
3515 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
3516 ENTER_V8;
3517 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3518 i::Handle<i::Context> context =
3519 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3520 i::Bootstrapper::DetachGlobal(context);
3521}
3522
3523
Andrei Popescu74b3c142010-03-29 12:03:09 +01003524void Context::ReattachGlobal(Handle<Object> global_object) {
3525 if (IsDeadCheck("v8::Context::ReattachGlobal()")) return;
3526 ENTER_V8;
3527 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3528 i::Handle<i::Context> context =
3529 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3530 i::Bootstrapper::ReattachGlobal(context, Utils::OpenHandle(*global_object));
3531}
3532
3533
Steve Blocka7e24c12009-10-30 11:49:00 +00003534Local<v8::Object> ObjectTemplate::NewInstance() {
3535 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
3536 LOG_API("ObjectTemplate::NewInstance");
3537 ENTER_V8;
3538 EXCEPTION_PREAMBLE();
3539 i::Handle<i::Object> obj =
3540 i::Execution::InstantiateObject(Utils::OpenHandle(this),
3541 &has_pending_exception);
3542 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
3543 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3544}
3545
3546
3547Local<v8::Function> FunctionTemplate::GetFunction() {
3548 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
3549 return Local<v8::Function>());
3550 LOG_API("FunctionTemplate::GetFunction");
3551 ENTER_V8;
3552 EXCEPTION_PREAMBLE();
3553 i::Handle<i::Object> obj =
3554 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3555 &has_pending_exception);
3556 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
3557 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3558}
3559
3560
3561bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3562 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
3563 i::Object* obj = *Utils::OpenHandle(*value);
3564 return obj->IsInstanceOf(*Utils::OpenHandle(this));
3565}
3566
3567
3568static Local<External> ExternalNewImpl(void* data) {
3569 return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
3570}
3571
3572static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3573 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3574}
3575
3576
Steve Blocka7e24c12009-10-30 11:49:00 +00003577Local<Value> v8::External::Wrap(void* data) {
3578 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3579 LOG_API("External::Wrap");
3580 EnsureInitialized("v8::External::Wrap()");
3581 ENTER_V8;
Ben Murdochb8e0da22011-05-16 14:20:40 +01003582
3583 v8::Local<v8::Value> result = CanBeEncodedAsSmi(data)
3584 ? Utils::ToLocal(i::Handle<i::Object>(EncodeAsSmi(data)))
3585 : v8::Local<v8::Value>(ExternalNewImpl(data));
3586
3587 ASSERT_EQ(data, Unwrap(result));
3588 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00003589}
3590
3591
Steve Block3ce2e202009-11-05 08:53:23 +00003592void* v8::Object::SlowGetPointerFromInternalField(int index) {
3593 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3594 i::Object* value = obj->GetInternalField(index);
3595 if (value->IsSmi()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01003596 return i::Internals::GetExternalPointerFromSmi(value);
Steve Block3ce2e202009-11-05 08:53:23 +00003597 } else if (value->IsProxy()) {
3598 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3599 } else {
3600 return NULL;
3601 }
3602}
3603
3604
Steve Blocka7e24c12009-10-30 11:49:00 +00003605void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3606 if (IsDeadCheck("v8::External::Unwrap()")) return 0;
3607 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3608 void* result;
3609 if (obj->IsSmi()) {
Ben Murdochb8e0da22011-05-16 14:20:40 +01003610 result = i::Internals::GetExternalPointerFromSmi(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003611 } else if (obj->IsProxy()) {
3612 result = ExternalValueImpl(obj);
3613 } else {
3614 result = NULL;
3615 }
3616 ASSERT_EQ(result, QuickUnwrap(wrapper));
3617 return result;
3618}
3619
3620
3621Local<External> v8::External::New(void* data) {
3622 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3623 LOG_API("External::New");
3624 EnsureInitialized("v8::External::New()");
3625 ENTER_V8;
3626 return ExternalNewImpl(data);
3627}
3628
3629
3630void* External::Value() const {
3631 if (IsDeadCheck("v8::External::Value()")) return 0;
3632 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3633 return ExternalValueImpl(obj);
3634}
3635
3636
3637Local<String> v8::String::Empty() {
3638 EnsureInitialized("v8::String::Empty()");
3639 LOG_API("String::Empty()");
3640 return Utils::ToLocal(i::Factory::empty_symbol());
3641}
3642
3643
3644Local<String> v8::String::New(const char* data, int length) {
3645 EnsureInitialized("v8::String::New()");
3646 LOG_API("String::New(char)");
3647 if (length == 0) return Empty();
3648 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003649 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003650 i::Handle<i::String> result =
3651 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3652 return Utils::ToLocal(result);
3653}
3654
3655
Steve Block3ce2e202009-11-05 08:53:23 +00003656Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3657 EnsureInitialized("v8::String::New()");
3658 LOG_API("String::New(char)");
3659 ENTER_V8;
3660 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3661 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3662 i::Handle<i::String> result = i::Factory::NewConsString(left_string,
3663 right_string);
3664 return Utils::ToLocal(result);
3665}
3666
3667
Steve Blocka7e24c12009-10-30 11:49:00 +00003668Local<String> v8::String::NewUndetectable(const char* data, int length) {
3669 EnsureInitialized("v8::String::NewUndetectable()");
3670 LOG_API("String::NewUndetectable(char)");
3671 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003672 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003673 i::Handle<i::String> result =
3674 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3675 result->MarkAsUndetectable();
3676 return Utils::ToLocal(result);
3677}
3678
3679
3680static int TwoByteStringLength(const uint16_t* data) {
3681 int length = 0;
3682 while (data[length] != '\0') length++;
3683 return length;
3684}
3685
3686
3687Local<String> v8::String::New(const uint16_t* data, int length) {
3688 EnsureInitialized("v8::String::New()");
3689 LOG_API("String::New(uint16_)");
3690 if (length == 0) return Empty();
3691 ENTER_V8;
3692 if (length == -1) length = TwoByteStringLength(data);
3693 i::Handle<i::String> result =
3694 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3695 return Utils::ToLocal(result);
3696}
3697
3698
3699Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
3700 EnsureInitialized("v8::String::NewUndetectable()");
3701 LOG_API("String::NewUndetectable(uint16_)");
3702 ENTER_V8;
3703 if (length == -1) length = TwoByteStringLength(data);
3704 i::Handle<i::String> result =
3705 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3706 result->MarkAsUndetectable();
3707 return Utils::ToLocal(result);
3708}
3709
3710
3711i::Handle<i::String> NewExternalStringHandle(
3712 v8::String::ExternalStringResource* resource) {
3713 i::Handle<i::String> result =
3714 i::Factory::NewExternalStringFromTwoByte(resource);
3715 return result;
3716}
3717
3718
3719i::Handle<i::String> NewExternalAsciiStringHandle(
3720 v8::String::ExternalAsciiStringResource* resource) {
3721 i::Handle<i::String> result =
3722 i::Factory::NewExternalStringFromAscii(resource);
3723 return result;
3724}
3725
3726
Steve Blocka7e24c12009-10-30 11:49:00 +00003727Local<String> v8::String::NewExternal(
3728 v8::String::ExternalStringResource* resource) {
3729 EnsureInitialized("v8::String::NewExternal()");
3730 LOG_API("String::NewExternal");
3731 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003732 i::Handle<i::String> result = NewExternalStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003733 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003734 return Utils::ToLocal(result);
3735}
3736
3737
3738bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3739 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3740 if (this->IsExternal()) return false; // Already an external string.
3741 ENTER_V8;
3742 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003743 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003744 bool result = obj->MakeExternal(resource);
3745 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003746 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003747 }
3748 return result;
3749}
3750
3751
3752Local<String> v8::String::NewExternal(
3753 v8::String::ExternalAsciiStringResource* resource) {
3754 EnsureInitialized("v8::String::NewExternal()");
3755 LOG_API("String::NewExternal");
3756 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003757 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003758 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003759 return Utils::ToLocal(result);
3760}
3761
3762
3763bool v8::String::MakeExternal(
3764 v8::String::ExternalAsciiStringResource* resource) {
3765 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3766 if (this->IsExternal()) return false; // Already an external string.
3767 ENTER_V8;
3768 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003769 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003770 bool result = obj->MakeExternal(resource);
3771 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003772 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003773 }
3774 return result;
3775}
3776
3777
3778bool v8::String::CanMakeExternal() {
3779 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3780 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003781 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003782 int size = obj->Size(); // Byte size of the original string.
3783 if (size < i::ExternalString::kSize)
3784 return false;
3785 i::StringShape shape(*obj);
3786 return !shape.IsExternal();
3787}
3788
3789
3790Local<v8::Object> v8::Object::New() {
3791 EnsureInitialized("v8::Object::New()");
3792 LOG_API("Object::New");
3793 ENTER_V8;
3794 i::Handle<i::JSObject> obj =
3795 i::Factory::NewJSObject(i::Top::object_function());
3796 return Utils::ToLocal(obj);
3797}
3798
3799
3800Local<v8::Value> v8::Date::New(double time) {
3801 EnsureInitialized("v8::Date::New()");
3802 LOG_API("Date::New");
Steve Blockd0582a62009-12-15 09:54:21 +00003803 if (isnan(time)) {
3804 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3805 time = i::OS::nan_value();
3806 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003807 ENTER_V8;
3808 EXCEPTION_PREAMBLE();
3809 i::Handle<i::Object> obj =
3810 i::Execution::NewDate(time, &has_pending_exception);
3811 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3812 return Utils::ToLocal(obj);
3813}
3814
3815
3816double v8::Date::NumberValue() const {
3817 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3818 LOG_API("Date::NumberValue");
3819 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3820 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3821 return jsvalue->value()->Number();
3822}
3823
3824
Ben Murdochb0fe1622011-05-05 13:52:32 +01003825void v8::Date::DateTimeConfigurationChangeNotification() {
3826 ON_BAILOUT("v8::Date::DateTimeConfigurationChangeNotification()", return);
3827 LOG_API("Date::DateTimeConfigurationChangeNotification");
3828 ENTER_V8;
3829
3830 HandleScope scope;
3831
3832 // Get the function ResetDateCache (defined in date-delay.js).
3833 i::Handle<i::String> func_name_str =
3834 i::Factory::LookupAsciiSymbol("ResetDateCache");
3835 i::MaybeObject* result = i::Top::builtins()->GetProperty(*func_name_str);
3836 i::Object* object_func;
3837 if (!result->ToObject(&object_func)) {
3838 return;
3839 }
3840
3841 if (object_func->IsJSFunction()) {
3842 i::Handle<i::JSFunction> func =
3843 i::Handle<i::JSFunction>(i::JSFunction::cast(object_func));
3844
3845 // Call ResetDateCache(0 but expect no exceptions:
3846 bool caught_exception = false;
3847 i::Handle<i::Object> result =
3848 i::Execution::TryCall(func, i::Top::builtins(), 0, NULL,
3849 &caught_exception);
3850 }
3851}
3852
3853
Ben Murdochf87a2032010-10-22 12:50:53 +01003854static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
3855 char flags_buf[3];
3856 int num_flags = 0;
3857 if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
3858 if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
3859 if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
3860 ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
3861 return i::Factory::LookupSymbol(
3862 i::Vector<const char>(flags_buf, num_flags));
3863}
3864
3865
3866Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
3867 Flags flags) {
3868 EnsureInitialized("v8::RegExp::New()");
3869 LOG_API("RegExp::New");
3870 ENTER_V8;
3871 EXCEPTION_PREAMBLE();
3872 i::Handle<i::JSRegExp> obj = i::Execution::NewJSRegExp(
3873 Utils::OpenHandle(*pattern),
3874 RegExpFlagsToString(flags),
3875 &has_pending_exception);
3876 EXCEPTION_BAILOUT_CHECK(Local<v8::RegExp>());
3877 return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
3878}
3879
3880
3881Local<v8::String> v8::RegExp::GetSource() const {
3882 if (IsDeadCheck("v8::RegExp::GetSource()")) return Local<v8::String>();
3883 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
3884 return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
3885}
3886
3887
3888// Assert that the static flags cast in GetFlags is valid.
3889#define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \
3890 STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \
3891 static_cast<int>(i::JSRegExp::internal_flag))
3892REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
3893REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
3894REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
3895REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
3896#undef REGEXP_FLAG_ASSERT_EQ
3897
3898v8::RegExp::Flags v8::RegExp::GetFlags() const {
3899 if (IsDeadCheck("v8::RegExp::GetFlags()")) return v8::RegExp::kNone;
3900 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
3901 return static_cast<RegExp::Flags>(obj->GetFlags().value());
3902}
3903
3904
Steve Blocka7e24c12009-10-30 11:49:00 +00003905Local<v8::Array> v8::Array::New(int length) {
3906 EnsureInitialized("v8::Array::New()");
3907 LOG_API("Array::New");
3908 ENTER_V8;
3909 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3910 return Utils::ToLocal(obj);
3911}
3912
3913
3914uint32_t v8::Array::Length() const {
3915 if (IsDeadCheck("v8::Array::Length()")) return 0;
3916 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3917 i::Object* length = obj->length();
3918 if (length->IsSmi()) {
3919 return i::Smi::cast(length)->value();
3920 } else {
3921 return static_cast<uint32_t>(length->Number());
3922 }
3923}
3924
3925
3926Local<Object> Array::CloneElementAt(uint32_t index) {
3927 ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3928 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3929 if (!self->HasFastElements()) {
3930 return Local<Object>();
3931 }
3932 i::FixedArray* elms = i::FixedArray::cast(self->elements());
3933 i::Object* paragon = elms->get(index);
3934 if (!paragon->IsJSObject()) {
3935 return Local<Object>();
3936 }
3937 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3938 EXCEPTION_PREAMBLE();
Steve Block6ded16b2010-05-10 14:33:55 +01003939 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003940 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3941 has_pending_exception = result.is_null();
3942 EXCEPTION_BAILOUT_CHECK(Local<Object>());
3943 return Utils::ToLocal(result);
3944}
3945
3946
3947Local<String> v8::String::NewSymbol(const char* data, int length) {
3948 EnsureInitialized("v8::String::NewSymbol()");
3949 LOG_API("String::NewSymbol(char)");
3950 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003951 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003952 i::Handle<i::String> result =
3953 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3954 return Utils::ToLocal(result);
3955}
3956
3957
3958Local<Number> v8::Number::New(double value) {
3959 EnsureInitialized("v8::Number::New()");
Steve Blockd0582a62009-12-15 09:54:21 +00003960 if (isnan(value)) {
3961 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3962 value = i::OS::nan_value();
3963 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003964 ENTER_V8;
3965 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3966 return Utils::NumberToLocal(result);
3967}
3968
3969
3970Local<Integer> v8::Integer::New(int32_t value) {
3971 EnsureInitialized("v8::Integer::New()");
3972 if (i::Smi::IsValid(value)) {
3973 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3974 }
3975 ENTER_V8;
3976 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3977 return Utils::IntegerToLocal(result);
3978}
3979
3980
Steve Block3ce2e202009-11-05 08:53:23 +00003981Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
3982 bool fits_into_int32_t = (value & (1 << 31)) == 0;
3983 if (fits_into_int32_t) {
3984 return Integer::New(static_cast<int32_t>(value));
3985 }
3986 ENTER_V8;
3987 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3988 return Utils::IntegerToLocal(result);
3989}
3990
3991
Steve Blocka7e24c12009-10-30 11:49:00 +00003992void V8::IgnoreOutOfMemoryException() {
3993 thread_local.set_ignore_out_of_memory(true);
3994}
3995
3996
3997bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
3998 EnsureInitialized("v8::V8::AddMessageListener()");
3999 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
4000 ENTER_V8;
4001 HandleScope scope;
4002 NeanderArray listeners(i::Factory::message_listeners());
4003 NeanderObject obj(2);
4004 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
4005 obj.set(1, data.IsEmpty() ?
4006 i::Heap::undefined_value() :
4007 *Utils::OpenHandle(*data));
4008 listeners.add(obj.value());
4009 return true;
4010}
4011
4012
4013void V8::RemoveMessageListeners(MessageCallback that) {
4014 EnsureInitialized("v8::V8::RemoveMessageListener()");
4015 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
4016 ENTER_V8;
4017 HandleScope scope;
4018 NeanderArray listeners(i::Factory::message_listeners());
4019 for (int i = 0; i < listeners.length(); i++) {
4020 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
4021
4022 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
4023 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
4024 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
4025 listeners.set(i, i::Heap::undefined_value());
4026 }
4027 }
4028}
4029
4030
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004031void V8::SetCaptureStackTraceForUncaughtExceptions(
4032 bool capture,
4033 int frame_limit,
4034 StackTrace::StackTraceOptions options) {
4035 i::Top::SetCaptureStackTraceForUncaughtExceptions(
4036 capture,
4037 frame_limit,
4038 options);
4039}
4040
4041
Steve Blocka7e24c12009-10-30 11:49:00 +00004042void V8::SetCounterFunction(CounterLookupCallback callback) {
4043 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
4044 i::StatsTable::SetCounterFunction(callback);
4045}
4046
4047void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
4048 if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
4049 i::StatsTable::SetCreateHistogramFunction(callback);
4050}
4051
4052void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
4053 if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
4054 i::StatsTable::SetAddHistogramSampleFunction(callback);
4055}
4056
4057void V8::EnableSlidingStateWindow() {
4058 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
4059 i::Logger::EnableSlidingStateWindow();
4060}
4061
4062
4063void V8::SetFailedAccessCheckCallbackFunction(
4064 FailedAccessCheckCallback callback) {
4065 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
4066 i::Top::SetFailedAccessCheckCallback(callback);
4067}
4068
4069
4070void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
4071 if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
4072 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
4073 i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
4074}
4075
4076
4077int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
4078 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
4079 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
4080}
4081
4082
4083void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
4084 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
4085 i::Heap::SetGlobalGCPrologueCallback(callback);
4086}
4087
4088
4089void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
4090 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
4091 i::Heap::SetGlobalGCEpilogueCallback(callback);
4092}
4093
4094
Steve Block6ded16b2010-05-10 14:33:55 +01004095void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
4096 if (IsDeadCheck("v8::V8::AddGCPrologueCallback()")) return;
4097 i::Heap::AddGCPrologueCallback(callback, gc_type);
4098}
4099
4100
4101void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
4102 if (IsDeadCheck("v8::V8::RemoveGCPrologueCallback()")) return;
4103 i::Heap::RemoveGCPrologueCallback(callback);
4104}
4105
4106
4107void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
4108 if (IsDeadCheck("v8::V8::AddGCEpilogueCallback()")) return;
4109 i::Heap::AddGCEpilogueCallback(callback, gc_type);
4110}
4111
4112
4113void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
4114 if (IsDeadCheck("v8::V8::RemoveGCEpilogueCallback()")) return;
4115 i::Heap::RemoveGCEpilogueCallback(callback);
4116}
4117
4118
Iain Merrick9ac36c92010-09-13 15:29:50 +01004119void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
4120 ObjectSpace space,
4121 AllocationAction action) {
4122 if (IsDeadCheck("v8::V8::AddMemoryAllocationCallback()")) return;
4123 i::MemoryAllocator::AddMemoryAllocationCallback(callback,
4124 space,
4125 action);
4126}
4127
4128
4129void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
4130 if (IsDeadCheck("v8::V8::RemoveMemoryAllocationCallback()")) return;
4131 i::MemoryAllocator::RemoveMemoryAllocationCallback(callback);
4132}
4133
4134
Steve Blocka7e24c12009-10-30 11:49:00 +00004135void V8::PauseProfiler() {
4136#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004137 PauseProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00004138#endif
4139}
4140
4141
4142void V8::ResumeProfiler() {
4143#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004144 ResumeProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00004145#endif
4146}
4147
4148
4149bool V8::IsProfilerPaused() {
4150#ifdef ENABLE_LOGGING_AND_PROFILING
4151 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
4152#else
4153 return true;
4154#endif
4155}
4156
4157
Andrei Popescu402d9372010-02-26 13:31:12 +00004158void V8::ResumeProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004159#ifdef ENABLE_LOGGING_AND_PROFILING
4160 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
4161 // Snapshot mode: resume modules, perform GC, then pause only
4162 // those modules which haven't been started prior to making a
4163 // snapshot.
4164
Steve Block6ded16b2010-05-10 14:33:55 +01004165 // Make a GC prior to taking a snapshot.
4166 i::Heap::CollectAllGarbage(false);
Steve Blocka7e24c12009-10-30 11:49:00 +00004167 // Reset snapshot flag and CPU module flags.
4168 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
4169 const int current_flags = i::Logger::GetActiveProfilerModules();
Andrei Popescu402d9372010-02-26 13:31:12 +00004170 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004171 i::Heap::CollectAllGarbage(false);
Andrei Popescu402d9372010-02-26 13:31:12 +00004172 i::Logger::PauseProfiler(~current_flags & flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004173 } else {
Andrei Popescu402d9372010-02-26 13:31:12 +00004174 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004175 }
4176#endif
4177}
4178
4179
Andrei Popescu402d9372010-02-26 13:31:12 +00004180void V8::PauseProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00004181#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00004182 i::Logger::PauseProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00004183#endif
4184}
4185
4186
4187int V8::GetActiveProfilerModules() {
4188#ifdef ENABLE_LOGGING_AND_PROFILING
4189 return i::Logger::GetActiveProfilerModules();
4190#else
4191 return PROFILER_MODULE_NONE;
4192#endif
4193}
4194
4195
4196int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
4197#ifdef ENABLE_LOGGING_AND_PROFILING
Steve Block6ded16b2010-05-10 14:33:55 +01004198 ASSERT(max_size >= kMinimumSizeForLogLinesBuffer);
Steve Blocka7e24c12009-10-30 11:49:00 +00004199 return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
4200#endif
4201 return 0;
4202}
4203
4204
4205int V8::GetCurrentThreadId() {
4206 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
4207 EnsureInitialized("V8::GetCurrentThreadId()");
4208 return i::Top::thread_id();
4209}
4210
4211
4212void V8::TerminateExecution(int thread_id) {
4213 if (!i::V8::IsRunning()) return;
4214 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
4215 // If the thread_id identifies the current thread just terminate
4216 // execution right away. Otherwise, ask the thread manager to
4217 // terminate the thread with the given id if any.
4218 if (thread_id == i::Top::thread_id()) {
4219 i::StackGuard::TerminateExecution();
4220 } else {
4221 i::ThreadManager::TerminateExecution(thread_id);
4222 }
4223}
4224
4225
4226void V8::TerminateExecution() {
4227 if (!i::V8::IsRunning()) return;
4228 i::StackGuard::TerminateExecution();
4229}
4230
4231
Steve Block6ded16b2010-05-10 14:33:55 +01004232bool V8::IsExecutionTerminating() {
4233 if (!i::V8::IsRunning()) return false;
4234 if (i::Top::has_scheduled_exception()) {
4235 return i::Top::scheduled_exception() == i::Heap::termination_exception();
4236 }
4237 return false;
4238}
4239
4240
Steve Blocka7e24c12009-10-30 11:49:00 +00004241String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
4242 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
4243 if (obj.IsEmpty()) {
4244 str_ = NULL;
4245 length_ = 0;
4246 return;
4247 }
4248 ENTER_V8;
4249 HandleScope scope;
4250 TryCatch try_catch;
4251 Handle<String> str = obj->ToString();
4252 if (str.IsEmpty()) {
4253 str_ = NULL;
4254 length_ = 0;
4255 } else {
4256 length_ = str->Utf8Length();
4257 str_ = i::NewArray<char>(length_ + 1);
4258 str->WriteUtf8(str_);
4259 }
4260}
4261
4262
4263String::Utf8Value::~Utf8Value() {
4264 i::DeleteArray(str_);
4265}
4266
4267
4268String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
4269 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
4270 if (obj.IsEmpty()) {
4271 str_ = NULL;
4272 length_ = 0;
4273 return;
4274 }
4275 ENTER_V8;
4276 HandleScope scope;
4277 TryCatch try_catch;
4278 Handle<String> str = obj->ToString();
4279 if (str.IsEmpty()) {
4280 str_ = NULL;
4281 length_ = 0;
4282 } else {
4283 length_ = str->Length();
4284 str_ = i::NewArray<char>(length_ + 1);
4285 str->WriteAscii(str_);
4286 }
4287}
4288
4289
4290String::AsciiValue::~AsciiValue() {
4291 i::DeleteArray(str_);
4292}
4293
4294
4295String::Value::Value(v8::Handle<v8::Value> obj) {
4296 EnsureInitialized("v8::String::Value::Value()");
4297 if (obj.IsEmpty()) {
4298 str_ = NULL;
4299 length_ = 0;
4300 return;
4301 }
4302 ENTER_V8;
4303 HandleScope scope;
4304 TryCatch try_catch;
4305 Handle<String> str = obj->ToString();
4306 if (str.IsEmpty()) {
4307 str_ = NULL;
4308 length_ = 0;
4309 } else {
4310 length_ = str->Length();
4311 str_ = i::NewArray<uint16_t>(length_ + 1);
4312 str->Write(str_);
4313 }
4314}
4315
4316
4317String::Value::~Value() {
4318 i::DeleteArray(str_);
4319}
4320
4321Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
4322 LOG_API("RangeError");
4323 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
4324 ENTER_V8;
4325 i::Object* error;
4326 {
4327 HandleScope scope;
4328 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4329 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
4330 error = *result;
4331 }
4332 i::Handle<i::Object> result(error);
4333 return Utils::ToLocal(result);
4334}
4335
4336Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
4337 LOG_API("ReferenceError");
4338 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
4339 ENTER_V8;
4340 i::Object* error;
4341 {
4342 HandleScope scope;
4343 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4344 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
4345 error = *result;
4346 }
4347 i::Handle<i::Object> result(error);
4348 return Utils::ToLocal(result);
4349}
4350
4351Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
4352 LOG_API("SyntaxError");
4353 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
4354 ENTER_V8;
4355 i::Object* error;
4356 {
4357 HandleScope scope;
4358 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4359 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
4360 error = *result;
4361 }
4362 i::Handle<i::Object> result(error);
4363 return Utils::ToLocal(result);
4364}
4365
4366Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
4367 LOG_API("TypeError");
4368 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
4369 ENTER_V8;
4370 i::Object* error;
4371 {
4372 HandleScope scope;
4373 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4374 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
4375 error = *result;
4376 }
4377 i::Handle<i::Object> result(error);
4378 return Utils::ToLocal(result);
4379}
4380
4381Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
4382 LOG_API("Error");
4383 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
4384 ENTER_V8;
4385 i::Object* error;
4386 {
4387 HandleScope scope;
4388 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
4389 i::Handle<i::Object> result = i::Factory::NewError(message);
4390 error = *result;
4391 }
4392 i::Handle<i::Object> result(error);
4393 return Utils::ToLocal(result);
4394}
4395
4396
4397// --- D e b u g S u p p o r t ---
4398
4399#ifdef ENABLE_DEBUGGER_SUPPORT
Leon Clarkef7060e22010-06-03 12:02:55 +01004400
4401static v8::Debug::EventCallback event_callback = NULL;
4402
4403static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) {
4404 if (event_callback) {
4405 event_callback(event_details.GetEvent(),
4406 event_details.GetExecutionState(),
4407 event_details.GetEventData(),
4408 event_details.GetCallbackData());
4409 }
4410}
4411
4412
Steve Blocka7e24c12009-10-30 11:49:00 +00004413bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
4414 EnsureInitialized("v8::Debug::SetDebugEventListener()");
4415 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4416 ENTER_V8;
Leon Clarkef7060e22010-06-03 12:02:55 +01004417
4418 event_callback = that;
4419
4420 HandleScope scope;
4421 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4422 if (that != NULL) {
4423 proxy = i::Factory::NewProxy(FUNCTION_ADDR(EventCallbackWrapper));
4424 }
4425 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4426 return true;
4427}
4428
4429
4430bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
4431 EnsureInitialized("v8::Debug::SetDebugEventListener2()");
4432 ON_BAILOUT("v8::Debug::SetDebugEventListener2()", return false);
4433 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004434 HandleScope scope;
4435 i::Handle<i::Object> proxy = i::Factory::undefined_value();
4436 if (that != NULL) {
4437 proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
4438 }
4439 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
4440 return true;
4441}
4442
4443
4444bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
4445 Handle<Value> data) {
4446 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
4447 ENTER_V8;
4448 i::Debugger::SetEventListener(Utils::OpenHandle(*that),
4449 Utils::OpenHandle(*data));
4450 return true;
4451}
4452
4453
4454void Debug::DebugBreak() {
4455 if (!i::V8::IsRunning()) return;
4456 i::StackGuard::DebugBreak();
4457}
4458
4459
Ben Murdochf87a2032010-10-22 12:50:53 +01004460void Debug::CancelDebugBreak() {
4461 i::StackGuard::Continue(i::DEBUGBREAK);
4462}
4463
4464
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004465void Debug::DebugBreakForCommand(ClientData* data) {
4466 if (!i::V8::IsRunning()) return;
4467 i::Debugger::EnqueueDebugCommand(data);
4468}
4469
4470
Steve Blocka7e24c12009-10-30 11:49:00 +00004471static v8::Debug::MessageHandler message_handler = NULL;
4472
4473static void MessageHandlerWrapper(const v8::Debug::Message& message) {
4474 if (message_handler) {
4475 v8::String::Value json(message.GetJSON());
4476 message_handler(*json, json.length(), message.GetClientData());
4477 }
4478}
4479
4480
4481void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
4482 bool message_handler_thread) {
4483 EnsureInitialized("v8::Debug::SetMessageHandler");
4484 ENTER_V8;
4485 // Message handler thread not supported any more. Parameter temporally left in
4486 // the API for client compatability reasons.
4487 CHECK(!message_handler_thread);
4488
4489 // TODO(sgjesse) support the old message handler API through a simple wrapper.
4490 message_handler = handler;
4491 if (message_handler != NULL) {
4492 i::Debugger::SetMessageHandler(MessageHandlerWrapper);
4493 } else {
4494 i::Debugger::SetMessageHandler(NULL);
4495 }
4496}
4497
4498
4499void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
4500 EnsureInitialized("v8::Debug::SetMessageHandler");
4501 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00004502 i::Debugger::SetMessageHandler(handler);
4503}
4504
4505
4506void Debug::SendCommand(const uint16_t* command, int length,
4507 ClientData* client_data) {
4508 if (!i::V8::IsRunning()) return;
4509 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
4510 client_data);
4511}
4512
4513
4514void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
4515 int period) {
4516 EnsureInitialized("v8::Debug::SetHostDispatchHandler");
4517 ENTER_V8;
4518 i::Debugger::SetHostDispatchHandler(handler, period);
4519}
4520
4521
Steve Blockd0582a62009-12-15 09:54:21 +00004522void Debug::SetDebugMessageDispatchHandler(
Leon Clarkee46be812010-01-19 14:06:41 +00004523 DebugMessageDispatchHandler handler, bool provide_locker) {
Steve Blockd0582a62009-12-15 09:54:21 +00004524 EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
4525 ENTER_V8;
Leon Clarkee46be812010-01-19 14:06:41 +00004526 i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
Steve Blockd0582a62009-12-15 09:54:21 +00004527}
4528
4529
Steve Blocka7e24c12009-10-30 11:49:00 +00004530Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
4531 v8::Handle<v8::Value> data) {
4532 if (!i::V8::IsRunning()) return Local<Value>();
4533 ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
4534 ENTER_V8;
4535 i::Handle<i::Object> result;
4536 EXCEPTION_PREAMBLE();
4537 if (data.IsEmpty()) {
4538 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4539 i::Factory::undefined_value(),
4540 &has_pending_exception);
4541 } else {
4542 result = i::Debugger::Call(Utils::OpenHandle(*fun),
4543 Utils::OpenHandle(*data),
4544 &has_pending_exception);
4545 }
4546 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4547 return Utils::ToLocal(result);
4548}
4549
4550
4551Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
4552 if (!i::V8::IsRunning()) return Local<Value>();
4553 ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
4554 ENTER_V8;
4555 v8::HandleScope scope;
4556 i::Debug::Load();
4557 i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
4558 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
4559 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
4560 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
4561 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
4562 const int kArgc = 1;
4563 v8::Handle<v8::Value> argv[kArgc] = { obj };
4564 EXCEPTION_PREAMBLE();
4565 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
4566 kArgc,
4567 argv);
4568 EXCEPTION_BAILOUT_CHECK(Local<Value>());
4569 return scope.Close(result);
4570}
4571
4572
Leon Clarkee46be812010-01-19 14:06:41 +00004573bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
4574 return i::Debugger::StartAgent(name, port, wait_for_connection);
Steve Blocka7e24c12009-10-30 11:49:00 +00004575}
Leon Clarkee46be812010-01-19 14:06:41 +00004576
4577void Debug::ProcessDebugMessages() {
4578 i::Execution::ProcessDebugMesssages(true);
4579}
4580
Steve Block6ded16b2010-05-10 14:33:55 +01004581Local<Context> Debug::GetDebugContext() {
4582 EnsureInitialized("v8::Debug::GetDebugContext()");
4583 ENTER_V8;
4584 return Utils::ToLocal(i::Debugger::GetDebugContext());
4585}
4586
Steve Blocka7e24c12009-10-30 11:49:00 +00004587#endif // ENABLE_DEBUGGER_SUPPORT
4588
Steve Block6ded16b2010-05-10 14:33:55 +01004589
4590#ifdef ENABLE_LOGGING_AND_PROFILING
4591
4592Handle<String> CpuProfileNode::GetFunctionName() const {
4593 IsDeadCheck("v8::CpuProfileNode::GetFunctionName");
4594 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4595 const i::CodeEntry* entry = node->entry();
4596 if (!entry->has_name_prefix()) {
4597 return Handle<String>(ToApi<String>(
4598 i::Factory::LookupAsciiSymbol(entry->name())));
4599 } else {
4600 return Handle<String>(ToApi<String>(i::Factory::NewConsString(
4601 i::Factory::LookupAsciiSymbol(entry->name_prefix()),
4602 i::Factory::LookupAsciiSymbol(entry->name()))));
4603 }
4604}
4605
4606
4607Handle<String> CpuProfileNode::GetScriptResourceName() const {
4608 IsDeadCheck("v8::CpuProfileNode::GetScriptResourceName");
4609 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
4610 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4611 node->entry()->resource_name())));
4612}
4613
4614
4615int CpuProfileNode::GetLineNumber() const {
4616 IsDeadCheck("v8::CpuProfileNode::GetLineNumber");
4617 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
4618}
4619
4620
4621double CpuProfileNode::GetTotalTime() const {
4622 IsDeadCheck("v8::CpuProfileNode::GetTotalTime");
4623 return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis();
4624}
4625
4626
4627double CpuProfileNode::GetSelfTime() const {
4628 IsDeadCheck("v8::CpuProfileNode::GetSelfTime");
4629 return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis();
4630}
4631
4632
4633double CpuProfileNode::GetTotalSamplesCount() const {
4634 IsDeadCheck("v8::CpuProfileNode::GetTotalSamplesCount");
4635 return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
4636}
4637
4638
4639double CpuProfileNode::GetSelfSamplesCount() const {
4640 IsDeadCheck("v8::CpuProfileNode::GetSelfSamplesCount");
4641 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
4642}
4643
4644
4645unsigned CpuProfileNode::GetCallUid() const {
4646 IsDeadCheck("v8::CpuProfileNode::GetCallUid");
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004647 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
Steve Block6ded16b2010-05-10 14:33:55 +01004648}
4649
4650
4651int CpuProfileNode::GetChildrenCount() const {
4652 IsDeadCheck("v8::CpuProfileNode::GetChildrenCount");
4653 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
4654}
4655
4656
4657const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
4658 IsDeadCheck("v8::CpuProfileNode::GetChild");
4659 const i::ProfileNode* child =
4660 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
4661 return reinterpret_cast<const CpuProfileNode*>(child);
4662}
4663
4664
4665unsigned CpuProfile::GetUid() const {
4666 IsDeadCheck("v8::CpuProfile::GetUid");
4667 return reinterpret_cast<const i::CpuProfile*>(this)->uid();
4668}
4669
4670
4671Handle<String> CpuProfile::GetTitle() const {
4672 IsDeadCheck("v8::CpuProfile::GetTitle");
4673 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4674 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4675 profile->title())));
4676}
4677
4678
4679const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
4680 IsDeadCheck("v8::CpuProfile::GetBottomUpRoot");
4681 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4682 return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
4683}
4684
4685
4686const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
4687 IsDeadCheck("v8::CpuProfile::GetTopDownRoot");
4688 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
4689 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
4690}
4691
4692
4693int CpuProfiler::GetProfilesCount() {
4694 IsDeadCheck("v8::CpuProfiler::GetProfilesCount");
4695 return i::CpuProfiler::GetProfilesCount();
4696}
4697
4698
Leon Clarkef7060e22010-06-03 12:02:55 +01004699const CpuProfile* CpuProfiler::GetProfile(int index,
4700 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004701 IsDeadCheck("v8::CpuProfiler::GetProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004702 return reinterpret_cast<const CpuProfile*>(
4703 i::CpuProfiler::GetProfile(
4704 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4705 index));
Steve Block6ded16b2010-05-10 14:33:55 +01004706}
4707
4708
Leon Clarkef7060e22010-06-03 12:02:55 +01004709const CpuProfile* CpuProfiler::FindProfile(unsigned uid,
4710 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004711 IsDeadCheck("v8::CpuProfiler::FindProfile");
Leon Clarkef7060e22010-06-03 12:02:55 +01004712 return reinterpret_cast<const CpuProfile*>(
4713 i::CpuProfiler::FindProfile(
4714 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4715 uid));
Steve Block6ded16b2010-05-10 14:33:55 +01004716}
4717
4718
4719void CpuProfiler::StartProfiling(Handle<String> title) {
4720 IsDeadCheck("v8::CpuProfiler::StartProfiling");
4721 i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
4722}
4723
4724
Leon Clarkef7060e22010-06-03 12:02:55 +01004725const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title,
4726 Handle<Value> security_token) {
Steve Block6ded16b2010-05-10 14:33:55 +01004727 IsDeadCheck("v8::CpuProfiler::StopProfiling");
4728 return reinterpret_cast<const CpuProfile*>(
Leon Clarkef7060e22010-06-03 12:02:55 +01004729 i::CpuProfiler::StopProfiling(
4730 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
4731 *Utils::OpenHandle(*title)));
Steve Block6ded16b2010-05-10 14:33:55 +01004732}
4733
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004734
Iain Merrick75681382010-08-19 15:07:18 +01004735static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
4736 return const_cast<i::HeapGraphEdge*>(
4737 reinterpret_cast<const i::HeapGraphEdge*>(edge));
4738}
4739
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004740HeapGraphEdge::Type HeapGraphEdge::GetType() const {
4741 IsDeadCheck("v8::HeapGraphEdge::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004742 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004743}
4744
4745
4746Handle<Value> HeapGraphEdge::GetName() const {
4747 IsDeadCheck("v8::HeapGraphEdge::GetName");
Iain Merrick75681382010-08-19 15:07:18 +01004748 i::HeapGraphEdge* edge = ToInternal(this);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004749 switch (edge->type()) {
Iain Merrick75681382010-08-19 15:07:18 +01004750 case i::HeapGraphEdge::kContextVariable:
4751 case i::HeapGraphEdge::kInternal:
4752 case i::HeapGraphEdge::kProperty:
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004753 case i::HeapGraphEdge::kShortcut:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004754 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
4755 edge->name())));
Iain Merrick75681382010-08-19 15:07:18 +01004756 case i::HeapGraphEdge::kElement:
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004757 case i::HeapGraphEdge::kHidden:
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004758 return Handle<Number>(ToApi<Number>(i::Factory::NewNumberFromInt(
4759 edge->index())));
4760 default: UNREACHABLE();
4761 }
4762 return ImplementationUtilities::Undefined();
4763}
4764
4765
4766const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
4767 IsDeadCheck("v8::HeapGraphEdge::GetFromNode");
Iain Merrick75681382010-08-19 15:07:18 +01004768 const i::HeapEntry* from = ToInternal(this)->From();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004769 return reinterpret_cast<const HeapGraphNode*>(from);
4770}
4771
4772
4773const HeapGraphNode* HeapGraphEdge::GetToNode() const {
4774 IsDeadCheck("v8::HeapGraphEdge::GetToNode");
Iain Merrick75681382010-08-19 15:07:18 +01004775 const i::HeapEntry* to = ToInternal(this)->to();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004776 return reinterpret_cast<const HeapGraphNode*>(to);
4777}
4778
4779
Iain Merrick75681382010-08-19 15:07:18 +01004780static i::HeapGraphPath* ToInternal(const HeapGraphPath* path) {
4781 return const_cast<i::HeapGraphPath*>(
4782 reinterpret_cast<const i::HeapGraphPath*>(path));
4783}
4784
4785
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004786int HeapGraphPath::GetEdgesCount() const {
Iain Merrick75681382010-08-19 15:07:18 +01004787 return ToInternal(this)->path()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004788}
4789
4790
4791const HeapGraphEdge* HeapGraphPath::GetEdge(int index) const {
4792 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004793 ToInternal(this)->path()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004794}
4795
4796
4797const HeapGraphNode* HeapGraphPath::GetFromNode() const {
4798 return GetEdgesCount() > 0 ? GetEdge(0)->GetFromNode() : NULL;
4799}
4800
4801
4802const HeapGraphNode* HeapGraphPath::GetToNode() const {
4803 const int count = GetEdgesCount();
4804 return count > 0 ? GetEdge(count - 1)->GetToNode() : NULL;
4805}
4806
4807
Iain Merrick75681382010-08-19 15:07:18 +01004808static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
4809 return const_cast<i::HeapEntry*>(
4810 reinterpret_cast<const i::HeapEntry*>(entry));
4811}
4812
4813
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004814HeapGraphNode::Type HeapGraphNode::GetType() const {
4815 IsDeadCheck("v8::HeapGraphNode::GetType");
Iain Merrick75681382010-08-19 15:07:18 +01004816 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004817}
4818
4819
4820Handle<String> HeapGraphNode::GetName() const {
4821 IsDeadCheck("v8::HeapGraphNode::GetName");
4822 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004823 ToInternal(this)->name())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004824}
4825
4826
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004827uint64_t HeapGraphNode::GetId() const {
4828 IsDeadCheck("v8::HeapGraphNode::GetId");
Steve Block791712a2010-08-27 10:21:07 +01004829 ASSERT(ToInternal(this)->snapshot()->type() != i::HeapSnapshot::kAggregated);
Iain Merrick75681382010-08-19 15:07:18 +01004830 return ToInternal(this)->id();
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004831}
4832
4833
Steve Block791712a2010-08-27 10:21:07 +01004834int HeapGraphNode::GetInstancesCount() const {
4835 IsDeadCheck("v8::HeapGraphNode::GetInstancesCount");
4836 ASSERT(ToInternal(this)->snapshot()->type() == i::HeapSnapshot::kAggregated);
4837 return static_cast<int>(ToInternal(this)->id());
4838}
4839
4840
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004841int HeapGraphNode::GetSelfSize() const {
4842 IsDeadCheck("v8::HeapGraphNode::GetSelfSize");
Iain Merrick75681382010-08-19 15:07:18 +01004843 return ToInternal(this)->self_size();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004844}
4845
4846
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004847int HeapGraphNode::GetRetainedSize(bool exact) const {
Iain Merrick75681382010-08-19 15:07:18 +01004848 IsDeadCheck("v8::HeapSnapshot::GetRetainedSize");
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004849 return ToInternal(this)->RetainedSize(exact);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004850}
4851
4852
4853int HeapGraphNode::GetChildrenCount() const {
4854 IsDeadCheck("v8::HeapSnapshot::GetChildrenCount");
Iain Merrick75681382010-08-19 15:07:18 +01004855 return ToInternal(this)->children().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004856}
4857
4858
4859const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
4860 IsDeadCheck("v8::HeapSnapshot::GetChild");
4861 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004862 &ToInternal(this)->children()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004863}
4864
4865
4866int HeapGraphNode::GetRetainersCount() const {
4867 IsDeadCheck("v8::HeapSnapshot::GetRetainersCount");
Iain Merrick75681382010-08-19 15:07:18 +01004868 return ToInternal(this)->retainers().length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004869}
4870
4871
4872const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const {
4873 IsDeadCheck("v8::HeapSnapshot::GetRetainer");
4874 return reinterpret_cast<const HeapGraphEdge*>(
Iain Merrick75681382010-08-19 15:07:18 +01004875 ToInternal(this)->retainers()[index]);
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004876}
4877
4878
4879int HeapGraphNode::GetRetainingPathsCount() const {
4880 IsDeadCheck("v8::HeapSnapshot::GetRetainingPathsCount");
Iain Merrick75681382010-08-19 15:07:18 +01004881 return ToInternal(this)->GetRetainingPaths()->length();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004882}
4883
4884
4885const HeapGraphPath* HeapGraphNode::GetRetainingPath(int index) const {
4886 IsDeadCheck("v8::HeapSnapshot::GetRetainingPath");
4887 return reinterpret_cast<const HeapGraphPath*>(
Iain Merrick75681382010-08-19 15:07:18 +01004888 ToInternal(this)->GetRetainingPaths()->at(index));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004889}
4890
4891
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -08004892const HeapGraphNode* HeapGraphNode::GetDominatorNode() const {
4893 IsDeadCheck("v8::HeapSnapshot::GetDominatorNode");
4894 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->dominator());
4895}
4896
4897
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004898const HeapGraphNode* HeapSnapshotsDiff::GetAdditionsRoot() const {
4899 IsDeadCheck("v8::HeapSnapshotsDiff::GetAdditionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004900 i::HeapSnapshotsDiff* diff =
4901 const_cast<i::HeapSnapshotsDiff*>(
4902 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004903 return reinterpret_cast<const HeapGraphNode*>(diff->additions_root());
4904}
4905
4906
4907const HeapGraphNode* HeapSnapshotsDiff::GetDeletionsRoot() const {
4908 IsDeadCheck("v8::HeapSnapshotsDiff::GetDeletionsRoot");
Iain Merrick75681382010-08-19 15:07:18 +01004909 i::HeapSnapshotsDiff* diff =
4910 const_cast<i::HeapSnapshotsDiff*>(
4911 reinterpret_cast<const i::HeapSnapshotsDiff*>(this));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004912 return reinterpret_cast<const HeapGraphNode*>(diff->deletions_root());
4913}
4914
4915
Iain Merrick75681382010-08-19 15:07:18 +01004916static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
4917 return const_cast<i::HeapSnapshot*>(
4918 reinterpret_cast<const i::HeapSnapshot*>(snapshot));
4919}
4920
4921
Steve Block791712a2010-08-27 10:21:07 +01004922HeapSnapshot::Type HeapSnapshot::GetType() const {
4923 IsDeadCheck("v8::HeapSnapshot::GetType");
4924 return static_cast<HeapSnapshot::Type>(ToInternal(this)->type());
4925}
4926
4927
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004928unsigned HeapSnapshot::GetUid() const {
4929 IsDeadCheck("v8::HeapSnapshot::GetUid");
Iain Merrick75681382010-08-19 15:07:18 +01004930 return ToInternal(this)->uid();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004931}
4932
4933
4934Handle<String> HeapSnapshot::GetTitle() const {
4935 IsDeadCheck("v8::HeapSnapshot::GetTitle");
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004936 return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
Iain Merrick75681382010-08-19 15:07:18 +01004937 ToInternal(this)->title())));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004938}
4939
4940
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004941const HeapGraphNode* HeapSnapshot::GetRoot() const {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004942 IsDeadCheck("v8::HeapSnapshot::GetHead");
Iain Merrick75681382010-08-19 15:07:18 +01004943 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004944}
4945
4946
Ben Murdochb0fe1622011-05-05 13:52:32 +01004947const HeapGraphNode* HeapSnapshot::GetNodeById(uint64_t id) const {
4948 IsDeadCheck("v8::HeapSnapshot::GetNodeById");
4949 return reinterpret_cast<const HeapGraphNode*>(
4950 ToInternal(this)->GetEntryById(id));
4951}
4952
4953
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004954const HeapSnapshotsDiff* HeapSnapshot::CompareWith(
4955 const HeapSnapshot* snapshot) const {
4956 IsDeadCheck("v8::HeapSnapshot::CompareWith");
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004957 return reinterpret_cast<const HeapSnapshotsDiff*>(
Iain Merrick75681382010-08-19 15:07:18 +01004958 ToInternal(this)->CompareWith(ToInternal(snapshot)));
Ben Murdoch3bec4d22010-07-22 14:51:16 +01004959}
4960
4961
Kristian Monsen0d5e1162010-09-30 15:31:59 +01004962void HeapSnapshot::Serialize(OutputStream* stream,
4963 HeapSnapshot::SerializationFormat format) const {
4964 IsDeadCheck("v8::HeapSnapshot::Serialize");
4965 ApiCheck(format == kJSON,
4966 "v8::HeapSnapshot::Serialize",
4967 "Unknown serialization format");
4968 ApiCheck(stream->GetOutputEncoding() == OutputStream::kAscii,
4969 "v8::HeapSnapshot::Serialize",
4970 "Unsupported output encoding");
4971 ApiCheck(stream->GetChunkSize() > 0,
4972 "v8::HeapSnapshot::Serialize",
4973 "Invalid stream chunk size");
4974 i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
4975 serializer.Serialize(stream);
4976}
4977
4978
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01004979int HeapProfiler::GetSnapshotsCount() {
4980 IsDeadCheck("v8::HeapProfiler::GetSnapshotsCount");
4981 return i::HeapProfiler::GetSnapshotsCount();
4982}
4983
4984
4985const HeapSnapshot* HeapProfiler::GetSnapshot(int index) {
4986 IsDeadCheck("v8::HeapProfiler::GetSnapshot");
4987 return reinterpret_cast<const HeapSnapshot*>(
4988 i::HeapProfiler::GetSnapshot(index));
4989}
4990
4991
4992const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) {
4993 IsDeadCheck("v8::HeapProfiler::FindSnapshot");
4994 return reinterpret_cast<const HeapSnapshot*>(
4995 i::HeapProfiler::FindSnapshot(uid));
4996}
4997
4998
Steve Block791712a2010-08-27 10:21:07 +01004999const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title,
Ben Murdochb0fe1622011-05-05 13:52:32 +01005000 HeapSnapshot::Type type,
5001 ActivityControl* control) {
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005002 IsDeadCheck("v8::HeapProfiler::TakeSnapshot");
Steve Block791712a2010-08-27 10:21:07 +01005003 i::HeapSnapshot::Type internal_type = i::HeapSnapshot::kFull;
5004 switch (type) {
5005 case HeapSnapshot::kFull:
5006 internal_type = i::HeapSnapshot::kFull;
5007 break;
5008 case HeapSnapshot::kAggregated:
5009 internal_type = i::HeapSnapshot::kAggregated;
5010 break;
5011 default:
5012 UNREACHABLE();
5013 }
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005014 return reinterpret_cast<const HeapSnapshot*>(
Ben Murdochb0fe1622011-05-05 13:52:32 +01005015 i::HeapProfiler::TakeSnapshot(
5016 *Utils::OpenHandle(*title), internal_type, control));
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01005017}
5018
Steve Block6ded16b2010-05-10 14:33:55 +01005019#endif // ENABLE_LOGGING_AND_PROFILING
5020
5021
Ben Murdochb0fe1622011-05-05 13:52:32 +01005022v8::Testing::StressType internal::Testing::stress_type_ =
5023 v8::Testing::kStressTypeOpt;
5024
5025
5026void Testing::SetStressRunType(Testing::StressType type) {
5027 internal::Testing::set_stress_type(type);
5028}
5029
5030int Testing::GetStressRuns() {
5031 if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs;
5032#ifdef DEBUG
5033 // In debug mode the code runs much slower so stressing will only make two
5034 // runs.
5035 return 2;
5036#else
5037 return 5;
5038#endif
5039}
5040
5041
5042static void SetFlagsFromString(const char* flags) {
5043 V8::SetFlagsFromString(flags, i::StrLength(flags));
5044}
5045
5046
5047void Testing::PrepareStressRun(int run) {
5048 static const char* kLazyOptimizations =
5049 "--prepare-always-opt --nolimit-inlining "
5050 "--noalways-opt --noopt-eagerly";
5051 static const char* kEagerOptimizations = "--opt-eagerly";
5052 static const char* kForcedOptimizations = "--always-opt";
5053
5054 // If deoptimization stressed turn on frequent deoptimization. If no value
5055 // is spefified through --deopt-every-n-times use a default default value.
5056 static const char* kDeoptEvery13Times = "--deopt-every-n-times=13";
5057 if (internal::Testing::stress_type() == Testing::kStressTypeDeopt &&
5058 internal::FLAG_deopt_every_n_times == 0) {
5059 SetFlagsFromString(kDeoptEvery13Times);
5060 }
5061
5062#ifdef DEBUG
5063 // As stressing in debug mode only make two runs skip the deopt stressing
5064 // here.
5065 if (run == GetStressRuns() - 1) {
5066 SetFlagsFromString(kForcedOptimizations);
5067 } else {
5068 SetFlagsFromString(kEagerOptimizations);
5069 SetFlagsFromString(kLazyOptimizations);
5070 }
5071#else
5072 if (run == GetStressRuns() - 1) {
5073 SetFlagsFromString(kForcedOptimizations);
5074 } else if (run == GetStressRuns() - 2) {
5075 SetFlagsFromString(kEagerOptimizations);
5076 } else {
5077 SetFlagsFromString(kLazyOptimizations);
5078 }
5079#endif
5080}
5081
5082
Steve Blocka7e24c12009-10-30 11:49:00 +00005083namespace internal {
5084
5085
5086HandleScopeImplementer* HandleScopeImplementer::instance() {
5087 return &thread_local;
5088}
5089
5090
5091void HandleScopeImplementer::FreeThreadResources() {
5092 thread_local.Free();
5093}
5094
5095
5096char* HandleScopeImplementer::ArchiveThread(char* storage) {
5097 return thread_local.ArchiveThreadHelper(storage);
5098}
5099
5100
5101char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
5102 v8::ImplementationUtilities::HandleScopeData* current =
5103 v8::ImplementationUtilities::CurrentHandleScope();
5104 handle_scope_data_ = *current;
5105 memcpy(storage, this, sizeof(*this));
5106
5107 ResetAfterArchive();
5108 current->Initialize();
5109
5110 return storage + ArchiveSpacePerThread();
5111}
5112
5113
5114int HandleScopeImplementer::ArchiveSpacePerThread() {
5115 return sizeof(thread_local);
5116}
5117
5118
5119char* HandleScopeImplementer::RestoreThread(char* storage) {
5120 return thread_local.RestoreThreadHelper(storage);
5121}
5122
5123
5124char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
5125 memcpy(this, storage, sizeof(*this));
5126 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
5127 return storage + ArchiveSpacePerThread();
5128}
5129
5130
5131void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
5132 // Iterate over all handles in the blocks except for the last.
5133 for (int i = blocks()->length() - 2; i >= 0; --i) {
5134 Object** block = blocks()->at(i);
5135 v->VisitPointers(block, &block[kHandleBlockSize]);
5136 }
5137
5138 // Iterate over live handles in the last block (if any).
5139 if (!blocks()->is_empty()) {
5140 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
5141 }
5142
5143 if (!saved_contexts_.is_empty()) {
5144 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
5145 v->VisitPointers(start, start + saved_contexts_.length());
5146 }
5147}
5148
5149
5150void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
5151 v8::ImplementationUtilities::HandleScopeData* current =
5152 v8::ImplementationUtilities::CurrentHandleScope();
5153 thread_local.handle_scope_data_ = *current;
5154 thread_local.IterateThis(v);
5155}
5156
5157
5158char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
5159 HandleScopeImplementer* thread_local =
5160 reinterpret_cast<HandleScopeImplementer*>(storage);
5161 thread_local->IterateThis(v);
5162 return storage + ArchiveSpacePerThread();
5163}
5164
5165} } // namespace v8::internal