blob: 262bf528137222e4c9aa08b11c9c6bdbd57a88be [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2009 the V8 project authors. All rights reserved.
2// 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"
31#include "arguments.h"
32#include "bootstrapper.h"
33#include "compiler.h"
34#include "debug.h"
35#include "execution.h"
36#include "global-handles.h"
Andrei Popescu31002712010-02-23 13:46:05 +000037#include "globals.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000038#include "platform.h"
39#include "serialize.h"
40#include "snapshot.h"
Steve Blockd0582a62009-12-15 09:54:21 +000041#include "utils.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000042#include "v8threads.h"
43#include "version.h"
44
45
46#define LOG_API(expr) LOG(ApiEntryCall(expr))
47
48#ifdef ENABLE_HEAP_PROTECTION
49#define ENTER_V8 i::VMState __state__(i::OTHER)
50#define LEAVE_V8 i::VMState __state__(i::EXTERNAL)
51#else
52#define ENTER_V8 ((void) 0)
53#define LEAVE_V8 ((void) 0)
54#endif
55
56namespace v8 {
57
58
59#define ON_BAILOUT(location, code) \
60 if (IsDeadCheck(location)) { \
61 code; \
62 UNREACHABLE(); \
63 }
64
65
66#define EXCEPTION_PREAMBLE() \
67 thread_local.IncrementCallDepth(); \
68 ASSERT(!i::Top::external_caught_exception()); \
69 bool has_pending_exception = false
70
71
72#define EXCEPTION_BAILOUT_CHECK(value) \
73 do { \
74 thread_local.DecrementCallDepth(); \
75 if (has_pending_exception) { \
76 if (thread_local.CallDepthIsZero() && i::Top::is_out_of_memory()) { \
77 if (!thread_local.ignore_out_of_memory()) \
78 i::V8::FatalProcessOutOfMemory(NULL); \
79 } \
80 bool call_depth_is_zero = thread_local.CallDepthIsZero(); \
81 i::Top::OptionalRescheduleException(call_depth_is_zero); \
82 return value; \
83 } \
84 } while (false)
85
86
87#define API_ENTRY_CHECK(msg) \
88 do { \
89 if (v8::Locker::IsActive()) { \
90 ApiCheck(i::ThreadManager::IsLockedByCurrentThread(), \
91 msg, \
92 "Entering the V8 API without proper locking in place"); \
93 } \
94 } while (false)
95
96// --- 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 ---
97
98
99static i::HandleScopeImplementer thread_local;
100
101
102// --- E x c e p t i o n B e h a v i o r ---
103
104
105static FatalErrorCallback exception_behavior = NULL;
106int i::Internals::kJSObjectType = JS_OBJECT_TYPE;
107int i::Internals::kFirstNonstringType = FIRST_NONSTRING_TYPE;
108int i::Internals::kProxyType = PROXY_TYPE;
109
110static void DefaultFatalErrorHandler(const char* location,
111 const char* message) {
112 ENTER_V8;
113 API_Fatal(location, message);
114}
115
116
117
118static FatalErrorCallback& GetFatalErrorHandler() {
119 if (exception_behavior == NULL) {
120 exception_behavior = DefaultFatalErrorHandler;
121 }
122 return exception_behavior;
123}
124
125
126
127// When V8 cannot allocated memory FatalProcessOutOfMemory is called.
128// The default fatal error handler is called and execution is stopped.
129void i::V8::FatalProcessOutOfMemory(const char* location) {
Steve Blockd0582a62009-12-15 09:54:21 +0000130 i::HeapStats heap_stats;
131 int start_marker;
132 heap_stats.start_marker = &start_marker;
133 int new_space_size;
134 heap_stats.new_space_size = &new_space_size;
135 int new_space_capacity;
136 heap_stats.new_space_capacity = &new_space_capacity;
137 int old_pointer_space_size;
138 heap_stats.old_pointer_space_size = &old_pointer_space_size;
139 int old_pointer_space_capacity;
140 heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
141 int old_data_space_size;
142 heap_stats.old_data_space_size = &old_data_space_size;
143 int old_data_space_capacity;
144 heap_stats.old_data_space_capacity = &old_data_space_capacity;
145 int code_space_size;
146 heap_stats.code_space_size = &code_space_size;
147 int code_space_capacity;
148 heap_stats.code_space_capacity = &code_space_capacity;
149 int map_space_size;
150 heap_stats.map_space_size = &map_space_size;
151 int map_space_capacity;
152 heap_stats.map_space_capacity = &map_space_capacity;
153 int cell_space_size;
154 heap_stats.cell_space_size = &cell_space_size;
155 int cell_space_capacity;
156 heap_stats.cell_space_capacity = &cell_space_capacity;
157 int lo_space_size;
158 heap_stats.lo_space_size = &lo_space_size;
159 int global_handle_count;
160 heap_stats.global_handle_count = &global_handle_count;
161 int weak_global_handle_count;
162 heap_stats.weak_global_handle_count = &weak_global_handle_count;
163 int pending_global_handle_count;
164 heap_stats.pending_global_handle_count = &pending_global_handle_count;
165 int near_death_global_handle_count;
166 heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
167 int destroyed_global_handle_count;
168 heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count;
169 int end_marker;
170 heap_stats.end_marker = &end_marker;
171 i::Heap::RecordStats(&heap_stats);
Steve Blocka7e24c12009-10-30 11:49:00 +0000172 i::V8::SetFatalError();
173 FatalErrorCallback callback = GetFatalErrorHandler();
174 {
175 LEAVE_V8;
176 callback(location, "Allocation failed - process out of memory");
177 }
178 // If the callback returns, we stop execution.
179 UNREACHABLE();
180}
181
182
183void V8::SetFatalErrorHandler(FatalErrorCallback that) {
184 exception_behavior = that;
185}
186
187
188bool Utils::ReportApiFailure(const char* location, const char* message) {
189 FatalErrorCallback callback = GetFatalErrorHandler();
190 callback(location, message);
191 i::V8::SetFatalError();
192 return false;
193}
194
195
196bool V8::IsDead() {
197 return i::V8::IsDead();
198}
199
200
201static inline bool ApiCheck(bool condition,
202 const char* location,
203 const char* message) {
204 return condition ? true : Utils::ReportApiFailure(location, message);
205}
206
207
208static bool ReportV8Dead(const char* location) {
209 FatalErrorCallback callback = GetFatalErrorHandler();
210 callback(location, "V8 is no longer usable");
211 return true;
212}
213
214
215static bool ReportEmptyHandle(const char* location) {
216 FatalErrorCallback callback = GetFatalErrorHandler();
217 callback(location, "Reading from empty handle");
218 return true;
219}
220
221
222/**
223 * IsDeadCheck checks that the vm is usable. If, for instance, the vm has been
224 * out of memory at some point this check will fail. It should be called on
225 * entry to all methods that touch anything in the heap, except destructors
226 * which you sometimes can't avoid calling after the vm has crashed. Functions
227 * that call EnsureInitialized or ON_BAILOUT don't have to also call
228 * IsDeadCheck. ON_BAILOUT has the advantage over EnsureInitialized that you
229 * can arrange to return if the VM is dead. This is needed to ensure that no VM
230 * heap allocations are attempted on a dead VM. EnsureInitialized has the
231 * advantage over ON_BAILOUT that it actually initializes the VM if this has not
232 * yet been done.
233 */
234static inline bool IsDeadCheck(const char* location) {
235 return !i::V8::IsRunning()
236 && i::V8::IsDead() ? ReportV8Dead(location) : false;
237}
238
239
240static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
241 return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
242}
243
244
245static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
246 return (obj == 0) ? ReportEmptyHandle(location) : false;
247}
248
249// --- S t a t i c s ---
250
251
252static i::StringInputBuffer write_input_buffer;
253
254
255static inline bool EnsureInitialized(const char* location) {
256 if (i::V8::IsRunning()) {
257 return true;
258 }
259 if (IsDeadCheck(location)) {
260 return false;
261 }
262 return ApiCheck(v8::V8::Initialize(), location, "Error initializing V8");
263}
264
265
266ImplementationUtilities::HandleScopeData*
267 ImplementationUtilities::CurrentHandleScope() {
268 return &i::HandleScope::current_;
269}
270
271
272#ifdef DEBUG
273void ImplementationUtilities::ZapHandleRange(i::Object** begin,
274 i::Object** end) {
275 i::HandleScope::ZapRange(begin, end);
276}
277#endif
278
279
280v8::Handle<v8::Primitive> ImplementationUtilities::Undefined() {
281 if (!EnsureInitialized("v8::Undefined()")) return v8::Handle<v8::Primitive>();
282 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::undefined_value()));
283}
284
285
286v8::Handle<v8::Primitive> ImplementationUtilities::Null() {
287 if (!EnsureInitialized("v8::Null()")) return v8::Handle<v8::Primitive>();
288 return v8::Handle<Primitive>(ToApi<Primitive>(i::Factory::null_value()));
289}
290
291
292v8::Handle<v8::Boolean> ImplementationUtilities::True() {
293 if (!EnsureInitialized("v8::True()")) return v8::Handle<v8::Boolean>();
294 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::true_value()));
295}
296
297
298v8::Handle<v8::Boolean> ImplementationUtilities::False() {
299 if (!EnsureInitialized("v8::False()")) return v8::Handle<v8::Boolean>();
300 return v8::Handle<v8::Boolean>(ToApi<Boolean>(i::Factory::false_value()));
301}
302
303
304void V8::SetFlagsFromString(const char* str, int length) {
305 i::FlagList::SetFlagsFromString(str, length);
306}
307
308
309void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
310 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
311}
312
313
314v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
315 if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
316 ENTER_V8;
317 // If we're passed an empty handle, we throw an undefined exception
318 // to deal more gracefully with out of memory situations.
319 if (value.IsEmpty()) {
320 i::Top::ScheduleThrow(i::Heap::undefined_value());
321 } else {
322 i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
323 }
324 return v8::Undefined();
325}
326
327
328RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
329
330
331RegisteredExtension::RegisteredExtension(Extension* extension)
332 : extension_(extension), state_(UNVISITED) { }
333
334
335void RegisteredExtension::Register(RegisteredExtension* that) {
336 that->next_ = RegisteredExtension::first_extension_;
337 RegisteredExtension::first_extension_ = that;
338}
339
340
341void RegisterExtension(Extension* that) {
342 RegisteredExtension* extension = new RegisteredExtension(that);
343 RegisteredExtension::Register(extension);
344}
345
346
347Extension::Extension(const char* name,
348 const char* source,
349 int dep_count,
350 const char** deps)
351 : name_(name),
352 source_(source),
353 dep_count_(dep_count),
354 deps_(deps),
355 auto_enable_(false) { }
356
357
358v8::Handle<Primitive> Undefined() {
359 LOG_API("Undefined");
360 return ImplementationUtilities::Undefined();
361}
362
363
364v8::Handle<Primitive> Null() {
365 LOG_API("Null");
366 return ImplementationUtilities::Null();
367}
368
369
370v8::Handle<Boolean> True() {
371 LOG_API("True");
372 return ImplementationUtilities::True();
373}
374
375
376v8::Handle<Boolean> False() {
377 LOG_API("False");
378 return ImplementationUtilities::False();
379}
380
381
382ResourceConstraints::ResourceConstraints()
383 : max_young_space_size_(0),
384 max_old_space_size_(0),
385 stack_limit_(NULL) { }
386
387
388bool SetResourceConstraints(ResourceConstraints* constraints) {
Steve Block3ce2e202009-11-05 08:53:23 +0000389 int young_space_size = constraints->max_young_space_size();
Steve Blocka7e24c12009-10-30 11:49:00 +0000390 int old_gen_size = constraints->max_old_space_size();
Steve Block3ce2e202009-11-05 08:53:23 +0000391 if (young_space_size != 0 || old_gen_size != 0) {
392 bool result = i::Heap::ConfigureHeap(young_space_size / 2, old_gen_size);
Steve Blocka7e24c12009-10-30 11:49:00 +0000393 if (!result) return false;
394 }
395 if (constraints->stack_limit() != NULL) {
396 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
397 i::StackGuard::SetStackLimit(limit);
398 }
399 return true;
400}
401
402
403i::Object** V8::GlobalizeReference(i::Object** obj) {
404 if (IsDeadCheck("V8::Persistent::New")) return NULL;
405 LOG_API("Persistent::New");
406 i::Handle<i::Object> result =
407 i::GlobalHandles::Create(*obj);
408 return result.location();
409}
410
411
412void V8::MakeWeak(i::Object** object, void* parameters,
413 WeakReferenceCallback callback) {
414 LOG_API("MakeWeak");
415 i::GlobalHandles::MakeWeak(object, parameters, callback);
416}
417
418
419void V8::ClearWeak(i::Object** obj) {
420 LOG_API("ClearWeak");
421 i::GlobalHandles::ClearWeakness(obj);
422}
423
424
425bool V8::IsGlobalNearDeath(i::Object** obj) {
426 LOG_API("IsGlobalNearDeath");
427 if (!i::V8::IsRunning()) return false;
428 return i::GlobalHandles::IsNearDeath(obj);
429}
430
431
432bool V8::IsGlobalWeak(i::Object** obj) {
433 LOG_API("IsGlobalWeak");
434 if (!i::V8::IsRunning()) return false;
435 return i::GlobalHandles::IsWeak(obj);
436}
437
438
439void V8::DisposeGlobal(i::Object** obj) {
440 LOG_API("DisposeGlobal");
441 if (!i::V8::IsRunning()) return;
442 if ((*obj)->IsGlobalContext()) i::Heap::NotifyContextDisposed();
443 i::GlobalHandles::Destroy(obj);
444}
445
446// --- H a n d l e s ---
447
448
449HandleScope::HandleScope() : is_closed_(false) {
450 API_ENTRY_CHECK("HandleScope::HandleScope");
451 i::HandleScope::Enter(&previous_);
452}
453
454
455HandleScope::~HandleScope() {
456 if (!is_closed_) {
457 i::HandleScope::Leave(&previous_);
458 }
459}
460
461
462int HandleScope::NumberOfHandles() {
463 return i::HandleScope::NumberOfHandles();
464}
465
466
467i::Object** v8::HandleScope::CreateHandle(i::Object* value) {
468 return i::HandleScope::CreateHandle(value);
469}
470
471
472void Context::Enter() {
473 if (IsDeadCheck("v8::Context::Enter()")) return;
474 ENTER_V8;
475 i::Handle<i::Context> env = Utils::OpenHandle(this);
476 thread_local.EnterContext(env);
477
478 thread_local.SaveContext(i::Top::context());
479 i::Top::set_context(*env);
480}
481
482
483void Context::Exit() {
484 if (!i::V8::IsRunning()) return;
485 if (!ApiCheck(thread_local.LeaveLastContext(),
486 "v8::Context::Exit()",
487 "Cannot exit non-entered context")) {
488 return;
489 }
490
491 // Content of 'last_context' could be NULL.
492 i::Context* last_context = thread_local.RestoreContext();
493 i::Top::set_context(last_context);
494}
495
496
Steve Blockd0582a62009-12-15 09:54:21 +0000497void Context::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000498 if (IsDeadCheck("v8::Context::SetData()")) return;
499 ENTER_V8;
500 {
501 HandleScope scope;
502 i::Handle<i::Context> env = Utils::OpenHandle(this);
503 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
504 ASSERT(env->IsGlobalContext());
505 if (env->IsGlobalContext()) {
506 env->set_data(*raw_data);
507 }
508 }
509}
510
511
512v8::Local<v8::Value> Context::GetData() {
513 if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
514 ENTER_V8;
515 i::Object* raw_result = NULL;
516 {
517 HandleScope scope;
518 i::Handle<i::Context> env = Utils::OpenHandle(this);
519 ASSERT(env->IsGlobalContext());
520 if (env->IsGlobalContext()) {
521 raw_result = env->data();
522 } else {
523 return Local<Value>();
524 }
525 }
526 i::Handle<i::Object> result(raw_result);
527 return Utils::ToLocal(result);
528}
529
530
531i::Object** v8::HandleScope::RawClose(i::Object** value) {
532 if (!ApiCheck(!is_closed_,
533 "v8::HandleScope::Close()",
534 "Local scope has already been closed")) {
535 return 0;
536 }
537 LOG_API("CloseHandleScope");
538
539 // Read the result before popping the handle block.
540 i::Object* result = *value;
541 is_closed_ = true;
542 i::HandleScope::Leave(&previous_);
543
544 // Allocate a new handle on the previous handle block.
545 i::Handle<i::Object> handle(result);
546 return handle.location();
547}
548
549
550// --- N e a n d e r ---
551
552
553// A constructor cannot easily return an error value, therefore it is necessary
554// to check for a dead VM with ON_BAILOUT before constructing any Neander
555// objects. To remind you about this there is no HandleScope in the
556// NeanderObject constructor. When you add one to the site calling the
557// constructor you should check that you ensured the VM was not dead first.
558NeanderObject::NeanderObject(int size) {
559 EnsureInitialized("v8::Nowhere");
560 ENTER_V8;
561 value_ = i::Factory::NewNeanderObject();
562 i::Handle<i::FixedArray> elements = i::Factory::NewFixedArray(size);
563 value_->set_elements(*elements);
564}
565
566
567int NeanderObject::size() {
568 return i::FixedArray::cast(value_->elements())->length();
569}
570
571
572NeanderArray::NeanderArray() : obj_(2) {
573 obj_.set(0, i::Smi::FromInt(0));
574}
575
576
577int NeanderArray::length() {
578 return i::Smi::cast(obj_.get(0))->value();
579}
580
581
582i::Object* NeanderArray::get(int offset) {
583 ASSERT(0 <= offset);
584 ASSERT(offset < length());
585 return obj_.get(offset + 1);
586}
587
588
589// This method cannot easily return an error value, therefore it is necessary
590// to check for a dead VM with ON_BAILOUT before calling it. To remind you
591// about this there is no HandleScope in this method. When you add one to the
592// site calling this method you should check that you ensured the VM was not
593// dead first.
594void NeanderArray::add(i::Handle<i::Object> value) {
595 int length = this->length();
596 int size = obj_.size();
597 if (length == size - 1) {
598 i::Handle<i::FixedArray> new_elms = i::Factory::NewFixedArray(2 * size);
599 for (int i = 0; i < length; i++)
600 new_elms->set(i + 1, get(i));
601 obj_.value()->set_elements(*new_elms);
602 }
603 obj_.set(length + 1, *value);
604 obj_.set(0, i::Smi::FromInt(length + 1));
605}
606
607
608void NeanderArray::set(int index, i::Object* value) {
609 if (index < 0 || index >= this->length()) return;
610 obj_.set(index + 1, value);
611}
612
613
614// --- T e m p l a t e ---
615
616
617static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
618 that->set_tag(i::Smi::FromInt(type));
619}
620
621
622void Template::Set(v8::Handle<String> name, v8::Handle<Data> value,
623 v8::PropertyAttribute attribute) {
624 if (IsDeadCheck("v8::Template::SetProperty()")) return;
625 ENTER_V8;
626 HandleScope scope;
627 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list());
628 if (list->IsUndefined()) {
629 list = NeanderArray().value();
630 Utils::OpenHandle(this)->set_property_list(*list);
631 }
632 NeanderArray array(list);
633 array.add(Utils::OpenHandle(*name));
634 array.add(Utils::OpenHandle(*value));
635 array.add(Utils::OpenHandle(*v8::Integer::New(attribute)));
636}
637
638
639// --- F u n c t i o n T e m p l a t e ---
640static void InitializeFunctionTemplate(
641 i::Handle<i::FunctionTemplateInfo> info) {
642 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
643 info->set_flag(0);
644}
645
646
647Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
648 if (IsDeadCheck("v8::FunctionTemplate::PrototypeTemplate()")) {
649 return Local<ObjectTemplate>();
650 }
651 ENTER_V8;
652 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template());
653 if (result->IsUndefined()) {
654 result = Utils::OpenHandle(*ObjectTemplate::New());
655 Utils::OpenHandle(this)->set_prototype_template(*result);
656 }
657 return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result));
658}
659
660
661void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
662 if (IsDeadCheck("v8::FunctionTemplate::Inherit()")) return;
663 ENTER_V8;
664 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
665}
666
667
668// To distinguish the function templates, so that we can find them in the
669// function cache of the global context.
670static int next_serial_number = 0;
671
672
673Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback,
674 v8::Handle<Value> data, v8::Handle<Signature> signature) {
675 EnsureInitialized("v8::FunctionTemplate::New()");
676 LOG_API("FunctionTemplate::New");
677 ENTER_V8;
678 i::Handle<i::Struct> struct_obj =
679 i::Factory::NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
680 i::Handle<i::FunctionTemplateInfo> obj =
681 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
682 InitializeFunctionTemplate(obj);
683 obj->set_serial_number(i::Smi::FromInt(next_serial_number++));
684 if (callback != 0) {
685 if (data.IsEmpty()) data = v8::Undefined();
686 Utils::ToLocal(obj)->SetCallHandler(callback, data);
687 }
688 obj->set_undetectable(false);
689 obj->set_needs_access_check(false);
690
691 if (!signature.IsEmpty())
692 obj->set_signature(*Utils::OpenHandle(*signature));
693 return Utils::ToLocal(obj);
694}
695
696
697Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
698 int argc, Handle<FunctionTemplate> argv[]) {
699 EnsureInitialized("v8::Signature::New()");
700 LOG_API("Signature::New");
701 ENTER_V8;
702 i::Handle<i::Struct> struct_obj =
703 i::Factory::NewStruct(i::SIGNATURE_INFO_TYPE);
704 i::Handle<i::SignatureInfo> obj =
705 i::Handle<i::SignatureInfo>::cast(struct_obj);
706 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
707 if (argc > 0) {
708 i::Handle<i::FixedArray> args = i::Factory::NewFixedArray(argc);
709 for (int i = 0; i < argc; i++) {
710 if (!argv[i].IsEmpty())
711 args->set(i, *Utils::OpenHandle(*argv[i]));
712 }
713 obj->set_args(*args);
714 }
715 return Utils::ToLocal(obj);
716}
717
718
719Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
720 Handle<FunctionTemplate> types[1] = { type };
721 return TypeSwitch::New(1, types);
722}
723
724
725Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
726 EnsureInitialized("v8::TypeSwitch::New()");
727 LOG_API("TypeSwitch::New");
728 ENTER_V8;
729 i::Handle<i::FixedArray> vector = i::Factory::NewFixedArray(argc);
730 for (int i = 0; i < argc; i++)
731 vector->set(i, *Utils::OpenHandle(*types[i]));
732 i::Handle<i::Struct> struct_obj =
733 i::Factory::NewStruct(i::TYPE_SWITCH_INFO_TYPE);
734 i::Handle<i::TypeSwitchInfo> obj =
735 i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
736 obj->set_types(*vector);
737 return Utils::ToLocal(obj);
738}
739
740
741int TypeSwitch::match(v8::Handle<Value> value) {
742 LOG_API("TypeSwitch::match");
743 i::Handle<i::Object> obj = Utils::OpenHandle(*value);
744 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
745 i::FixedArray* types = i::FixedArray::cast(info->types());
746 for (int i = 0; i < types->length(); i++) {
747 if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
748 return i + 1;
749 }
750 return 0;
751}
752
753
754void FunctionTemplate::SetCallHandler(InvocationCallback callback,
755 v8::Handle<Value> data) {
756 if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
757 ENTER_V8;
758 HandleScope scope;
759 i::Handle<i::Struct> struct_obj =
760 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
761 i::Handle<i::CallHandlerInfo> obj =
762 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
763 obj->set_callback(*FromCData(callback));
764 if (data.IsEmpty()) data = v8::Undefined();
765 obj->set_data(*Utils::OpenHandle(*data));
766 Utils::OpenHandle(this)->set_call_code(*obj);
767}
768
769
770void FunctionTemplate::AddInstancePropertyAccessor(
771 v8::Handle<String> name,
772 AccessorGetter getter,
773 AccessorSetter setter,
774 v8::Handle<Value> data,
775 v8::AccessControl settings,
776 v8::PropertyAttribute attributes) {
777 if (IsDeadCheck("v8::FunctionTemplate::AddInstancePropertyAccessor()")) {
778 return;
779 }
780 ENTER_V8;
781 HandleScope scope;
782 i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
783 ASSERT(getter != NULL);
784 obj->set_getter(*FromCData(getter));
785 obj->set_setter(*FromCData(setter));
786 if (data.IsEmpty()) data = v8::Undefined();
787 obj->set_data(*Utils::OpenHandle(*data));
788 obj->set_name(*Utils::OpenHandle(*name));
789 if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
790 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
791 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
792 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
793
794 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors());
795 if (list->IsUndefined()) {
796 list = NeanderArray().value();
797 Utils::OpenHandle(this)->set_property_accessors(*list);
798 }
799 NeanderArray array(list);
800 array.add(obj);
801}
802
803
804Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
805 if (IsDeadCheck("v8::FunctionTemplate::InstanceTemplate()")
806 || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
807 return Local<ObjectTemplate>();
808 ENTER_V8;
809 if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) {
810 Local<ObjectTemplate> templ =
811 ObjectTemplate::New(v8::Handle<FunctionTemplate>(this));
812 Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ));
813 }
814 i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast(
815 Utils::OpenHandle(this)->instance_template()));
816 return Utils::ToLocal(result);
817}
818
819
820void FunctionTemplate::SetClassName(Handle<String> name) {
821 if (IsDeadCheck("v8::FunctionTemplate::SetClassName()")) return;
822 ENTER_V8;
823 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
824}
825
826
827void FunctionTemplate::SetHiddenPrototype(bool value) {
828 if (IsDeadCheck("v8::FunctionTemplate::SetHiddenPrototype()")) return;
829 ENTER_V8;
830 Utils::OpenHandle(this)->set_hidden_prototype(value);
831}
832
833
834void FunctionTemplate::SetNamedInstancePropertyHandler(
835 NamedPropertyGetter getter,
836 NamedPropertySetter setter,
837 NamedPropertyQuery query,
838 NamedPropertyDeleter remover,
839 NamedPropertyEnumerator enumerator,
840 Handle<Value> data) {
841 if (IsDeadCheck("v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) {
842 return;
843 }
844 ENTER_V8;
845 HandleScope scope;
846 i::Handle<i::Struct> struct_obj =
847 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
848 i::Handle<i::InterceptorInfo> obj =
849 i::Handle<i::InterceptorInfo>::cast(struct_obj);
850 if (getter != 0) obj->set_getter(*FromCData(getter));
851 if (setter != 0) obj->set_setter(*FromCData(setter));
852 if (query != 0) obj->set_query(*FromCData(query));
853 if (remover != 0) obj->set_deleter(*FromCData(remover));
854 if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
855 if (data.IsEmpty()) data = v8::Undefined();
856 obj->set_data(*Utils::OpenHandle(*data));
857 Utils::OpenHandle(this)->set_named_property_handler(*obj);
858}
859
860
861void FunctionTemplate::SetIndexedInstancePropertyHandler(
862 IndexedPropertyGetter getter,
863 IndexedPropertySetter setter,
864 IndexedPropertyQuery query,
865 IndexedPropertyDeleter remover,
866 IndexedPropertyEnumerator enumerator,
867 Handle<Value> data) {
868 if (IsDeadCheck(
869 "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) {
870 return;
871 }
872 ENTER_V8;
873 HandleScope scope;
874 i::Handle<i::Struct> struct_obj =
875 i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
876 i::Handle<i::InterceptorInfo> obj =
877 i::Handle<i::InterceptorInfo>::cast(struct_obj);
878 if (getter != 0) obj->set_getter(*FromCData(getter));
879 if (setter != 0) obj->set_setter(*FromCData(setter));
880 if (query != 0) obj->set_query(*FromCData(query));
881 if (remover != 0) obj->set_deleter(*FromCData(remover));
882 if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
883 if (data.IsEmpty()) data = v8::Undefined();
884 obj->set_data(*Utils::OpenHandle(*data));
885 Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
886}
887
888
889void FunctionTemplate::SetInstanceCallAsFunctionHandler(
890 InvocationCallback callback,
891 Handle<Value> data) {
892 if (IsDeadCheck("v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) {
893 return;
894 }
895 ENTER_V8;
896 HandleScope scope;
897 i::Handle<i::Struct> struct_obj =
898 i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
899 i::Handle<i::CallHandlerInfo> obj =
900 i::Handle<i::CallHandlerInfo>::cast(struct_obj);
901 obj->set_callback(*FromCData(callback));
902 if (data.IsEmpty()) data = v8::Undefined();
903 obj->set_data(*Utils::OpenHandle(*data));
904 Utils::OpenHandle(this)->set_instance_call_handler(*obj);
905}
906
907
908// --- O b j e c t T e m p l a t e ---
909
910
911Local<ObjectTemplate> ObjectTemplate::New() {
912 return New(Local<FunctionTemplate>());
913}
914
915
916Local<ObjectTemplate> ObjectTemplate::New(
917 v8::Handle<FunctionTemplate> constructor) {
918 if (IsDeadCheck("v8::ObjectTemplate::New()")) return Local<ObjectTemplate>();
919 EnsureInitialized("v8::ObjectTemplate::New()");
920 LOG_API("ObjectTemplate::New");
921 ENTER_V8;
922 i::Handle<i::Struct> struct_obj =
923 i::Factory::NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
924 i::Handle<i::ObjectTemplateInfo> obj =
925 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
926 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
927 if (!constructor.IsEmpty())
928 obj->set_constructor(*Utils::OpenHandle(*constructor));
929 obj->set_internal_field_count(i::Smi::FromInt(0));
930 return Utils::ToLocal(obj);
931}
932
933
934// Ensure that the object template has a constructor. If no
935// constructor is available we create one.
936static void EnsureConstructor(ObjectTemplate* object_template) {
937 if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) {
938 Local<FunctionTemplate> templ = FunctionTemplate::New();
939 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
940 constructor->set_instance_template(*Utils::OpenHandle(object_template));
941 Utils::OpenHandle(object_template)->set_constructor(*constructor);
942 }
943}
944
945
946void ObjectTemplate::SetAccessor(v8::Handle<String> name,
947 AccessorGetter getter,
948 AccessorSetter setter,
949 v8::Handle<Value> data,
950 AccessControl settings,
951 PropertyAttribute attribute) {
952 if (IsDeadCheck("v8::ObjectTemplate::SetAccessor()")) return;
953 ENTER_V8;
954 HandleScope scope;
955 EnsureConstructor(this);
956 i::FunctionTemplateInfo* constructor =
957 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
958 i::Handle<i::FunctionTemplateInfo> cons(constructor);
959 Utils::ToLocal(cons)->AddInstancePropertyAccessor(name,
960 getter,
961 setter,
962 data,
963 settings,
964 attribute);
965}
966
967
968void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
969 NamedPropertySetter setter,
970 NamedPropertyQuery query,
971 NamedPropertyDeleter remover,
972 NamedPropertyEnumerator enumerator,
973 Handle<Value> data) {
974 if (IsDeadCheck("v8::ObjectTemplate::SetNamedPropertyHandler()")) return;
975 ENTER_V8;
976 HandleScope scope;
977 EnsureConstructor(this);
978 i::FunctionTemplateInfo* constructor =
979 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
980 i::Handle<i::FunctionTemplateInfo> cons(constructor);
981 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
982 setter,
983 query,
984 remover,
985 enumerator,
986 data);
987}
988
989
990void ObjectTemplate::MarkAsUndetectable() {
991 if (IsDeadCheck("v8::ObjectTemplate::MarkAsUndetectable()")) return;
992 ENTER_V8;
993 HandleScope scope;
994 EnsureConstructor(this);
995 i::FunctionTemplateInfo* constructor =
996 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
997 i::Handle<i::FunctionTemplateInfo> cons(constructor);
998 cons->set_undetectable(true);
999}
1000
1001
1002void ObjectTemplate::SetAccessCheckCallbacks(
1003 NamedSecurityCallback named_callback,
1004 IndexedSecurityCallback indexed_callback,
1005 Handle<Value> data,
1006 bool turned_on_by_default) {
1007 if (IsDeadCheck("v8::ObjectTemplate::SetAccessCheckCallbacks()")) return;
1008 ENTER_V8;
1009 HandleScope scope;
1010 EnsureConstructor(this);
1011
1012 i::Handle<i::Struct> struct_info =
1013 i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1014 i::Handle<i::AccessCheckInfo> info =
1015 i::Handle<i::AccessCheckInfo>::cast(struct_info);
1016 info->set_named_callback(*FromCData(named_callback));
1017 info->set_indexed_callback(*FromCData(indexed_callback));
1018 if (data.IsEmpty()) data = v8::Undefined();
1019 info->set_data(*Utils::OpenHandle(*data));
1020
1021 i::FunctionTemplateInfo* constructor =
1022 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1023 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1024 cons->set_access_check_info(*info);
1025 cons->set_needs_access_check(turned_on_by_default);
1026}
1027
1028
1029void ObjectTemplate::SetIndexedPropertyHandler(
1030 IndexedPropertyGetter getter,
1031 IndexedPropertySetter setter,
1032 IndexedPropertyQuery query,
1033 IndexedPropertyDeleter remover,
1034 IndexedPropertyEnumerator enumerator,
1035 Handle<Value> data) {
1036 if (IsDeadCheck("v8::ObjectTemplate::SetIndexedPropertyHandler()")) return;
1037 ENTER_V8;
1038 HandleScope scope;
1039 EnsureConstructor(this);
1040 i::FunctionTemplateInfo* constructor =
1041 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1042 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1043 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter,
1044 setter,
1045 query,
1046 remover,
1047 enumerator,
1048 data);
1049}
1050
1051
1052void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback,
1053 Handle<Value> data) {
1054 if (IsDeadCheck("v8::ObjectTemplate::SetCallAsFunctionHandler()")) return;
1055 ENTER_V8;
1056 HandleScope scope;
1057 EnsureConstructor(this);
1058 i::FunctionTemplateInfo* constructor =
1059 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1060 i::Handle<i::FunctionTemplateInfo> cons(constructor);
1061 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data);
1062}
1063
1064
1065int ObjectTemplate::InternalFieldCount() {
1066 if (IsDeadCheck("v8::ObjectTemplate::InternalFieldCount()")) {
1067 return 0;
1068 }
1069 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1070}
1071
1072
1073void ObjectTemplate::SetInternalFieldCount(int value) {
1074 if (IsDeadCheck("v8::ObjectTemplate::SetInternalFieldCount()")) return;
1075 if (!ApiCheck(i::Smi::IsValid(value),
1076 "v8::ObjectTemplate::SetInternalFieldCount()",
1077 "Invalid internal field count")) {
1078 return;
1079 }
1080 ENTER_V8;
1081 if (value > 0) {
1082 // The internal field count is set by the constructor function's
1083 // construct code, so we ensure that there is a constructor
1084 // function to do the setting.
1085 EnsureConstructor(this);
1086 }
1087 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1088}
1089
1090
1091// --- S c r i p t D a t a ---
1092
1093
1094ScriptData* ScriptData::PreCompile(const char* input, int length) {
1095 unibrow::Utf8InputBuffer<> buf(input, length);
1096 return i::PreParse(i::Handle<i::String>(), &buf, NULL);
1097}
1098
1099
1100ScriptData* ScriptData::New(unsigned* data, int length) {
1101 return new i::ScriptDataImpl(i::Vector<unsigned>(data, length));
1102}
1103
1104
1105// --- S c r i p t ---
1106
1107
1108Local<Script> Script::New(v8::Handle<String> source,
1109 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001110 v8::ScriptData* pre_data,
1111 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001112 ON_BAILOUT("v8::Script::New()", return Local<Script>());
1113 LOG_API("Script::New");
1114 ENTER_V8;
1115 i::Handle<i::String> str = Utils::OpenHandle(*source);
1116 i::Handle<i::Object> name_obj;
1117 int line_offset = 0;
1118 int column_offset = 0;
1119 if (origin != NULL) {
1120 if (!origin->ResourceName().IsEmpty()) {
1121 name_obj = Utils::OpenHandle(*origin->ResourceName());
1122 }
1123 if (!origin->ResourceLineOffset().IsEmpty()) {
1124 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1125 }
1126 if (!origin->ResourceColumnOffset().IsEmpty()) {
1127 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value());
1128 }
1129 }
1130 EXCEPTION_PREAMBLE();
Andrei Popescu402d9372010-02-26 13:31:12 +00001131 i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001132 // We assert that the pre-data is sane, even though we can actually
1133 // handle it if it turns out not to be in release mode.
Andrei Popescu402d9372010-02-26 13:31:12 +00001134 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
Steve Blocka7e24c12009-10-30 11:49:00 +00001135 // If the pre-data isn't sane we simply ignore it
Andrei Popescu402d9372010-02-26 13:31:12 +00001136 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
1137 pre_data_impl = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00001138 }
Andrei Popescu31002712010-02-23 13:46:05 +00001139 i::Handle<i::JSFunction> boilerplate =
1140 i::Compiler::Compile(str,
1141 name_obj,
1142 line_offset,
1143 column_offset,
1144 NULL,
Andrei Popescu402d9372010-02-26 13:31:12 +00001145 pre_data_impl,
1146 Utils::OpenHandle(*script_data),
Andrei Popescu31002712010-02-23 13:46:05 +00001147 i::NOT_NATIVES_CODE);
Steve Blocka7e24c12009-10-30 11:49:00 +00001148 has_pending_exception = boilerplate.is_null();
1149 EXCEPTION_BAILOUT_CHECK(Local<Script>());
1150 return Local<Script>(ToApi<Script>(boilerplate));
1151}
1152
1153
1154Local<Script> Script::New(v8::Handle<String> source,
1155 v8::Handle<Value> file_name) {
1156 ScriptOrigin origin(file_name);
1157 return New(source, &origin);
1158}
1159
1160
1161Local<Script> Script::Compile(v8::Handle<String> source,
1162 v8::ScriptOrigin* origin,
Andrei Popescu402d9372010-02-26 13:31:12 +00001163 v8::ScriptData* pre_data,
1164 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001165 ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
1166 LOG_API("Script::Compile");
1167 ENTER_V8;
Andrei Popescu402d9372010-02-26 13:31:12 +00001168 Local<Script> generic = New(source, origin, pre_data, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001169 if (generic.IsEmpty())
1170 return generic;
1171 i::Handle<i::JSFunction> boilerplate = Utils::OpenHandle(*generic);
1172 i::Handle<i::JSFunction> result =
1173 i::Factory::NewFunctionFromBoilerplate(boilerplate,
1174 i::Top::global_context());
1175 return Local<Script>(ToApi<Script>(result));
1176}
1177
1178
1179Local<Script> Script::Compile(v8::Handle<String> source,
Andrei Popescu402d9372010-02-26 13:31:12 +00001180 v8::Handle<Value> file_name,
1181 v8::Handle<String> script_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001182 ScriptOrigin origin(file_name);
Andrei Popescu402d9372010-02-26 13:31:12 +00001183 return Compile(source, &origin, 0, script_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001184}
1185
1186
1187Local<Value> Script::Run() {
1188 ON_BAILOUT("v8::Script::Run()", return Local<Value>());
1189 LOG_API("Script::Run");
1190 ENTER_V8;
1191 i::Object* raw_result = NULL;
1192 {
1193 HandleScope scope;
1194 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
1195 if (fun->IsBoilerplate()) {
1196 fun = i::Factory::NewFunctionFromBoilerplate(fun,
1197 i::Top::global_context());
1198 }
1199 EXCEPTION_PREAMBLE();
1200 i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
1201 i::Handle<i::Object> result =
1202 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
1203 EXCEPTION_BAILOUT_CHECK(Local<Value>());
1204 raw_result = *result;
1205 }
1206 i::Handle<i::Object> result(raw_result);
1207 return Utils::ToLocal(result);
1208}
1209
1210
1211Local<Value> Script::Id() {
1212 ON_BAILOUT("v8::Script::Id()", return Local<Value>());
1213 LOG_API("Script::Id");
1214 i::Object* raw_id = NULL;
1215 {
1216 HandleScope scope;
1217 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
1218 i::Handle<i::Script> script(i::Script::cast(fun->shared()->script()));
1219 i::Handle<i::Object> id(script->id());
1220 raw_id = *id;
1221 }
1222 i::Handle<i::Object> id(raw_id);
1223 return Utils::ToLocal(id);
1224}
1225
1226
Steve Blockd0582a62009-12-15 09:54:21 +00001227void Script::SetData(v8::Handle<String> data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001228 ON_BAILOUT("v8::Script::SetData()", return);
1229 LOG_API("Script::SetData");
1230 {
1231 HandleScope scope;
1232 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
1233 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
1234 i::Handle<i::Script> script(i::Script::cast(fun->shared()->script()));
1235 script->set_data(*raw_data);
1236 }
1237}
1238
1239
1240// --- E x c e p t i o n s ---
1241
1242
1243v8::TryCatch::TryCatch()
Steve Blockd0582a62009-12-15 09:54:21 +00001244 : next_(i::Top::try_catch_handler_address()),
Steve Blocka7e24c12009-10-30 11:49:00 +00001245 exception_(i::Heap::the_hole_value()),
1246 message_(i::Smi::FromInt(0)),
1247 is_verbose_(false),
1248 can_continue_(true),
1249 capture_message_(true),
Steve Blockd0582a62009-12-15 09:54:21 +00001250 rethrow_(false) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001251 i::Top::RegisterTryCatchHandler(this);
1252}
1253
1254
1255v8::TryCatch::~TryCatch() {
Steve Blockd0582a62009-12-15 09:54:21 +00001256 if (rethrow_) {
1257 v8::HandleScope scope;
1258 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
1259 i::Top::UnregisterTryCatchHandler(this);
1260 v8::ThrowException(exc);
1261 } else {
1262 i::Top::UnregisterTryCatchHandler(this);
1263 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001264}
1265
1266
1267bool v8::TryCatch::HasCaught() const {
1268 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1269}
1270
1271
1272bool v8::TryCatch::CanContinue() const {
1273 return can_continue_;
1274}
1275
1276
Steve Blockd0582a62009-12-15 09:54:21 +00001277v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1278 if (!HasCaught()) return v8::Local<v8::Value>();
1279 rethrow_ = true;
1280 return v8::Undefined();
1281}
1282
1283
Steve Blocka7e24c12009-10-30 11:49:00 +00001284v8::Local<Value> v8::TryCatch::Exception() const {
1285 if (HasCaught()) {
1286 // Check for out of memory exception.
1287 i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1288 return v8::Utils::ToLocal(i::Handle<i::Object>(exception));
1289 } else {
1290 return v8::Local<Value>();
1291 }
1292}
1293
1294
1295v8::Local<Value> v8::TryCatch::StackTrace() const {
1296 if (HasCaught()) {
1297 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1298 if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1299 v8::HandleScope scope;
1300 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
1301 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
1302 if (!obj->HasProperty(*name))
1303 return v8::Local<Value>();
1304 return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
1305 } else {
1306 return v8::Local<Value>();
1307 }
1308}
1309
1310
1311v8::Local<v8::Message> v8::TryCatch::Message() const {
1312 if (HasCaught() && message_ != i::Smi::FromInt(0)) {
1313 i::Object* message = reinterpret_cast<i::Object*>(message_);
1314 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message));
1315 } else {
1316 return v8::Local<v8::Message>();
1317 }
1318}
1319
1320
1321void v8::TryCatch::Reset() {
1322 exception_ = i::Heap::the_hole_value();
1323 message_ = i::Smi::FromInt(0);
1324}
1325
1326
1327void v8::TryCatch::SetVerbose(bool value) {
1328 is_verbose_ = value;
1329}
1330
1331
1332void v8::TryCatch::SetCaptureMessage(bool value) {
1333 capture_message_ = value;
1334}
1335
1336
1337// --- M e s s a g e ---
1338
1339
1340Local<String> Message::Get() const {
1341 ON_BAILOUT("v8::Message::Get()", return Local<String>());
1342 ENTER_V8;
1343 HandleScope scope;
1344 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1345 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj);
1346 Local<String> result = Utils::ToLocal(raw_result);
1347 return scope.Close(result);
1348}
1349
1350
1351v8::Handle<Value> Message::GetScriptResourceName() const {
1352 if (IsDeadCheck("v8::Message::GetScriptResourceName()")) {
1353 return Local<String>();
1354 }
1355 ENTER_V8;
1356 HandleScope scope;
1357 i::Handle<i::JSObject> obj =
1358 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1359 // Return this.script.name.
1360 i::Handle<i::JSValue> script =
1361 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1362 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name());
1363 return scope.Close(Utils::ToLocal(resource_name));
1364}
1365
1366
1367v8::Handle<Value> Message::GetScriptData() const {
1368 if (IsDeadCheck("v8::Message::GetScriptResourceData()")) {
1369 return Local<Value>();
1370 }
1371 ENTER_V8;
1372 HandleScope scope;
1373 i::Handle<i::JSObject> obj =
1374 i::Handle<i::JSObject>::cast(Utils::OpenHandle(this));
1375 // Return this.script.data.
1376 i::Handle<i::JSValue> script =
1377 i::Handle<i::JSValue>::cast(GetProperty(obj, "script"));
1378 i::Handle<i::Object> data(i::Script::cast(script->value())->data());
1379 return scope.Close(Utils::ToLocal(data));
1380}
1381
1382
1383static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1384 i::Handle<i::Object> recv,
1385 int argc,
1386 i::Object** argv[],
1387 bool* has_pending_exception) {
1388 i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
1389 i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str);
1390 i::Handle<i::JSFunction> fun =
1391 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
1392 i::Handle<i::Object> value =
1393 i::Execution::Call(fun, recv, argc, argv, has_pending_exception);
1394 return value;
1395}
1396
1397
1398static i::Handle<i::Object> CallV8HeapFunction(const char* name,
1399 i::Handle<i::Object> data,
1400 bool* has_pending_exception) {
1401 i::Object** argv[1] = { data.location() };
1402 return CallV8HeapFunction(name,
1403 i::Top::builtins(),
1404 1,
1405 argv,
1406 has_pending_exception);
1407}
1408
1409
1410int Message::GetLineNumber() const {
1411 ON_BAILOUT("v8::Message::GetLineNumber()", return -1);
1412 ENTER_V8;
1413 HandleScope scope;
1414 EXCEPTION_PREAMBLE();
1415 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
1416 Utils::OpenHandle(this),
1417 &has_pending_exception);
1418 EXCEPTION_BAILOUT_CHECK(0);
1419 return static_cast<int>(result->Number());
1420}
1421
1422
1423int Message::GetStartPosition() const {
1424 if (IsDeadCheck("v8::Message::GetStartPosition()")) return 0;
1425 ENTER_V8;
1426 HandleScope scope;
1427
1428 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1429 return static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1430}
1431
1432
1433int Message::GetEndPosition() const {
1434 if (IsDeadCheck("v8::Message::GetEndPosition()")) return 0;
1435 ENTER_V8;
1436 HandleScope scope;
1437 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1438 return static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1439}
1440
1441
1442int Message::GetStartColumn() const {
1443 if (IsDeadCheck("v8::Message::GetStartColumn()")) return 0;
1444 ENTER_V8;
1445 HandleScope scope;
1446 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1447 EXCEPTION_PREAMBLE();
1448 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1449 "GetPositionInLine",
1450 data_obj,
1451 &has_pending_exception);
1452 EXCEPTION_BAILOUT_CHECK(0);
1453 return static_cast<int>(start_col_obj->Number());
1454}
1455
1456
1457int Message::GetEndColumn() const {
1458 if (IsDeadCheck("v8::Message::GetEndColumn()")) return 0;
1459 ENTER_V8;
1460 HandleScope scope;
1461 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
1462 EXCEPTION_PREAMBLE();
1463 i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
1464 "GetPositionInLine",
1465 data_obj,
1466 &has_pending_exception);
1467 EXCEPTION_BAILOUT_CHECK(0);
1468 int start = static_cast<int>(GetProperty(data_obj, "startPos")->Number());
1469 int end = static_cast<int>(GetProperty(data_obj, "endPos")->Number());
1470 return static_cast<int>(start_col_obj->Number()) + (end - start);
1471}
1472
1473
1474Local<String> Message::GetSourceLine() const {
1475 ON_BAILOUT("v8::Message::GetSourceLine()", return Local<String>());
1476 ENTER_V8;
1477 HandleScope scope;
1478 EXCEPTION_PREAMBLE();
1479 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
1480 Utils::OpenHandle(this),
1481 &has_pending_exception);
1482 EXCEPTION_BAILOUT_CHECK(Local<v8::String>());
1483 if (result->IsString()) {
1484 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
1485 } else {
1486 return Local<String>();
1487 }
1488}
1489
1490
1491void Message::PrintCurrentStackTrace(FILE* out) {
1492 if (IsDeadCheck("v8::Message::PrintCurrentStackTrace()")) return;
1493 ENTER_V8;
1494 i::Top::PrintCurrentStackTrace(out);
1495}
1496
1497
1498// --- D a t a ---
1499
1500bool Value::IsUndefined() const {
1501 if (IsDeadCheck("v8::Value::IsUndefined()")) return false;
1502 return Utils::OpenHandle(this)->IsUndefined();
1503}
1504
1505
1506bool Value::IsNull() const {
1507 if (IsDeadCheck("v8::Value::IsNull()")) return false;
1508 return Utils::OpenHandle(this)->IsNull();
1509}
1510
1511
1512bool Value::IsTrue() const {
1513 if (IsDeadCheck("v8::Value::IsTrue()")) return false;
1514 return Utils::OpenHandle(this)->IsTrue();
1515}
1516
1517
1518bool Value::IsFalse() const {
1519 if (IsDeadCheck("v8::Value::IsFalse()")) return false;
1520 return Utils::OpenHandle(this)->IsFalse();
1521}
1522
1523
1524bool Value::IsFunction() const {
1525 if (IsDeadCheck("v8::Value::IsFunction()")) return false;
1526 return Utils::OpenHandle(this)->IsJSFunction();
1527}
1528
1529
1530bool Value::FullIsString() const {
1531 if (IsDeadCheck("v8::Value::IsString()")) return false;
1532 bool result = Utils::OpenHandle(this)->IsString();
1533 ASSERT_EQ(result, QuickIsString());
1534 return result;
1535}
1536
1537
1538bool Value::IsArray() const {
1539 if (IsDeadCheck("v8::Value::IsArray()")) return false;
1540 return Utils::OpenHandle(this)->IsJSArray();
1541}
1542
1543
1544bool Value::IsObject() const {
1545 if (IsDeadCheck("v8::Value::IsObject()")) return false;
1546 return Utils::OpenHandle(this)->IsJSObject();
1547}
1548
1549
1550bool Value::IsNumber() const {
1551 if (IsDeadCheck("v8::Value::IsNumber()")) return false;
1552 return Utils::OpenHandle(this)->IsNumber();
1553}
1554
1555
1556bool Value::IsBoolean() const {
1557 if (IsDeadCheck("v8::Value::IsBoolean()")) return false;
1558 return Utils::OpenHandle(this)->IsBoolean();
1559}
1560
1561
1562bool Value::IsExternal() const {
1563 if (IsDeadCheck("v8::Value::IsExternal()")) return false;
1564 return Utils::OpenHandle(this)->IsProxy();
1565}
1566
1567
1568bool Value::IsInt32() const {
1569 if (IsDeadCheck("v8::Value::IsInt32()")) return false;
1570 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1571 if (obj->IsSmi()) return true;
1572 if (obj->IsNumber()) {
1573 double value = obj->Number();
1574 return i::FastI2D(i::FastD2I(value)) == value;
1575 }
1576 return false;
1577}
1578
1579
1580bool Value::IsDate() const {
1581 if (IsDeadCheck("v8::Value::IsDate()")) return false;
1582 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1583 return obj->HasSpecificClassOf(i::Heap::Date_symbol());
1584}
1585
1586
1587Local<String> Value::ToString() const {
1588 if (IsDeadCheck("v8::Value::ToString()")) return Local<String>();
1589 LOG_API("ToString");
1590 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1591 i::Handle<i::Object> str;
1592 if (obj->IsString()) {
1593 str = obj;
1594 } else {
1595 ENTER_V8;
1596 EXCEPTION_PREAMBLE();
1597 str = i::Execution::ToString(obj, &has_pending_exception);
1598 EXCEPTION_BAILOUT_CHECK(Local<String>());
1599 }
1600 return Local<String>(ToApi<String>(str));
1601}
1602
1603
1604Local<String> Value::ToDetailString() const {
1605 if (IsDeadCheck("v8::Value::ToDetailString()")) return Local<String>();
1606 LOG_API("ToDetailString");
1607 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1608 i::Handle<i::Object> str;
1609 if (obj->IsString()) {
1610 str = obj;
1611 } else {
1612 ENTER_V8;
1613 EXCEPTION_PREAMBLE();
1614 str = i::Execution::ToDetailString(obj, &has_pending_exception);
1615 EXCEPTION_BAILOUT_CHECK(Local<String>());
1616 }
1617 return Local<String>(ToApi<String>(str));
1618}
1619
1620
1621Local<v8::Object> Value::ToObject() const {
1622 if (IsDeadCheck("v8::Value::ToObject()")) return Local<v8::Object>();
1623 LOG_API("ToObject");
1624 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1625 i::Handle<i::Object> val;
1626 if (obj->IsJSObject()) {
1627 val = obj;
1628 } else {
1629 ENTER_V8;
1630 EXCEPTION_PREAMBLE();
1631 val = i::Execution::ToObject(obj, &has_pending_exception);
1632 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
1633 }
1634 return Local<v8::Object>(ToApi<Object>(val));
1635}
1636
1637
1638Local<Boolean> Value::ToBoolean() const {
1639 if (IsDeadCheck("v8::Value::ToBoolean()")) return Local<Boolean>();
1640 LOG_API("ToBoolean");
1641 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1642 if (obj->IsBoolean()) {
1643 return Local<Boolean>(ToApi<Boolean>(obj));
1644 } else {
1645 ENTER_V8;
1646 i::Handle<i::Object> val = i::Execution::ToBoolean(obj);
1647 return Local<Boolean>(ToApi<Boolean>(val));
1648 }
1649}
1650
1651
1652Local<Number> Value::ToNumber() const {
1653 if (IsDeadCheck("v8::Value::ToNumber()")) return Local<Number>();
1654 LOG_API("ToNumber");
1655 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1656 i::Handle<i::Object> num;
1657 if (obj->IsNumber()) {
1658 num = obj;
1659 } else {
1660 ENTER_V8;
1661 EXCEPTION_PREAMBLE();
1662 num = i::Execution::ToNumber(obj, &has_pending_exception);
1663 EXCEPTION_BAILOUT_CHECK(Local<Number>());
1664 }
1665 return Local<Number>(ToApi<Number>(num));
1666}
1667
1668
1669Local<Integer> Value::ToInteger() const {
1670 if (IsDeadCheck("v8::Value::ToInteger()")) return Local<Integer>();
1671 LOG_API("ToInteger");
1672 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1673 i::Handle<i::Object> num;
1674 if (obj->IsSmi()) {
1675 num = obj;
1676 } else {
1677 ENTER_V8;
1678 EXCEPTION_PREAMBLE();
1679 num = i::Execution::ToInteger(obj, &has_pending_exception);
1680 EXCEPTION_BAILOUT_CHECK(Local<Integer>());
1681 }
1682 return Local<Integer>(ToApi<Integer>(num));
1683}
1684
1685
1686void External::CheckCast(v8::Value* that) {
1687 if (IsDeadCheck("v8::External::Cast()")) return;
1688 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1689 ApiCheck(obj->IsProxy(),
1690 "v8::External::Cast()",
1691 "Could not convert to external");
1692}
1693
1694
1695void v8::Object::CheckCast(Value* that) {
1696 if (IsDeadCheck("v8::Object::Cast()")) return;
1697 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1698 ApiCheck(obj->IsJSObject(),
1699 "v8::Object::Cast()",
1700 "Could not convert to object");
1701}
1702
1703
1704void v8::Function::CheckCast(Value* that) {
1705 if (IsDeadCheck("v8::Function::Cast()")) return;
1706 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1707 ApiCheck(obj->IsJSFunction(),
1708 "v8::Function::Cast()",
1709 "Could not convert to function");
1710}
1711
1712
1713void v8::String::CheckCast(v8::Value* that) {
1714 if (IsDeadCheck("v8::String::Cast()")) return;
1715 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1716 ApiCheck(obj->IsString(),
1717 "v8::String::Cast()",
1718 "Could not convert to string");
1719}
1720
1721
1722void v8::Number::CheckCast(v8::Value* that) {
1723 if (IsDeadCheck("v8::Number::Cast()")) return;
1724 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1725 ApiCheck(obj->IsNumber(),
1726 "v8::Number::Cast()",
1727 "Could not convert to number");
1728}
1729
1730
1731void v8::Integer::CheckCast(v8::Value* that) {
1732 if (IsDeadCheck("v8::Integer::Cast()")) return;
1733 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1734 ApiCheck(obj->IsNumber(),
1735 "v8::Integer::Cast()",
1736 "Could not convert to number");
1737}
1738
1739
1740void v8::Array::CheckCast(Value* that) {
1741 if (IsDeadCheck("v8::Array::Cast()")) return;
1742 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1743 ApiCheck(obj->IsJSArray(),
1744 "v8::Array::Cast()",
1745 "Could not convert to array");
1746}
1747
1748
1749void v8::Date::CheckCast(v8::Value* that) {
1750 if (IsDeadCheck("v8::Date::Cast()")) return;
1751 i::Handle<i::Object> obj = Utils::OpenHandle(that);
1752 ApiCheck(obj->HasSpecificClassOf(i::Heap::Date_symbol()),
1753 "v8::Date::Cast()",
1754 "Could not convert to date");
1755}
1756
1757
1758bool Value::BooleanValue() const {
1759 if (IsDeadCheck("v8::Value::BooleanValue()")) return false;
1760 LOG_API("BooleanValue");
1761 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1762 if (obj->IsBoolean()) {
1763 return obj->IsTrue();
1764 } else {
1765 ENTER_V8;
1766 i::Handle<i::Object> value = i::Execution::ToBoolean(obj);
1767 return value->IsTrue();
1768 }
1769}
1770
1771
1772double Value::NumberValue() const {
1773 if (IsDeadCheck("v8::Value::NumberValue()")) return i::OS::nan_value();
1774 LOG_API("NumberValue");
1775 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1776 i::Handle<i::Object> num;
1777 if (obj->IsNumber()) {
1778 num = obj;
1779 } else {
1780 ENTER_V8;
1781 EXCEPTION_PREAMBLE();
1782 num = i::Execution::ToNumber(obj, &has_pending_exception);
1783 EXCEPTION_BAILOUT_CHECK(i::OS::nan_value());
1784 }
1785 return num->Number();
1786}
1787
1788
1789int64_t Value::IntegerValue() const {
1790 if (IsDeadCheck("v8::Value::IntegerValue()")) return 0;
1791 LOG_API("IntegerValue");
1792 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1793 i::Handle<i::Object> num;
1794 if (obj->IsNumber()) {
1795 num = obj;
1796 } else {
1797 ENTER_V8;
1798 EXCEPTION_PREAMBLE();
1799 num = i::Execution::ToInteger(obj, &has_pending_exception);
1800 EXCEPTION_BAILOUT_CHECK(0);
1801 }
1802 if (num->IsSmi()) {
1803 return i::Smi::cast(*num)->value();
1804 } else {
1805 return static_cast<int64_t>(num->Number());
1806 }
1807}
1808
1809
1810Local<Int32> Value::ToInt32() const {
1811 if (IsDeadCheck("v8::Value::ToInt32()")) return Local<Int32>();
1812 LOG_API("ToInt32");
1813 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1814 i::Handle<i::Object> num;
1815 if (obj->IsSmi()) {
1816 num = obj;
1817 } else {
1818 ENTER_V8;
1819 EXCEPTION_PREAMBLE();
1820 num = i::Execution::ToInt32(obj, &has_pending_exception);
1821 EXCEPTION_BAILOUT_CHECK(Local<Int32>());
1822 }
1823 return Local<Int32>(ToApi<Int32>(num));
1824}
1825
1826
1827Local<Uint32> Value::ToUint32() const {
1828 if (IsDeadCheck("v8::Value::ToUint32()")) return Local<Uint32>();
1829 LOG_API("ToUInt32");
1830 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1831 i::Handle<i::Object> num;
1832 if (obj->IsSmi()) {
1833 num = obj;
1834 } else {
1835 ENTER_V8;
1836 EXCEPTION_PREAMBLE();
1837 num = i::Execution::ToUint32(obj, &has_pending_exception);
1838 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
1839 }
1840 return Local<Uint32>(ToApi<Uint32>(num));
1841}
1842
1843
1844Local<Uint32> Value::ToArrayIndex() const {
1845 if (IsDeadCheck("v8::Value::ToArrayIndex()")) return Local<Uint32>();
1846 LOG_API("ToArrayIndex");
1847 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1848 if (obj->IsSmi()) {
1849 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
1850 return Local<Uint32>();
1851 }
1852 ENTER_V8;
1853 EXCEPTION_PREAMBLE();
1854 i::Handle<i::Object> string_obj =
1855 i::Execution::ToString(obj, &has_pending_exception);
1856 EXCEPTION_BAILOUT_CHECK(Local<Uint32>());
1857 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
1858 uint32_t index;
1859 if (str->AsArrayIndex(&index)) {
1860 i::Handle<i::Object> value;
1861 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
1862 value = i::Handle<i::Object>(i::Smi::FromInt(index));
1863 } else {
1864 value = i::Factory::NewNumber(index);
1865 }
1866 return Utils::Uint32ToLocal(value);
1867 }
1868 return Local<Uint32>();
1869}
1870
1871
1872int32_t Value::Int32Value() const {
1873 if (IsDeadCheck("v8::Value::Int32Value()")) return 0;
1874 LOG_API("Int32Value");
1875 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1876 if (obj->IsSmi()) {
1877 return i::Smi::cast(*obj)->value();
1878 } else {
1879 LOG_API("Int32Value (slow)");
1880 ENTER_V8;
1881 EXCEPTION_PREAMBLE();
1882 i::Handle<i::Object> num =
1883 i::Execution::ToInt32(obj, &has_pending_exception);
1884 EXCEPTION_BAILOUT_CHECK(0);
1885 if (num->IsSmi()) {
1886 return i::Smi::cast(*num)->value();
1887 } else {
1888 return static_cast<int32_t>(num->Number());
1889 }
1890 }
1891}
1892
1893
1894bool Value::Equals(Handle<Value> that) const {
1895 if (IsDeadCheck("v8::Value::Equals()")
1896 || EmptyCheck("v8::Value::Equals()", this)
1897 || EmptyCheck("v8::Value::Equals()", that)) {
1898 return false;
1899 }
1900 LOG_API("Equals");
1901 ENTER_V8;
1902 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1903 i::Handle<i::Object> other = Utils::OpenHandle(*that);
1904 i::Object** args[1] = { other.location() };
1905 EXCEPTION_PREAMBLE();
1906 i::Handle<i::Object> result =
1907 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception);
1908 EXCEPTION_BAILOUT_CHECK(false);
1909 return *result == i::Smi::FromInt(i::EQUAL);
1910}
1911
1912
1913bool Value::StrictEquals(Handle<Value> that) const {
1914 if (IsDeadCheck("v8::Value::StrictEquals()")
1915 || EmptyCheck("v8::Value::StrictEquals()", this)
1916 || EmptyCheck("v8::Value::StrictEquals()", that)) {
1917 return false;
1918 }
1919 LOG_API("StrictEquals");
1920 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1921 i::Handle<i::Object> other = Utils::OpenHandle(*that);
1922 // Must check HeapNumber first, since NaN !== NaN.
1923 if (obj->IsHeapNumber()) {
1924 if (!other->IsNumber()) return false;
1925 double x = obj->Number();
1926 double y = other->Number();
1927 // Must check explicitly for NaN:s on Windows, but -0 works fine.
1928 return x == y && !isnan(x) && !isnan(y);
1929 } else if (*obj == *other) { // Also covers Booleans.
1930 return true;
1931 } else if (obj->IsSmi()) {
1932 return other->IsNumber() && obj->Number() == other->Number();
1933 } else if (obj->IsString()) {
1934 return other->IsString() &&
1935 i::String::cast(*obj)->Equals(i::String::cast(*other));
1936 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
1937 return other->IsUndefined() || other->IsUndetectableObject();
1938 } else {
1939 return false;
1940 }
1941}
1942
1943
1944uint32_t Value::Uint32Value() const {
1945 if (IsDeadCheck("v8::Value::Uint32Value()")) return 0;
1946 LOG_API("Uint32Value");
1947 i::Handle<i::Object> obj = Utils::OpenHandle(this);
1948 if (obj->IsSmi()) {
1949 return i::Smi::cast(*obj)->value();
1950 } else {
1951 ENTER_V8;
1952 EXCEPTION_PREAMBLE();
1953 i::Handle<i::Object> num =
1954 i::Execution::ToUint32(obj, &has_pending_exception);
1955 EXCEPTION_BAILOUT_CHECK(0);
1956 if (num->IsSmi()) {
1957 return i::Smi::cast(*num)->value();
1958 } else {
1959 return static_cast<uint32_t>(num->Number());
1960 }
1961 }
1962}
1963
1964
1965bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
1966 v8::PropertyAttribute attribs) {
1967 ON_BAILOUT("v8::Object::Set()", return false);
1968 ENTER_V8;
1969 HandleScope scope;
1970 i::Handle<i::Object> self = Utils::OpenHandle(this);
1971 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
1972 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
1973 EXCEPTION_PREAMBLE();
1974 i::Handle<i::Object> obj = i::SetProperty(
1975 self,
1976 key_obj,
1977 value_obj,
1978 static_cast<PropertyAttributes>(attribs));
1979 has_pending_exception = obj.is_null();
1980 EXCEPTION_BAILOUT_CHECK(false);
1981 return true;
1982}
1983
1984
1985bool v8::Object::ForceSet(v8::Handle<Value> key,
1986 v8::Handle<Value> value,
1987 v8::PropertyAttribute attribs) {
1988 ON_BAILOUT("v8::Object::ForceSet()", return false);
1989 ENTER_V8;
1990 HandleScope scope;
1991 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
1992 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
1993 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
1994 EXCEPTION_PREAMBLE();
1995 i::Handle<i::Object> obj = i::ForceSetProperty(
1996 self,
1997 key_obj,
1998 value_obj,
1999 static_cast<PropertyAttributes>(attribs));
2000 has_pending_exception = obj.is_null();
2001 EXCEPTION_BAILOUT_CHECK(false);
2002 return true;
2003}
2004
2005
2006bool v8::Object::ForceDelete(v8::Handle<Value> key) {
2007 ON_BAILOUT("v8::Object::ForceDelete()", return false);
2008 ENTER_V8;
2009 HandleScope scope;
2010 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2011 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2012 EXCEPTION_PREAMBLE();
2013 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
2014 has_pending_exception = obj.is_null();
2015 EXCEPTION_BAILOUT_CHECK(false);
2016 return obj->IsTrue();
2017}
2018
2019
2020Local<Value> v8::Object::Get(v8::Handle<Value> key) {
2021 ON_BAILOUT("v8::Object::Get()", return Local<v8::Value>());
2022 ENTER_V8;
2023 i::Handle<i::Object> self = Utils::OpenHandle(this);
2024 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2025 EXCEPTION_PREAMBLE();
2026 i::Handle<i::Object> result = i::GetProperty(self, key_obj);
2027 has_pending_exception = result.is_null();
2028 EXCEPTION_BAILOUT_CHECK(Local<Value>());
2029 return Utils::ToLocal(result);
2030}
2031
2032
2033Local<Value> v8::Object::GetPrototype() {
2034 ON_BAILOUT("v8::Object::GetPrototype()", return Local<v8::Value>());
2035 ENTER_V8;
2036 i::Handle<i::Object> self = Utils::OpenHandle(this);
2037 i::Handle<i::Object> result = i::GetPrototype(self);
2038 return Utils::ToLocal(result);
2039}
2040
2041
Andrei Popescu402d9372010-02-26 13:31:12 +00002042bool v8::Object::SetPrototype(Handle<Value> value) {
2043 ON_BAILOUT("v8::Object::SetPrototype()", return false);
2044 ENTER_V8;
2045 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2046 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2047 EXCEPTION_PREAMBLE();
2048 i::Handle<i::Object> result = i::SetPrototype(self, value_obj);
2049 has_pending_exception = result.is_null();
2050 EXCEPTION_BAILOUT_CHECK(false);
2051 return true;
2052}
2053
2054
Steve Blocka7e24c12009-10-30 11:49:00 +00002055Local<Object> v8::Object::FindInstanceInPrototypeChain(
2056 v8::Handle<FunctionTemplate> tmpl) {
2057 ON_BAILOUT("v8::Object::FindInstanceInPrototypeChain()",
2058 return Local<v8::Object>());
2059 ENTER_V8;
2060 i::JSObject* object = *Utils::OpenHandle(this);
2061 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
2062 while (!object->IsInstanceOf(tmpl_info)) {
2063 i::Object* prototype = object->GetPrototype();
2064 if (!prototype->IsJSObject()) return Local<Object>();
2065 object = i::JSObject::cast(prototype);
2066 }
2067 return Utils::ToLocal(i::Handle<i::JSObject>(object));
2068}
2069
2070
2071Local<Array> v8::Object::GetPropertyNames() {
2072 ON_BAILOUT("v8::Object::GetPropertyNames()", return Local<v8::Array>());
2073 ENTER_V8;
2074 v8::HandleScope scope;
2075 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2076 i::Handle<i::FixedArray> value =
2077 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS);
2078 // Because we use caching to speed up enumeration it is important
2079 // to never change the result of the basic enumeration function so
2080 // we clone the result.
2081 i::Handle<i::FixedArray> elms = i::Factory::CopyFixedArray(value);
2082 i::Handle<i::JSArray> result = i::Factory::NewJSArrayWithElements(elms);
2083 return scope.Close(Utils::ToLocal(result));
2084}
2085
2086
2087Local<String> v8::Object::ObjectProtoToString() {
2088 ON_BAILOUT("v8::Object::ObjectProtoToString()", return Local<v8::String>());
2089 ENTER_V8;
2090 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2091
2092 i::Handle<i::Object> name(self->class_name());
2093
2094 // Native implementation of Object.prototype.toString (v8natives.js):
2095 // var c = %ClassOf(this);
2096 // if (c === 'Arguments') c = 'Object';
2097 // return "[object " + c + "]";
2098
2099 if (!name->IsString()) {
2100 return v8::String::New("[object ]");
2101
2102 } else {
2103 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
2104 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
2105 return v8::String::New("[object Object]");
2106
2107 } else {
2108 const char* prefix = "[object ";
2109 Local<String> str = Utils::ToLocal(class_name);
2110 const char* postfix = "]";
2111
Steve Blockd0582a62009-12-15 09:54:21 +00002112 int prefix_len = i::StrLength(prefix);
2113 int str_len = str->Length();
2114 int postfix_len = i::StrLength(postfix);
Steve Blocka7e24c12009-10-30 11:49:00 +00002115
Steve Blockd0582a62009-12-15 09:54:21 +00002116 int buf_len = prefix_len + str_len + postfix_len;
Steve Blocka7e24c12009-10-30 11:49:00 +00002117 char* buf = i::NewArray<char>(buf_len);
2118
2119 // Write prefix.
2120 char* ptr = buf;
2121 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize);
2122 ptr += prefix_len;
2123
2124 // Write real content.
2125 str->WriteAscii(ptr, 0, str_len);
2126 ptr += str_len;
2127
2128 // Write postfix.
2129 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize);
2130
2131 // Copy the buffer into a heap-allocated string and return it.
2132 Local<String> result = v8::String::New(buf, buf_len);
2133 i::DeleteArray(buf);
2134 return result;
2135 }
2136 }
2137}
2138
2139
2140bool v8::Object::Delete(v8::Handle<String> key) {
2141 ON_BAILOUT("v8::Object::Delete()", return false);
2142 ENTER_V8;
2143 HandleScope scope;
2144 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2145 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2146 return i::DeleteProperty(self, key_obj)->IsTrue();
2147}
2148
2149
2150bool v8::Object::Has(v8::Handle<String> key) {
2151 ON_BAILOUT("v8::Object::Has()", return false);
2152 ENTER_V8;
2153 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2154 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2155 return self->HasProperty(*key_obj);
2156}
2157
2158
2159bool v8::Object::Delete(uint32_t index) {
2160 ON_BAILOUT("v8::Object::DeleteProperty()", return false);
2161 ENTER_V8;
2162 HandleScope scope;
2163 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2164 return i::DeleteElement(self, index)->IsTrue();
2165}
2166
2167
2168bool v8::Object::Has(uint32_t index) {
2169 ON_BAILOUT("v8::Object::HasProperty()", return false);
2170 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2171 return self->HasElement(index);
2172}
2173
2174
2175bool v8::Object::HasRealNamedProperty(Handle<String> key) {
2176 ON_BAILOUT("v8::Object::HasRealNamedProperty()", return false);
2177 return Utils::OpenHandle(this)->HasRealNamedProperty(
2178 *Utils::OpenHandle(*key));
2179}
2180
2181
2182bool v8::Object::HasRealIndexedProperty(uint32_t index) {
2183 ON_BAILOUT("v8::Object::HasRealIndexedProperty()", return false);
2184 return Utils::OpenHandle(this)->HasRealElementProperty(index);
2185}
2186
2187
2188bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
2189 ON_BAILOUT("v8::Object::HasRealNamedCallbackProperty()", return false);
2190 ENTER_V8;
2191 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty(
2192 *Utils::OpenHandle(*key));
2193}
2194
2195
2196bool v8::Object::HasNamedLookupInterceptor() {
2197 ON_BAILOUT("v8::Object::HasNamedLookupInterceptor()", return false);
2198 return Utils::OpenHandle(this)->HasNamedInterceptor();
2199}
2200
2201
2202bool v8::Object::HasIndexedLookupInterceptor() {
2203 ON_BAILOUT("v8::Object::HasIndexedLookupInterceptor()", return false);
2204 return Utils::OpenHandle(this)->HasIndexedInterceptor();
2205}
2206
2207
2208Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
2209 Handle<String> key) {
2210 ON_BAILOUT("v8::Object::GetRealNamedPropertyInPrototypeChain()",
2211 return Local<Value>());
2212 ENTER_V8;
2213 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2214 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2215 i::LookupResult lookup;
2216 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002217 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002218 PropertyAttributes attributes;
2219 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2220 &lookup,
2221 *key_obj,
2222 &attributes));
2223 return Utils::ToLocal(result);
2224 }
2225 return Local<Value>(); // No real property was found in prototype chain.
2226}
2227
2228
2229Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
2230 ON_BAILOUT("v8::Object::GetRealNamedProperty()", return Local<Value>());
2231 ENTER_V8;
2232 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
2233 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2234 i::LookupResult lookup;
2235 self_obj->LookupRealNamedProperty(*key_obj, &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +00002236 if (lookup.IsProperty()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002237 PropertyAttributes attributes;
2238 i::Handle<i::Object> result(self_obj->GetProperty(*self_obj,
2239 &lookup,
2240 *key_obj,
2241 &attributes));
2242 return Utils::ToLocal(result);
2243 }
2244 return Local<Value>(); // No real property was found in prototype chain.
2245}
2246
2247
2248// Turns on access checks by copying the map and setting the check flag.
2249// Because the object gets a new map, existing inline cache caching
2250// the old map of this object will fail.
2251void v8::Object::TurnOnAccessCheck() {
2252 ON_BAILOUT("v8::Object::TurnOnAccessCheck()", return);
2253 ENTER_V8;
2254 HandleScope scope;
2255 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2256
2257 i::Handle<i::Map> new_map =
2258 i::Factory::CopyMapDropTransitions(i::Handle<i::Map>(obj->map()));
2259 new_map->set_is_access_check_needed(true);
2260 obj->set_map(*new_map);
2261}
2262
2263
2264bool v8::Object::IsDirty() {
2265 return Utils::OpenHandle(this)->IsDirty();
2266}
2267
2268
2269Local<v8::Object> v8::Object::Clone() {
2270 ON_BAILOUT("v8::Object::Clone()", return Local<Object>());
2271 ENTER_V8;
2272 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2273 EXCEPTION_PREAMBLE();
2274 i::Handle<i::JSObject> result = i::Copy(self);
2275 has_pending_exception = result.is_null();
2276 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2277 return Utils::ToLocal(result);
2278}
2279
2280
2281int v8::Object::GetIdentityHash() {
2282 ON_BAILOUT("v8::Object::GetIdentityHash()", return 0);
2283 ENTER_V8;
2284 HandleScope scope;
2285 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2286 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2287 i::Handle<i::Object> hash_symbol = i::Factory::identity_hash_symbol();
2288 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol);
2289 int hash_value;
2290 if (hash->IsSmi()) {
2291 hash_value = i::Smi::cast(*hash)->value();
2292 } else {
2293 int attempts = 0;
2294 do {
2295 // Generate a random 32-bit hash value but limit range to fit
2296 // within a smi.
2297 hash_value = i::V8::Random() & i::Smi::kMaxValue;
2298 attempts++;
2299 } while (hash_value == 0 && attempts < 30);
2300 hash_value = hash_value != 0 ? hash_value : 1; // never return 0
2301 i::SetProperty(hidden_props,
2302 hash_symbol,
2303 i::Handle<i::Object>(i::Smi::FromInt(hash_value)),
2304 static_cast<PropertyAttributes>(None));
2305 }
2306 return hash_value;
2307}
2308
2309
2310bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
2311 v8::Handle<v8::Value> value) {
2312 ON_BAILOUT("v8::Object::SetHiddenValue()", return false);
2313 ENTER_V8;
2314 HandleScope scope;
2315 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2316 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true));
2317 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
2318 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
2319 EXCEPTION_PREAMBLE();
2320 i::Handle<i::Object> obj = i::SetProperty(
2321 hidden_props,
2322 key_obj,
2323 value_obj,
2324 static_cast<PropertyAttributes>(None));
2325 has_pending_exception = obj.is_null();
2326 EXCEPTION_BAILOUT_CHECK(false);
2327 return true;
2328}
2329
2330
2331v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
2332 ON_BAILOUT("v8::Object::GetHiddenValue()", return Local<v8::Value>());
2333 ENTER_V8;
2334 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2335 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2336 if (hidden_props->IsUndefined()) {
2337 return v8::Local<v8::Value>();
2338 }
2339 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2340 EXCEPTION_PREAMBLE();
2341 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj);
2342 has_pending_exception = result.is_null();
2343 EXCEPTION_BAILOUT_CHECK(v8::Local<v8::Value>());
2344 if (result->IsUndefined()) {
2345 return v8::Local<v8::Value>();
2346 }
2347 return Utils::ToLocal(result);
2348}
2349
2350
2351bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
2352 ON_BAILOUT("v8::DeleteHiddenValue()", return false);
2353 ENTER_V8;
2354 HandleScope scope;
2355 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2356 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false));
2357 if (hidden_props->IsUndefined()) {
2358 return true;
2359 }
2360 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props));
2361 i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
2362 return i::DeleteProperty(js_obj, key_obj)->IsTrue();
2363}
2364
2365
2366void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
2367 ON_BAILOUT("v8::SetElementsToPixelData()", return);
2368 ENTER_V8;
2369 HandleScope scope;
Steve Block3ce2e202009-11-05 08:53:23 +00002370 if (!ApiCheck(length <= i::PixelArray::kMaxLength,
Steve Blocka7e24c12009-10-30 11:49:00 +00002371 "v8::Object::SetIndexedPropertiesToPixelData()",
2372 "length exceeds max acceptable value")) {
2373 return;
2374 }
2375 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2376 if (!ApiCheck(!self->IsJSArray(),
2377 "v8::Object::SetIndexedPropertiesToPixelData()",
2378 "JSArray is not supported")) {
2379 return;
2380 }
2381 i::Handle<i::PixelArray> pixels = i::Factory::NewPixelArray(length, data);
2382 self->set_elements(*pixels);
2383}
2384
2385
Steve Block3ce2e202009-11-05 08:53:23 +00002386void v8::Object::SetIndexedPropertiesToExternalArrayData(
2387 void* data,
2388 ExternalArrayType array_type,
2389 int length) {
2390 ON_BAILOUT("v8::SetIndexedPropertiesToExternalArrayData()", return);
2391 ENTER_V8;
2392 HandleScope scope;
2393 if (!ApiCheck(length <= i::ExternalArray::kMaxLength,
2394 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2395 "length exceeds max acceptable value")) {
2396 return;
2397 }
2398 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2399 if (!ApiCheck(!self->IsJSArray(),
2400 "v8::Object::SetIndexedPropertiesToExternalArrayData()",
2401 "JSArray is not supported")) {
2402 return;
2403 }
2404 i::Handle<i::ExternalArray> array =
2405 i::Factory::NewExternalArray(length, array_type, data);
2406 self->set_elements(*array);
2407}
2408
2409
Steve Blocka7e24c12009-10-30 11:49:00 +00002410Local<v8::Object> Function::NewInstance() const {
2411 return NewInstance(0, NULL);
2412}
2413
2414
2415Local<v8::Object> Function::NewInstance(int argc,
2416 v8::Handle<v8::Value> argv[]) const {
2417 ON_BAILOUT("v8::Function::NewInstance()", return Local<v8::Object>());
2418 LOG_API("Function::NewInstance");
2419 ENTER_V8;
2420 HandleScope scope;
2421 i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
2422 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2423 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2424 EXCEPTION_PREAMBLE();
2425 i::Handle<i::Object> returned =
2426 i::Execution::New(function, argc, args, &has_pending_exception);
2427 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
2428 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
2429}
2430
2431
2432Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
2433 v8::Handle<v8::Value> argv[]) {
2434 ON_BAILOUT("v8::Function::Call()", return Local<v8::Value>());
2435 LOG_API("Function::Call");
2436 ENTER_V8;
2437 i::Object* raw_result = NULL;
2438 {
2439 HandleScope scope;
2440 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
2441 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
2442 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
2443 i::Object*** args = reinterpret_cast<i::Object***>(argv);
2444 EXCEPTION_PREAMBLE();
2445 i::Handle<i::Object> returned =
2446 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
2447 EXCEPTION_BAILOUT_CHECK(Local<Object>());
2448 raw_result = *returned;
2449 }
2450 i::Handle<i::Object> result(raw_result);
2451 return Utils::ToLocal(result);
2452}
2453
2454
2455void Function::SetName(v8::Handle<v8::String> name) {
2456 ENTER_V8;
2457 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2458 func->shared()->set_name(*Utils::OpenHandle(*name));
2459}
2460
2461
2462Handle<Value> Function::GetName() const {
2463 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2464 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name()));
2465}
2466
2467
Andrei Popescu402d9372010-02-26 13:31:12 +00002468ScriptOrigin Function::GetScriptOrigin() const {
2469 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2470 if (func->shared()->script()->IsScript()) {
2471 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2472 v8::ScriptOrigin origin(
2473 Utils::ToLocal(i::Handle<i::Object>(script->name())),
2474 v8::Integer::New(script->line_offset()->value()),
2475 v8::Integer::New(script->column_offset()->value()));
2476 return origin;
2477 }
2478 return v8::ScriptOrigin(Handle<Value>());
2479}
2480
2481
2482const int Function::kLineOffsetNotFound = -1;
2483
2484
2485int Function::GetScriptLineNumber() const {
2486 i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
2487 if (func->shared()->script()->IsScript()) {
2488 i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
2489 return i::GetScriptLineNumber(script, func->shared()->start_position());
2490 }
2491 return kLineOffsetNotFound;
2492}
2493
2494
2495namespace {
2496
2497// Tracks string usage to help make better decisions when
2498// externalizing strings.
2499//
2500// Implementation note: internally this class only tracks fresh
2501// strings and keeps a single use counter for them.
2502class StringTracker {
2503 public:
2504 // Records that the given string's characters were copied to some
2505 // external buffer. If this happens often we should honor
2506 // externalization requests for the string.
2507 static void RecordWrite(i::Handle<i::String> string) {
2508 i::Address address = reinterpret_cast<i::Address>(*string);
2509 i::Address top = i::Heap::NewSpaceTop();
2510 if (IsFreshString(address, top)) {
2511 IncrementUseCount(top);
2512 }
2513 }
2514
2515 // Estimates freshness and use frequency of the given string based
2516 // on how close it is to the new space top and the recorded usage
2517 // history.
2518 static inline bool IsFreshUnusedString(i::Handle<i::String> string) {
2519 i::Address address = reinterpret_cast<i::Address>(*string);
2520 i::Address top = i::Heap::NewSpaceTop();
2521 return IsFreshString(address, top) && IsUseCountLow(top);
2522 }
2523
2524 private:
2525 static inline bool IsFreshString(i::Address string, i::Address top) {
2526 return top - kFreshnessLimit <= string && string <= top;
2527 }
2528
2529 static inline bool IsUseCountLow(i::Address top) {
2530 if (last_top_ != top) return true;
2531 return use_count_ < kUseLimit;
2532 }
2533
2534 static inline void IncrementUseCount(i::Address top) {
2535 if (last_top_ != top) {
2536 use_count_ = 0;
2537 last_top_ = top;
2538 }
2539 ++use_count_;
2540 }
2541
2542 // How close to the new space top a fresh string has to be.
2543 static const int kFreshnessLimit = 1024;
2544
2545 // The number of uses required to consider a string useful.
2546 static const int kUseLimit = 32;
2547
2548 // Single use counter shared by all fresh strings.
2549 static int use_count_;
2550
2551 // Last new space top when the use count above was valid.
2552 static i::Address last_top_;
2553};
2554
2555int StringTracker::use_count_ = 0;
2556i::Address StringTracker::last_top_ = NULL;
2557
2558} // namespace
2559
2560
Steve Blocka7e24c12009-10-30 11:49:00 +00002561int String::Length() const {
2562 if (IsDeadCheck("v8::String::Length()")) return 0;
2563 return Utils::OpenHandle(this)->length();
2564}
2565
2566
2567int String::Utf8Length() const {
2568 if (IsDeadCheck("v8::String::Utf8Length()")) return 0;
2569 return Utils::OpenHandle(this)->Utf8Length();
2570}
2571
2572
2573int String::WriteUtf8(char* buffer, int capacity) const {
2574 if (IsDeadCheck("v8::String::WriteUtf8()")) return 0;
2575 LOG_API("String::WriteUtf8");
2576 ENTER_V8;
2577 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002578 StringTracker::RecordWrite(str);
Steve Blocka7e24c12009-10-30 11:49:00 +00002579 write_input_buffer.Reset(0, *str);
2580 int len = str->length();
2581 // Encode the first K - 3 bytes directly into the buffer since we
2582 // know there's room for them. If no capacity is given we copy all
2583 // of them here.
2584 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1);
2585 int i;
2586 int pos = 0;
2587 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) {
2588 i::uc32 c = write_input_buffer.GetNext();
2589 int written = unibrow::Utf8::Encode(buffer + pos, c);
2590 pos += written;
2591 }
2592 if (i < len) {
2593 // For the last characters we need to check the length for each one
2594 // because they may be longer than the remaining space in the
2595 // buffer.
2596 char intermediate[unibrow::Utf8::kMaxEncodedSize];
2597 for (; i < len && pos < capacity; i++) {
2598 i::uc32 c = write_input_buffer.GetNext();
2599 int written = unibrow::Utf8::Encode(intermediate, c);
2600 if (pos + written <= capacity) {
2601 for (int j = 0; j < written; j++)
2602 buffer[pos + j] = intermediate[j];
2603 pos += written;
2604 } else {
2605 // We've reached the end of the buffer
2606 break;
2607 }
2608 }
2609 }
2610 if (i == len && (capacity == -1 || pos < capacity))
2611 buffer[pos++] = '\0';
2612 return pos;
2613}
2614
2615
2616int String::WriteAscii(char* buffer, int start, int length) const {
2617 if (IsDeadCheck("v8::String::WriteAscii()")) return 0;
2618 LOG_API("String::WriteAscii");
2619 ENTER_V8;
2620 ASSERT(start >= 0 && length >= -1);
2621 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002622 StringTracker::RecordWrite(str);
Steve Blocka7e24c12009-10-30 11:49:00 +00002623 // Flatten the string for efficiency. This applies whether we are
2624 // using StringInputBuffer or Get(i) to access the characters.
2625 str->TryFlattenIfNotFlat();
2626 int end = length;
2627 if ( (length == -1) || (length > str->length() - start) )
2628 end = str->length() - start;
2629 if (end < 0) return 0;
2630 write_input_buffer.Reset(start, *str);
2631 int i;
2632 for (i = 0; i < end; i++) {
2633 char c = static_cast<char>(write_input_buffer.GetNext());
2634 if (c == '\0') c = ' ';
2635 buffer[i] = c;
2636 }
2637 if (length == -1 || i < length)
2638 buffer[i] = '\0';
2639 return i;
2640}
2641
2642
2643int String::Write(uint16_t* buffer, int start, int length) const {
2644 if (IsDeadCheck("v8::String::Write()")) return 0;
2645 LOG_API("String::Write");
2646 ENTER_V8;
2647 ASSERT(start >= 0 && length >= -1);
2648 i::Handle<i::String> str = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00002649 StringTracker::RecordWrite(str);
Steve Blocka7e24c12009-10-30 11:49:00 +00002650 int end = length;
2651 if ( (length == -1) || (length > str->length() - start) )
2652 end = str->length() - start;
2653 if (end < 0) return 0;
2654 i::String::WriteToFlat(*str, buffer, start, end);
2655 if (length == -1 || end < length)
2656 buffer[end] = '\0';
2657 return end;
2658}
2659
2660
2661bool v8::String::IsExternal() const {
2662 EnsureInitialized("v8::String::IsExternal()");
2663 i::Handle<i::String> str = Utils::OpenHandle(this);
2664 return i::StringShape(*str).IsExternalTwoByte();
2665}
2666
2667
2668bool v8::String::IsExternalAscii() const {
2669 EnsureInitialized("v8::String::IsExternalAscii()");
2670 i::Handle<i::String> str = Utils::OpenHandle(this);
2671 return i::StringShape(*str).IsExternalAscii();
2672}
2673
2674
2675void v8::String::VerifyExternalStringResource(
2676 v8::String::ExternalStringResource* value) const {
2677 i::Handle<i::String> str = Utils::OpenHandle(this);
2678 v8::String::ExternalStringResource* expected;
2679 if (i::StringShape(*str).IsExternalTwoByte()) {
2680 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
2681 expected = reinterpret_cast<ExternalStringResource*>(resource);
2682 } else {
2683 expected = NULL;
2684 }
2685 CHECK_EQ(expected, value);
2686}
2687
2688
2689v8::String::ExternalAsciiStringResource*
2690 v8::String::GetExternalAsciiStringResource() const {
2691 EnsureInitialized("v8::String::GetExternalAsciiStringResource()");
2692 i::Handle<i::String> str = Utils::OpenHandle(this);
2693 if (i::StringShape(*str).IsExternalAscii()) {
2694 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
2695 return reinterpret_cast<ExternalAsciiStringResource*>(resource);
2696 } else {
2697 return NULL;
2698 }
2699}
2700
2701
2702double Number::Value() const {
2703 if (IsDeadCheck("v8::Number::Value()")) return 0;
2704 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2705 return obj->Number();
2706}
2707
2708
2709bool Boolean::Value() const {
2710 if (IsDeadCheck("v8::Boolean::Value()")) return false;
2711 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2712 return obj->IsTrue();
2713}
2714
2715
2716int64_t Integer::Value() const {
2717 if (IsDeadCheck("v8::Integer::Value()")) return 0;
2718 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2719 if (obj->IsSmi()) {
2720 return i::Smi::cast(*obj)->value();
2721 } else {
2722 return static_cast<int64_t>(obj->Number());
2723 }
2724}
2725
2726
2727int32_t Int32::Value() const {
2728 if (IsDeadCheck("v8::Int32::Value()")) return 0;
2729 i::Handle<i::Object> obj = Utils::OpenHandle(this);
2730 if (obj->IsSmi()) {
2731 return i::Smi::cast(*obj)->value();
2732 } else {
2733 return static_cast<int32_t>(obj->Number());
2734 }
2735}
2736
2737
2738int v8::Object::InternalFieldCount() {
2739 if (IsDeadCheck("v8::Object::InternalFieldCount()")) return 0;
2740 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2741 return obj->GetInternalFieldCount();
2742}
2743
2744
2745Local<Value> v8::Object::CheckedGetInternalField(int index) {
2746 if (IsDeadCheck("v8::Object::GetInternalField()")) return Local<Value>();
2747 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2748 if (!ApiCheck(index < obj->GetInternalFieldCount(),
2749 "v8::Object::GetInternalField()",
2750 "Reading internal field out of bounds")) {
2751 return Local<Value>();
2752 }
2753 i::Handle<i::Object> value(obj->GetInternalField(index));
2754 Local<Value> result = Utils::ToLocal(value);
2755#ifdef DEBUG
2756 Local<Value> unchecked = UncheckedGetInternalField(index);
2757 ASSERT(unchecked.IsEmpty() || (unchecked == result));
2758#endif
2759 return result;
2760}
2761
2762
2763void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
2764 if (IsDeadCheck("v8::Object::SetInternalField()")) return;
2765 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
2766 if (!ApiCheck(index < obj->GetInternalFieldCount(),
2767 "v8::Object::SetInternalField()",
2768 "Writing internal field out of bounds")) {
2769 return;
2770 }
2771 ENTER_V8;
2772 i::Handle<i::Object> val = Utils::OpenHandle(*value);
2773 obj->SetInternalField(index, *val);
2774}
2775
2776
2777void v8::Object::SetPointerInInternalField(int index, void* value) {
Steve Block3ce2e202009-11-05 08:53:23 +00002778 i::Object* as_object = reinterpret_cast<i::Object*>(value);
2779 if (as_object->IsSmi()) {
2780 Utils::OpenHandle(this)->SetInternalField(index, as_object);
2781 return;
2782 }
2783 HandleScope scope;
2784 i::Handle<i::Proxy> proxy =
2785 i::Factory::NewProxy(reinterpret_cast<i::Address>(value), i::TENURED);
2786 if (!proxy.is_null())
2787 Utils::OpenHandle(this)->SetInternalField(index, *proxy);
Steve Blocka7e24c12009-10-30 11:49:00 +00002788}
2789
2790
2791// --- E n v i r o n m e n t ---
2792
2793bool v8::V8::Initialize() {
2794 if (i::V8::IsRunning()) return true;
2795 ENTER_V8;
2796 HandleScope scope;
Steve Blockd0582a62009-12-15 09:54:21 +00002797 if (i::Snapshot::Initialize()) return true;
2798 return i::V8::Initialize(NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00002799}
2800
2801
2802bool v8::V8::Dispose() {
2803 i::V8::TearDown();
2804 return true;
2805}
2806
2807
Steve Block3ce2e202009-11-05 08:53:23 +00002808HeapStatistics::HeapStatistics(): total_heap_size_(0), used_heap_size_(0) { }
2809
2810
2811void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) {
2812 heap_statistics->set_total_heap_size(i::Heap::CommittedMemory());
2813 heap_statistics->set_used_heap_size(i::Heap::SizeOfObjects());
2814}
2815
2816
2817bool v8::V8::IdleNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002818 // Returning true tells the caller that it need not
2819 // continue to call IdleNotification.
2820 if (!i::V8::IsRunning()) return true;
Steve Block3ce2e202009-11-05 08:53:23 +00002821 return i::V8::IdleNotification();
Steve Blocka7e24c12009-10-30 11:49:00 +00002822}
2823
2824
2825void v8::V8::LowMemoryNotification() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002826 if (!i::V8::IsRunning()) return;
2827 i::Heap::CollectAllGarbage(true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002828}
2829
2830
2831const char* v8::V8::GetVersion() {
2832 static v8::internal::EmbeddedVector<char, 128> buffer;
2833 v8::internal::Version::GetString(buffer);
2834 return buffer.start();
2835}
2836
2837
2838static i::Handle<i::FunctionTemplateInfo>
2839 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) {
2840 if (templ->constructor()->IsUndefined()) {
2841 Local<FunctionTemplate> constructor = FunctionTemplate::New();
2842 Utils::OpenHandle(*constructor)->set_instance_template(*templ);
2843 templ->set_constructor(*Utils::OpenHandle(*constructor));
2844 }
2845 return i::Handle<i::FunctionTemplateInfo>(
2846 i::FunctionTemplateInfo::cast(templ->constructor()));
2847}
2848
2849
2850Persistent<Context> v8::Context::New(
2851 v8::ExtensionConfiguration* extensions,
2852 v8::Handle<ObjectTemplate> global_template,
2853 v8::Handle<Value> global_object) {
2854 EnsureInitialized("v8::Context::New()");
2855 LOG_API("Context::New");
2856 ON_BAILOUT("v8::Context::New()", return Persistent<Context>());
2857
Andrei Popescu31002712010-02-23 13:46:05 +00002858#if defined(ANDROID)
2859 // On mobile device, full GC is expensive, leave it to the system to
2860 // decide when should make a full GC.
2861#else
2862 // Give the heap a chance to cleanup if we've disposed contexts.
2863 i::Heap::CollectAllGarbageIfContextDisposed();
2864#endif
2865
Steve Blocka7e24c12009-10-30 11:49:00 +00002866 // Enter V8 via an ENTER_V8 scope.
2867 i::Handle<i::Context> env;
2868 {
2869 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00002870 v8::Handle<ObjectTemplate> proxy_template = global_template;
2871 i::Handle<i::FunctionTemplateInfo> proxy_constructor;
2872 i::Handle<i::FunctionTemplateInfo> global_constructor;
2873
2874 if (!global_template.IsEmpty()) {
2875 // Make sure that the global_template has a constructor.
2876 global_constructor =
2877 EnsureConstructor(Utils::OpenHandle(*global_template));
2878
2879 // Create a fresh template for the global proxy object.
2880 proxy_template = ObjectTemplate::New();
2881 proxy_constructor =
2882 EnsureConstructor(Utils::OpenHandle(*proxy_template));
2883
2884 // Set the global template to be the prototype template of
2885 // global proxy template.
2886 proxy_constructor->set_prototype_template(
2887 *Utils::OpenHandle(*global_template));
2888
2889 // Migrate security handlers from global_template to
2890 // proxy_template. Temporarily removing access check
2891 // information from the global template.
2892 if (!global_constructor->access_check_info()->IsUndefined()) {
2893 proxy_constructor->set_access_check_info(
2894 global_constructor->access_check_info());
2895 proxy_constructor->set_needs_access_check(
2896 global_constructor->needs_access_check());
2897 global_constructor->set_needs_access_check(false);
2898 global_constructor->set_access_check_info(i::Heap::undefined_value());
2899 }
2900 }
2901
2902 // Create the environment.
2903 env = i::Bootstrapper::CreateEnvironment(
2904 Utils::OpenHandle(*global_object),
2905 proxy_template,
2906 extensions);
2907
2908 // Restore the access check info on the global template.
2909 if (!global_template.IsEmpty()) {
2910 ASSERT(!global_constructor.is_null());
2911 ASSERT(!proxy_constructor.is_null());
2912 global_constructor->set_access_check_info(
2913 proxy_constructor->access_check_info());
2914 global_constructor->set_needs_access_check(
2915 proxy_constructor->needs_access_check());
2916 }
2917 }
2918 // Leave V8.
2919
2920 if (env.is_null())
2921 return Persistent<Context>();
2922 return Persistent<Context>(Utils::ToLocal(env));
2923}
2924
2925
2926void v8::Context::SetSecurityToken(Handle<Value> token) {
2927 if (IsDeadCheck("v8::Context::SetSecurityToken()")) return;
2928 ENTER_V8;
2929 i::Handle<i::Context> env = Utils::OpenHandle(this);
2930 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
2931 env->set_security_token(*token_handle);
2932}
2933
2934
2935void v8::Context::UseDefaultSecurityToken() {
2936 if (IsDeadCheck("v8::Context::UseDefaultSecurityToken()")) return;
2937 ENTER_V8;
2938 i::Handle<i::Context> env = Utils::OpenHandle(this);
2939 env->set_security_token(env->global());
2940}
2941
2942
2943Handle<Value> v8::Context::GetSecurityToken() {
2944 if (IsDeadCheck("v8::Context::GetSecurityToken()")) return Handle<Value>();
2945 i::Handle<i::Context> env = Utils::OpenHandle(this);
2946 i::Object* security_token = env->security_token();
2947 i::Handle<i::Object> token_handle(security_token);
2948 return Utils::ToLocal(token_handle);
2949}
2950
2951
2952bool Context::HasOutOfMemoryException() {
2953 i::Handle<i::Context> env = Utils::OpenHandle(this);
2954 return env->has_out_of_memory();
2955}
2956
2957
2958bool Context::InContext() {
2959 return i::Top::context() != NULL;
2960}
2961
2962
2963v8::Local<v8::Context> Context::GetEntered() {
2964 if (IsDeadCheck("v8::Context::GetEntered()")) return Local<Context>();
2965 i::Handle<i::Object> last = thread_local.LastEnteredContext();
2966 if (last.is_null()) return Local<Context>();
2967 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last);
2968 return Utils::ToLocal(context);
2969}
2970
2971
2972v8::Local<v8::Context> Context::GetCurrent() {
2973 if (IsDeadCheck("v8::Context::GetCurrent()")) return Local<Context>();
Steve Block3ce2e202009-11-05 08:53:23 +00002974 i::Handle<i::Object> current = i::Top::global_context();
2975 if (current.is_null()) return Local<Context>();
2976 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current);
Steve Blocka7e24c12009-10-30 11:49:00 +00002977 return Utils::ToLocal(context);
2978}
2979
2980
2981v8::Local<v8::Context> Context::GetCalling() {
2982 if (IsDeadCheck("v8::Context::GetCalling()")) return Local<Context>();
2983 i::Handle<i::Object> calling = i::Top::GetCallingGlobalContext();
2984 if (calling.is_null()) return Local<Context>();
2985 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling);
2986 return Utils::ToLocal(context);
2987}
2988
2989
2990v8::Local<v8::Object> Context::Global() {
2991 if (IsDeadCheck("v8::Context::Global()")) return Local<v8::Object>();
2992 i::Object** ctx = reinterpret_cast<i::Object**>(this);
2993 i::Handle<i::Context> context =
2994 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
2995 i::Handle<i::Object> global(context->global_proxy());
2996 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
2997}
2998
2999
3000void Context::DetachGlobal() {
3001 if (IsDeadCheck("v8::Context::DetachGlobal()")) return;
3002 ENTER_V8;
3003 i::Object** ctx = reinterpret_cast<i::Object**>(this);
3004 i::Handle<i::Context> context =
3005 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx));
3006 i::Bootstrapper::DetachGlobal(context);
3007}
3008
3009
3010Local<v8::Object> ObjectTemplate::NewInstance() {
3011 ON_BAILOUT("v8::ObjectTemplate::NewInstance()", return Local<v8::Object>());
3012 LOG_API("ObjectTemplate::NewInstance");
3013 ENTER_V8;
3014 EXCEPTION_PREAMBLE();
3015 i::Handle<i::Object> obj =
3016 i::Execution::InstantiateObject(Utils::OpenHandle(this),
3017 &has_pending_exception);
3018 EXCEPTION_BAILOUT_CHECK(Local<v8::Object>());
3019 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
3020}
3021
3022
3023Local<v8::Function> FunctionTemplate::GetFunction() {
3024 ON_BAILOUT("v8::FunctionTemplate::GetFunction()",
3025 return Local<v8::Function>());
3026 LOG_API("FunctionTemplate::GetFunction");
3027 ENTER_V8;
3028 EXCEPTION_PREAMBLE();
3029 i::Handle<i::Object> obj =
3030 i::Execution::InstantiateFunction(Utils::OpenHandle(this),
3031 &has_pending_exception);
3032 EXCEPTION_BAILOUT_CHECK(Local<v8::Function>());
3033 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
3034}
3035
3036
3037bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
3038 ON_BAILOUT("v8::FunctionTemplate::HasInstanceOf()", return false);
3039 i::Object* obj = *Utils::OpenHandle(*value);
3040 return obj->IsInstanceOf(*Utils::OpenHandle(this));
3041}
3042
3043
3044static Local<External> ExternalNewImpl(void* data) {
3045 return Utils::ToLocal(i::Factory::NewProxy(static_cast<i::Address>(data)));
3046}
3047
3048static void* ExternalValueImpl(i::Handle<i::Object> obj) {
3049 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy());
3050}
3051
3052
Steve Blocka7e24c12009-10-30 11:49:00 +00003053Local<Value> v8::External::Wrap(void* data) {
3054 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3055 LOG_API("External::Wrap");
3056 EnsureInitialized("v8::External::Wrap()");
3057 ENTER_V8;
Steve Block3ce2e202009-11-05 08:53:23 +00003058 i::Object* as_object = reinterpret_cast<i::Object*>(data);
3059 if (as_object->IsSmi()) {
3060 return Utils::ToLocal(i::Handle<i::Object>(as_object));
Steve Blocka7e24c12009-10-30 11:49:00 +00003061 }
3062 return ExternalNewImpl(data);
3063}
3064
3065
Steve Block3ce2e202009-11-05 08:53:23 +00003066void* v8::Object::SlowGetPointerFromInternalField(int index) {
3067 i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3068 i::Object* value = obj->GetInternalField(index);
3069 if (value->IsSmi()) {
3070 return value;
3071 } else if (value->IsProxy()) {
3072 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy());
3073 } else {
3074 return NULL;
3075 }
3076}
3077
3078
Steve Blocka7e24c12009-10-30 11:49:00 +00003079void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) {
3080 if (IsDeadCheck("v8::External::Unwrap()")) return 0;
3081 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper);
3082 void* result;
3083 if (obj->IsSmi()) {
3084 // The external value was an aligned pointer.
Steve Block3ce2e202009-11-05 08:53:23 +00003085 result = *obj;
Steve Blocka7e24c12009-10-30 11:49:00 +00003086 } else if (obj->IsProxy()) {
3087 result = ExternalValueImpl(obj);
3088 } else {
3089 result = NULL;
3090 }
3091 ASSERT_EQ(result, QuickUnwrap(wrapper));
3092 return result;
3093}
3094
3095
3096Local<External> v8::External::New(void* data) {
3097 STATIC_ASSERT(sizeof(data) == sizeof(i::Address));
3098 LOG_API("External::New");
3099 EnsureInitialized("v8::External::New()");
3100 ENTER_V8;
3101 return ExternalNewImpl(data);
3102}
3103
3104
3105void* External::Value() const {
3106 if (IsDeadCheck("v8::External::Value()")) return 0;
3107 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3108 return ExternalValueImpl(obj);
3109}
3110
3111
3112Local<String> v8::String::Empty() {
3113 EnsureInitialized("v8::String::Empty()");
3114 LOG_API("String::Empty()");
3115 return Utils::ToLocal(i::Factory::empty_symbol());
3116}
3117
3118
3119Local<String> v8::String::New(const char* data, int length) {
3120 EnsureInitialized("v8::String::New()");
3121 LOG_API("String::New(char)");
3122 if (length == 0) return Empty();
3123 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003124 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003125 i::Handle<i::String> result =
3126 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3127 return Utils::ToLocal(result);
3128}
3129
3130
Steve Block3ce2e202009-11-05 08:53:23 +00003131Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
3132 EnsureInitialized("v8::String::New()");
3133 LOG_API("String::New(char)");
3134 ENTER_V8;
3135 i::Handle<i::String> left_string = Utils::OpenHandle(*left);
3136 i::Handle<i::String> right_string = Utils::OpenHandle(*right);
3137 i::Handle<i::String> result = i::Factory::NewConsString(left_string,
3138 right_string);
3139 return Utils::ToLocal(result);
3140}
3141
3142
Steve Blocka7e24c12009-10-30 11:49:00 +00003143Local<String> v8::String::NewUndetectable(const char* data, int length) {
3144 EnsureInitialized("v8::String::NewUndetectable()");
3145 LOG_API("String::NewUndetectable(char)");
3146 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003147 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003148 i::Handle<i::String> result =
3149 i::Factory::NewStringFromUtf8(i::Vector<const char>(data, length));
3150 result->MarkAsUndetectable();
3151 return Utils::ToLocal(result);
3152}
3153
3154
3155static int TwoByteStringLength(const uint16_t* data) {
3156 int length = 0;
3157 while (data[length] != '\0') length++;
3158 return length;
3159}
3160
3161
3162Local<String> v8::String::New(const uint16_t* data, int length) {
3163 EnsureInitialized("v8::String::New()");
3164 LOG_API("String::New(uint16_)");
3165 if (length == 0) return Empty();
3166 ENTER_V8;
3167 if (length == -1) length = TwoByteStringLength(data);
3168 i::Handle<i::String> result =
3169 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3170 return Utils::ToLocal(result);
3171}
3172
3173
3174Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) {
3175 EnsureInitialized("v8::String::NewUndetectable()");
3176 LOG_API("String::NewUndetectable(uint16_)");
3177 ENTER_V8;
3178 if (length == -1) length = TwoByteStringLength(data);
3179 i::Handle<i::String> result =
3180 i::Factory::NewStringFromTwoByte(i::Vector<const uint16_t>(data, length));
3181 result->MarkAsUndetectable();
3182 return Utils::ToLocal(result);
3183}
3184
3185
3186i::Handle<i::String> NewExternalStringHandle(
3187 v8::String::ExternalStringResource* resource) {
3188 i::Handle<i::String> result =
3189 i::Factory::NewExternalStringFromTwoByte(resource);
3190 return result;
3191}
3192
3193
3194i::Handle<i::String> NewExternalAsciiStringHandle(
3195 v8::String::ExternalAsciiStringResource* resource) {
3196 i::Handle<i::String> result =
3197 i::Factory::NewExternalStringFromAscii(resource);
3198 return result;
3199}
3200
3201
Steve Blocka7e24c12009-10-30 11:49:00 +00003202Local<String> v8::String::NewExternal(
3203 v8::String::ExternalStringResource* resource) {
3204 EnsureInitialized("v8::String::NewExternal()");
3205 LOG_API("String::NewExternal");
3206 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003207 i::Handle<i::String> result = NewExternalStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003208 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003209 return Utils::ToLocal(result);
3210}
3211
3212
3213bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
3214 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3215 if (this->IsExternal()) return false; // Already an external string.
3216 ENTER_V8;
3217 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003218 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003219 bool result = obj->MakeExternal(resource);
3220 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003221 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003222 }
3223 return result;
3224}
3225
3226
3227Local<String> v8::String::NewExternal(
3228 v8::String::ExternalAsciiStringResource* resource) {
3229 EnsureInitialized("v8::String::NewExternal()");
3230 LOG_API("String::NewExternal");
3231 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003232 i::Handle<i::String> result = NewExternalAsciiStringHandle(resource);
Leon Clarkee46be812010-01-19 14:06:41 +00003233 i::ExternalStringTable::AddString(*result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003234 return Utils::ToLocal(result);
3235}
3236
3237
3238bool v8::String::MakeExternal(
3239 v8::String::ExternalAsciiStringResource* resource) {
3240 if (IsDeadCheck("v8::String::MakeExternal()")) return false;
3241 if (this->IsExternal()) return false; // Already an external string.
3242 ENTER_V8;
3243 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003244 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003245 bool result = obj->MakeExternal(resource);
3246 if (result && !obj->IsSymbol()) {
Leon Clarkee46be812010-01-19 14:06:41 +00003247 i::ExternalStringTable::AddString(*obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00003248 }
3249 return result;
3250}
3251
3252
3253bool v8::String::CanMakeExternal() {
3254 if (IsDeadCheck("v8::String::CanMakeExternal()")) return false;
3255 i::Handle<i::String> obj = Utils::OpenHandle(this);
Andrei Popescu402d9372010-02-26 13:31:12 +00003256 if (StringTracker::IsFreshUnusedString(obj)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00003257 int size = obj->Size(); // Byte size of the original string.
3258 if (size < i::ExternalString::kSize)
3259 return false;
3260 i::StringShape shape(*obj);
3261 return !shape.IsExternal();
3262}
3263
3264
3265Local<v8::Object> v8::Object::New() {
3266 EnsureInitialized("v8::Object::New()");
3267 LOG_API("Object::New");
3268 ENTER_V8;
3269 i::Handle<i::JSObject> obj =
3270 i::Factory::NewJSObject(i::Top::object_function());
3271 return Utils::ToLocal(obj);
3272}
3273
3274
3275Local<v8::Value> v8::Date::New(double time) {
3276 EnsureInitialized("v8::Date::New()");
3277 LOG_API("Date::New");
Steve Blockd0582a62009-12-15 09:54:21 +00003278 if (isnan(time)) {
3279 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3280 time = i::OS::nan_value();
3281 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003282 ENTER_V8;
3283 EXCEPTION_PREAMBLE();
3284 i::Handle<i::Object> obj =
3285 i::Execution::NewDate(time, &has_pending_exception);
3286 EXCEPTION_BAILOUT_CHECK(Local<v8::Value>());
3287 return Utils::ToLocal(obj);
3288}
3289
3290
3291double v8::Date::NumberValue() const {
3292 if (IsDeadCheck("v8::Date::NumberValue()")) return 0;
3293 LOG_API("Date::NumberValue");
3294 i::Handle<i::Object> obj = Utils::OpenHandle(this);
3295 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
3296 return jsvalue->value()->Number();
3297}
3298
3299
3300Local<v8::Array> v8::Array::New(int length) {
3301 EnsureInitialized("v8::Array::New()");
3302 LOG_API("Array::New");
3303 ENTER_V8;
3304 i::Handle<i::JSArray> obj = i::Factory::NewJSArray(length);
3305 return Utils::ToLocal(obj);
3306}
3307
3308
3309uint32_t v8::Array::Length() const {
3310 if (IsDeadCheck("v8::Array::Length()")) return 0;
3311 i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
3312 i::Object* length = obj->length();
3313 if (length->IsSmi()) {
3314 return i::Smi::cast(length)->value();
3315 } else {
3316 return static_cast<uint32_t>(length->Number());
3317 }
3318}
3319
3320
3321Local<Object> Array::CloneElementAt(uint32_t index) {
3322 ON_BAILOUT("v8::Array::CloneElementAt()", return Local<Object>());
3323 i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3324 if (!self->HasFastElements()) {
3325 return Local<Object>();
3326 }
3327 i::FixedArray* elms = i::FixedArray::cast(self->elements());
3328 i::Object* paragon = elms->get(index);
3329 if (!paragon->IsJSObject()) {
3330 return Local<Object>();
3331 }
3332 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
3333 EXCEPTION_PREAMBLE();
3334 i::Handle<i::JSObject> result = i::Copy(paragon_handle);
3335 has_pending_exception = result.is_null();
3336 EXCEPTION_BAILOUT_CHECK(Local<Object>());
3337 return Utils::ToLocal(result);
3338}
3339
3340
3341Local<String> v8::String::NewSymbol(const char* data, int length) {
3342 EnsureInitialized("v8::String::NewSymbol()");
3343 LOG_API("String::NewSymbol(char)");
3344 ENTER_V8;
Steve Blockd0582a62009-12-15 09:54:21 +00003345 if (length == -1) length = i::StrLength(data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003346 i::Handle<i::String> result =
3347 i::Factory::LookupSymbol(i::Vector<const char>(data, length));
3348 return Utils::ToLocal(result);
3349}
3350
3351
3352Local<Number> v8::Number::New(double value) {
3353 EnsureInitialized("v8::Number::New()");
Steve Blockd0582a62009-12-15 09:54:21 +00003354 if (isnan(value)) {
3355 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
3356 value = i::OS::nan_value();
3357 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003358 ENTER_V8;
3359 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3360 return Utils::NumberToLocal(result);
3361}
3362
3363
3364Local<Integer> v8::Integer::New(int32_t value) {
3365 EnsureInitialized("v8::Integer::New()");
3366 if (i::Smi::IsValid(value)) {
3367 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value)));
3368 }
3369 ENTER_V8;
3370 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3371 return Utils::IntegerToLocal(result);
3372}
3373
3374
Steve Block3ce2e202009-11-05 08:53:23 +00003375Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
3376 bool fits_into_int32_t = (value & (1 << 31)) == 0;
3377 if (fits_into_int32_t) {
3378 return Integer::New(static_cast<int32_t>(value));
3379 }
3380 ENTER_V8;
3381 i::Handle<i::Object> result = i::Factory::NewNumber(value);
3382 return Utils::IntegerToLocal(result);
3383}
3384
3385
Steve Blocka7e24c12009-10-30 11:49:00 +00003386void V8::IgnoreOutOfMemoryException() {
3387 thread_local.set_ignore_out_of_memory(true);
3388}
3389
3390
3391bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
3392 EnsureInitialized("v8::V8::AddMessageListener()");
3393 ON_BAILOUT("v8::V8::AddMessageListener()", return false);
3394 ENTER_V8;
3395 HandleScope scope;
3396 NeanderArray listeners(i::Factory::message_listeners());
3397 NeanderObject obj(2);
3398 obj.set(0, *i::Factory::NewProxy(FUNCTION_ADDR(that)));
3399 obj.set(1, data.IsEmpty() ?
3400 i::Heap::undefined_value() :
3401 *Utils::OpenHandle(*data));
3402 listeners.add(obj.value());
3403 return true;
3404}
3405
3406
3407void V8::RemoveMessageListeners(MessageCallback that) {
3408 EnsureInitialized("v8::V8::RemoveMessageListener()");
3409 ON_BAILOUT("v8::V8::RemoveMessageListeners()", return);
3410 ENTER_V8;
3411 HandleScope scope;
3412 NeanderArray listeners(i::Factory::message_listeners());
3413 for (int i = 0; i < listeners.length(); i++) {
3414 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones
3415
3416 NeanderObject listener(i::JSObject::cast(listeners.get(i)));
3417 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0)));
3418 if (callback_obj->proxy() == FUNCTION_ADDR(that)) {
3419 listeners.set(i, i::Heap::undefined_value());
3420 }
3421 }
3422}
3423
3424
3425void V8::SetCounterFunction(CounterLookupCallback callback) {
3426 if (IsDeadCheck("v8::V8::SetCounterFunction()")) return;
3427 i::StatsTable::SetCounterFunction(callback);
3428}
3429
3430void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
3431 if (IsDeadCheck("v8::V8::SetCreateHistogramFunction()")) return;
3432 i::StatsTable::SetCreateHistogramFunction(callback);
3433}
3434
3435void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
3436 if (IsDeadCheck("v8::V8::SetAddHistogramSampleFunction()")) return;
3437 i::StatsTable::SetAddHistogramSampleFunction(callback);
3438}
3439
3440void V8::EnableSlidingStateWindow() {
3441 if (IsDeadCheck("v8::V8::EnableSlidingStateWindow()")) return;
3442 i::Logger::EnableSlidingStateWindow();
3443}
3444
3445
3446void V8::SetFailedAccessCheckCallbackFunction(
3447 FailedAccessCheckCallback callback) {
3448 if (IsDeadCheck("v8::V8::SetFailedAccessCheckCallbackFunction()")) return;
3449 i::Top::SetFailedAccessCheckCallback(callback);
3450}
3451
3452
3453void V8::AddObjectGroup(Persistent<Value>* objects, size_t length) {
3454 if (IsDeadCheck("v8::V8::AddObjectGroup()")) return;
3455 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**));
3456 i::GlobalHandles::AddGroup(reinterpret_cast<i::Object***>(objects), length);
3457}
3458
3459
3460int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) {
3461 if (IsDeadCheck("v8::V8::AdjustAmountOfExternalAllocatedMemory()")) return 0;
3462 return i::Heap::AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
3463}
3464
3465
3466void V8::SetGlobalGCPrologueCallback(GCCallback callback) {
3467 if (IsDeadCheck("v8::V8::SetGlobalGCPrologueCallback()")) return;
3468 i::Heap::SetGlobalGCPrologueCallback(callback);
3469}
3470
3471
3472void V8::SetGlobalGCEpilogueCallback(GCCallback callback) {
3473 if (IsDeadCheck("v8::V8::SetGlobalGCEpilogueCallback()")) return;
3474 i::Heap::SetGlobalGCEpilogueCallback(callback);
3475}
3476
3477
3478void V8::PauseProfiler() {
3479#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003480 PauseProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003481#endif
3482}
3483
3484
3485void V8::ResumeProfiler() {
3486#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003487 ResumeProfilerEx(PROFILER_MODULE_CPU);
Steve Blocka7e24c12009-10-30 11:49:00 +00003488#endif
3489}
3490
3491
3492bool V8::IsProfilerPaused() {
3493#ifdef ENABLE_LOGGING_AND_PROFILING
3494 return i::Logger::GetActiveProfilerModules() & PROFILER_MODULE_CPU;
3495#else
3496 return true;
3497#endif
3498}
3499
3500
Andrei Popescu402d9372010-02-26 13:31:12 +00003501void V8::ResumeProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003502#ifdef ENABLE_LOGGING_AND_PROFILING
3503 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) {
3504 // Snapshot mode: resume modules, perform GC, then pause only
3505 // those modules which haven't been started prior to making a
3506 // snapshot.
3507
3508 // Reset snapshot flag and CPU module flags.
3509 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU);
3510 const int current_flags = i::Logger::GetActiveProfilerModules();
Andrei Popescu402d9372010-02-26 13:31:12 +00003511 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003512 i::Heap::CollectAllGarbage(false);
Andrei Popescu402d9372010-02-26 13:31:12 +00003513 i::Logger::PauseProfiler(~current_flags & flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003514 } else {
Andrei Popescu402d9372010-02-26 13:31:12 +00003515 i::Logger::ResumeProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003516 }
3517#endif
3518}
3519
3520
Andrei Popescu402d9372010-02-26 13:31:12 +00003521void V8::PauseProfilerEx(int flags, int tag) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003522#ifdef ENABLE_LOGGING_AND_PROFILING
Andrei Popescu402d9372010-02-26 13:31:12 +00003523 i::Logger::PauseProfiler(flags, tag);
Steve Blocka7e24c12009-10-30 11:49:00 +00003524#endif
3525}
3526
3527
3528int V8::GetActiveProfilerModules() {
3529#ifdef ENABLE_LOGGING_AND_PROFILING
3530 return i::Logger::GetActiveProfilerModules();
3531#else
3532 return PROFILER_MODULE_NONE;
3533#endif
3534}
3535
3536
3537int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
3538#ifdef ENABLE_LOGGING_AND_PROFILING
3539 return i::Logger::GetLogLines(from_pos, dest_buf, max_size);
3540#endif
3541 return 0;
3542}
3543
3544
3545int V8::GetCurrentThreadId() {
3546 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3547 EnsureInitialized("V8::GetCurrentThreadId()");
3548 return i::Top::thread_id();
3549}
3550
3551
3552void V8::TerminateExecution(int thread_id) {
3553 if (!i::V8::IsRunning()) return;
3554 API_ENTRY_CHECK("V8::GetCurrentThreadId()");
3555 // If the thread_id identifies the current thread just terminate
3556 // execution right away. Otherwise, ask the thread manager to
3557 // terminate the thread with the given id if any.
3558 if (thread_id == i::Top::thread_id()) {
3559 i::StackGuard::TerminateExecution();
3560 } else {
3561 i::ThreadManager::TerminateExecution(thread_id);
3562 }
3563}
3564
3565
3566void V8::TerminateExecution() {
3567 if (!i::V8::IsRunning()) return;
3568 i::StackGuard::TerminateExecution();
3569}
3570
3571
3572String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
3573 EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
3574 if (obj.IsEmpty()) {
3575 str_ = NULL;
3576 length_ = 0;
3577 return;
3578 }
3579 ENTER_V8;
3580 HandleScope scope;
3581 TryCatch try_catch;
3582 Handle<String> str = obj->ToString();
3583 if (str.IsEmpty()) {
3584 str_ = NULL;
3585 length_ = 0;
3586 } else {
3587 length_ = str->Utf8Length();
3588 str_ = i::NewArray<char>(length_ + 1);
3589 str->WriteUtf8(str_);
3590 }
3591}
3592
3593
3594String::Utf8Value::~Utf8Value() {
3595 i::DeleteArray(str_);
3596}
3597
3598
3599String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) {
3600 EnsureInitialized("v8::String::AsciiValue::AsciiValue()");
3601 if (obj.IsEmpty()) {
3602 str_ = NULL;
3603 length_ = 0;
3604 return;
3605 }
3606 ENTER_V8;
3607 HandleScope scope;
3608 TryCatch try_catch;
3609 Handle<String> str = obj->ToString();
3610 if (str.IsEmpty()) {
3611 str_ = NULL;
3612 length_ = 0;
3613 } else {
3614 length_ = str->Length();
3615 str_ = i::NewArray<char>(length_ + 1);
3616 str->WriteAscii(str_);
3617 }
3618}
3619
3620
3621String::AsciiValue::~AsciiValue() {
3622 i::DeleteArray(str_);
3623}
3624
3625
3626String::Value::Value(v8::Handle<v8::Value> obj) {
3627 EnsureInitialized("v8::String::Value::Value()");
3628 if (obj.IsEmpty()) {
3629 str_ = NULL;
3630 length_ = 0;
3631 return;
3632 }
3633 ENTER_V8;
3634 HandleScope scope;
3635 TryCatch try_catch;
3636 Handle<String> str = obj->ToString();
3637 if (str.IsEmpty()) {
3638 str_ = NULL;
3639 length_ = 0;
3640 } else {
3641 length_ = str->Length();
3642 str_ = i::NewArray<uint16_t>(length_ + 1);
3643 str->Write(str_);
3644 }
3645}
3646
3647
3648String::Value::~Value() {
3649 i::DeleteArray(str_);
3650}
3651
3652Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
3653 LOG_API("RangeError");
3654 ON_BAILOUT("v8::Exception::RangeError()", return Local<Value>());
3655 ENTER_V8;
3656 i::Object* error;
3657 {
3658 HandleScope scope;
3659 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3660 i::Handle<i::Object> result = i::Factory::NewRangeError(message);
3661 error = *result;
3662 }
3663 i::Handle<i::Object> result(error);
3664 return Utils::ToLocal(result);
3665}
3666
3667Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
3668 LOG_API("ReferenceError");
3669 ON_BAILOUT("v8::Exception::ReferenceError()", return Local<Value>());
3670 ENTER_V8;
3671 i::Object* error;
3672 {
3673 HandleScope scope;
3674 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3675 i::Handle<i::Object> result = i::Factory::NewReferenceError(message);
3676 error = *result;
3677 }
3678 i::Handle<i::Object> result(error);
3679 return Utils::ToLocal(result);
3680}
3681
3682Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
3683 LOG_API("SyntaxError");
3684 ON_BAILOUT("v8::Exception::SyntaxError()", return Local<Value>());
3685 ENTER_V8;
3686 i::Object* error;
3687 {
3688 HandleScope scope;
3689 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3690 i::Handle<i::Object> result = i::Factory::NewSyntaxError(message);
3691 error = *result;
3692 }
3693 i::Handle<i::Object> result(error);
3694 return Utils::ToLocal(result);
3695}
3696
3697Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
3698 LOG_API("TypeError");
3699 ON_BAILOUT("v8::Exception::TypeError()", return Local<Value>());
3700 ENTER_V8;
3701 i::Object* error;
3702 {
3703 HandleScope scope;
3704 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3705 i::Handle<i::Object> result = i::Factory::NewTypeError(message);
3706 error = *result;
3707 }
3708 i::Handle<i::Object> result(error);
3709 return Utils::ToLocal(result);
3710}
3711
3712Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
3713 LOG_API("Error");
3714 ON_BAILOUT("v8::Exception::Error()", return Local<Value>());
3715 ENTER_V8;
3716 i::Object* error;
3717 {
3718 HandleScope scope;
3719 i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
3720 i::Handle<i::Object> result = i::Factory::NewError(message);
3721 error = *result;
3722 }
3723 i::Handle<i::Object> result(error);
3724 return Utils::ToLocal(result);
3725}
3726
3727
3728// --- D e b u g S u p p o r t ---
3729
3730#ifdef ENABLE_DEBUGGER_SUPPORT
3731bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
3732 EnsureInitialized("v8::Debug::SetDebugEventListener()");
3733 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
3734 ENTER_V8;
3735 HandleScope scope;
3736 i::Handle<i::Object> proxy = i::Factory::undefined_value();
3737 if (that != NULL) {
3738 proxy = i::Factory::NewProxy(FUNCTION_ADDR(that));
3739 }
3740 i::Debugger::SetEventListener(proxy, Utils::OpenHandle(*data));
3741 return true;
3742}
3743
3744
3745bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
3746 Handle<Value> data) {
3747 ON_BAILOUT("v8::Debug::SetDebugEventListener()", return false);
3748 ENTER_V8;
3749 i::Debugger::SetEventListener(Utils::OpenHandle(*that),
3750 Utils::OpenHandle(*data));
3751 return true;
3752}
3753
3754
3755void Debug::DebugBreak() {
3756 if (!i::V8::IsRunning()) return;
3757 i::StackGuard::DebugBreak();
3758}
3759
3760
3761static v8::Debug::MessageHandler message_handler = NULL;
3762
3763static void MessageHandlerWrapper(const v8::Debug::Message& message) {
3764 if (message_handler) {
3765 v8::String::Value json(message.GetJSON());
3766 message_handler(*json, json.length(), message.GetClientData());
3767 }
3768}
3769
3770
3771void Debug::SetMessageHandler(v8::Debug::MessageHandler handler,
3772 bool message_handler_thread) {
3773 EnsureInitialized("v8::Debug::SetMessageHandler");
3774 ENTER_V8;
3775 // Message handler thread not supported any more. Parameter temporally left in
3776 // the API for client compatability reasons.
3777 CHECK(!message_handler_thread);
3778
3779 // TODO(sgjesse) support the old message handler API through a simple wrapper.
3780 message_handler = handler;
3781 if (message_handler != NULL) {
3782 i::Debugger::SetMessageHandler(MessageHandlerWrapper);
3783 } else {
3784 i::Debugger::SetMessageHandler(NULL);
3785 }
3786}
3787
3788
3789void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
3790 EnsureInitialized("v8::Debug::SetMessageHandler");
3791 ENTER_V8;
Steve Blocka7e24c12009-10-30 11:49:00 +00003792 i::Debugger::SetMessageHandler(handler);
3793}
3794
3795
3796void Debug::SendCommand(const uint16_t* command, int length,
3797 ClientData* client_data) {
3798 if (!i::V8::IsRunning()) return;
3799 i::Debugger::ProcessCommand(i::Vector<const uint16_t>(command, length),
3800 client_data);
3801}
3802
3803
3804void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
3805 int period) {
3806 EnsureInitialized("v8::Debug::SetHostDispatchHandler");
3807 ENTER_V8;
3808 i::Debugger::SetHostDispatchHandler(handler, period);
3809}
3810
3811
Steve Blockd0582a62009-12-15 09:54:21 +00003812void Debug::SetDebugMessageDispatchHandler(
Leon Clarkee46be812010-01-19 14:06:41 +00003813 DebugMessageDispatchHandler handler, bool provide_locker) {
Steve Blockd0582a62009-12-15 09:54:21 +00003814 EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler");
3815 ENTER_V8;
Leon Clarkee46be812010-01-19 14:06:41 +00003816 i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker);
Steve Blockd0582a62009-12-15 09:54:21 +00003817}
3818
3819
Steve Blocka7e24c12009-10-30 11:49:00 +00003820Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
3821 v8::Handle<v8::Value> data) {
3822 if (!i::V8::IsRunning()) return Local<Value>();
3823 ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
3824 ENTER_V8;
3825 i::Handle<i::Object> result;
3826 EXCEPTION_PREAMBLE();
3827 if (data.IsEmpty()) {
3828 result = i::Debugger::Call(Utils::OpenHandle(*fun),
3829 i::Factory::undefined_value(),
3830 &has_pending_exception);
3831 } else {
3832 result = i::Debugger::Call(Utils::OpenHandle(*fun),
3833 Utils::OpenHandle(*data),
3834 &has_pending_exception);
3835 }
3836 EXCEPTION_BAILOUT_CHECK(Local<Value>());
3837 return Utils::ToLocal(result);
3838}
3839
3840
3841Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
3842 if (!i::V8::IsRunning()) return Local<Value>();
3843 ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
3844 ENTER_V8;
3845 v8::HandleScope scope;
3846 i::Debug::Load();
3847 i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
3848 i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
3849 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
3850 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
3851 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
3852 const int kArgc = 1;
3853 v8::Handle<v8::Value> argv[kArgc] = { obj };
3854 EXCEPTION_PREAMBLE();
3855 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
3856 kArgc,
3857 argv);
3858 EXCEPTION_BAILOUT_CHECK(Local<Value>());
3859 return scope.Close(result);
3860}
3861
3862
Leon Clarkee46be812010-01-19 14:06:41 +00003863bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
3864 return i::Debugger::StartAgent(name, port, wait_for_connection);
Steve Blocka7e24c12009-10-30 11:49:00 +00003865}
Leon Clarkee46be812010-01-19 14:06:41 +00003866
3867void Debug::ProcessDebugMessages() {
3868 i::Execution::ProcessDebugMesssages(true);
3869}
3870
Steve Blocka7e24c12009-10-30 11:49:00 +00003871#endif // ENABLE_DEBUGGER_SUPPORT
3872
3873namespace internal {
3874
3875
3876HandleScopeImplementer* HandleScopeImplementer::instance() {
3877 return &thread_local;
3878}
3879
3880
3881void HandleScopeImplementer::FreeThreadResources() {
3882 thread_local.Free();
3883}
3884
3885
3886char* HandleScopeImplementer::ArchiveThread(char* storage) {
3887 return thread_local.ArchiveThreadHelper(storage);
3888}
3889
3890
3891char* HandleScopeImplementer::ArchiveThreadHelper(char* storage) {
3892 v8::ImplementationUtilities::HandleScopeData* current =
3893 v8::ImplementationUtilities::CurrentHandleScope();
3894 handle_scope_data_ = *current;
3895 memcpy(storage, this, sizeof(*this));
3896
3897 ResetAfterArchive();
3898 current->Initialize();
3899
3900 return storage + ArchiveSpacePerThread();
3901}
3902
3903
3904int HandleScopeImplementer::ArchiveSpacePerThread() {
3905 return sizeof(thread_local);
3906}
3907
3908
3909char* HandleScopeImplementer::RestoreThread(char* storage) {
3910 return thread_local.RestoreThreadHelper(storage);
3911}
3912
3913
3914char* HandleScopeImplementer::RestoreThreadHelper(char* storage) {
3915 memcpy(this, storage, sizeof(*this));
3916 *v8::ImplementationUtilities::CurrentHandleScope() = handle_scope_data_;
3917 return storage + ArchiveSpacePerThread();
3918}
3919
3920
3921void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
3922 // Iterate over all handles in the blocks except for the last.
3923 for (int i = blocks()->length() - 2; i >= 0; --i) {
3924 Object** block = blocks()->at(i);
3925 v->VisitPointers(block, &block[kHandleBlockSize]);
3926 }
3927
3928 // Iterate over live handles in the last block (if any).
3929 if (!blocks()->is_empty()) {
3930 v->VisitPointers(blocks()->last(), handle_scope_data_.next);
3931 }
3932
3933 if (!saved_contexts_.is_empty()) {
3934 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first());
3935 v->VisitPointers(start, start + saved_contexts_.length());
3936 }
3937}
3938
3939
3940void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
3941 v8::ImplementationUtilities::HandleScopeData* current =
3942 v8::ImplementationUtilities::CurrentHandleScope();
3943 thread_local.handle_scope_data_ = *current;
3944 thread_local.IterateThis(v);
3945}
3946
3947
3948char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
3949 HandleScopeImplementer* thread_local =
3950 reinterpret_cast<HandleScopeImplementer*>(storage);
3951 thread_local->IterateThis(v);
3952 return storage + ArchiveSpacePerThread();
3953}
3954
3955} } // namespace v8::internal