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