1 // Copyright 2010 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 32 #include "arguments.h" 33 #include "bootstrapper.h" 34 #include "compiler.h" 35 #include "debug.h" 36 #include "deoptimizer.h" 37 #include "execution.h" 38 #include "global-handles.h" 39 #include "heap-profiler.h" 40 #include "messages.h" 41 #include "parser.h" 42 #include "platform.h" 43 #include "profile-generator-inl.h" 44 #include "runtime-profiler.h" 45 #include "serialize.h" 46 #include "snapshot.h" 47 #include "v8threads.h" 48 #include "version.h" 49 #include "vm-state-inl.h" 50 51 #include "../include/v8-profiler.h" 52 #include "../include/v8-testing.h" 53 54 #define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr)) 55 56 // TODO(isolates): avoid repeated TLS reads in function prologues. 57 #ifdef ENABLE_VMSTATE_TRACKING 58 #define ENTER_V8(isolate) \ 59 ASSERT((isolate)->IsInitialized()); \ 60 i::VMState __state__((isolate), i::OTHER) 61 #define LEAVE_V8(isolate) \ 62 i::VMState __state__((isolate), i::EXTERNAL) 63 #else 64 #define ENTER_V8(isolate) ((void) 0) 65 #define LEAVE_V8(isolate) ((void) 0) 66 #endif 67 68 namespace v8 { 69 70 #define ON_BAILOUT(isolate, location, code) \ 71 if (IsDeadCheck(isolate, location) || \ 72 IsExecutionTerminatingCheck(isolate)) { \ 73 code; \ 74 UNREACHABLE(); \ 75 } 76 77 78 #define EXCEPTION_PREAMBLE(isolate) \ 79 (isolate)->handle_scope_implementer()->IncrementCallDepth(); \ 80 ASSERT(!(isolate)->external_caught_exception()); \ 81 bool has_pending_exception = false 82 83 84 #define EXCEPTION_BAILOUT_CHECK(isolate, value) \ 85 do { \ 86 i::HandleScopeImplementer* handle_scope_implementer = \ 87 (isolate)->handle_scope_implementer(); \ 88 handle_scope_implementer->DecrementCallDepth(); \ 89 if (has_pending_exception) { \ 90 if (handle_scope_implementer->CallDepthIsZero() && \ 91 (isolate)->is_out_of_memory()) { \ 92 if (!(isolate)->ignore_out_of_memory()) \ 93 i::V8::FatalProcessOutOfMemory(NULL); \ 94 } \ 95 bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero(); \ 96 (isolate)->OptionalRescheduleException(call_depth_is_zero); \ 97 return value; \ 98 } \ 99 } while (false) 100 101 // TODO(isolates): Add a parameter to this macro for an isolate. 102 103 #define API_ENTRY_CHECK(msg) \ 104 do { \ 105 if (v8::Locker::IsActive()) { \ 106 ApiCheck(i::Isolate::Current()->thread_manager()-> \ 107 IsLockedByCurrentThread(), \ 108 msg, \ 109 "Entering the V8 API without proper locking in place"); \ 110 } \ 111 } while (false) 112 113 114 // --- E x c e p t i o n B e h a v i o r --- 115 116 117 static void DefaultFatalErrorHandler(const char* location, 118 const char* message) { 119 #ifdef ENABLE_VMSTATE_TRACKING 120 i::VMState __state__(i::Isolate::Current(), i::OTHER); 121 #endif 122 API_Fatal(location, message); 123 } 124 125 126 static FatalErrorCallback GetFatalErrorHandler() { 127 i::Isolate* isolate = i::Isolate::Current(); 128 if (isolate->exception_behavior() == NULL) { 129 isolate->set_exception_behavior(DefaultFatalErrorHandler); 130 } 131 return isolate->exception_behavior(); 132 } 133 134 135 void i::FatalProcessOutOfMemory(const char* location) { 136 i::V8::FatalProcessOutOfMemory(location, false); 137 } 138 139 140 // When V8 cannot allocated memory FatalProcessOutOfMemory is called. 141 // The default fatal error handler is called and execution is stopped. 142 void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) { 143 i::HeapStats heap_stats; 144 int start_marker; 145 heap_stats.start_marker = &start_marker; 146 int new_space_size; 147 heap_stats.new_space_size = &new_space_size; 148 int new_space_capacity; 149 heap_stats.new_space_capacity = &new_space_capacity; 150 intptr_t old_pointer_space_size; 151 heap_stats.old_pointer_space_size = &old_pointer_space_size; 152 intptr_t old_pointer_space_capacity; 153 heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity; 154 intptr_t old_data_space_size; 155 heap_stats.old_data_space_size = &old_data_space_size; 156 intptr_t old_data_space_capacity; 157 heap_stats.old_data_space_capacity = &old_data_space_capacity; 158 intptr_t code_space_size; 159 heap_stats.code_space_size = &code_space_size; 160 intptr_t code_space_capacity; 161 heap_stats.code_space_capacity = &code_space_capacity; 162 intptr_t map_space_size; 163 heap_stats.map_space_size = &map_space_size; 164 intptr_t map_space_capacity; 165 heap_stats.map_space_capacity = &map_space_capacity; 166 intptr_t cell_space_size; 167 heap_stats.cell_space_size = &cell_space_size; 168 intptr_t cell_space_capacity; 169 heap_stats.cell_space_capacity = &cell_space_capacity; 170 intptr_t lo_space_size; 171 heap_stats.lo_space_size = &lo_space_size; 172 int global_handle_count; 173 heap_stats.global_handle_count = &global_handle_count; 174 int weak_global_handle_count; 175 heap_stats.weak_global_handle_count = &weak_global_handle_count; 176 int pending_global_handle_count; 177 heap_stats.pending_global_handle_count = &pending_global_handle_count; 178 int near_death_global_handle_count; 179 heap_stats.near_death_global_handle_count = &near_death_global_handle_count; 180 int destroyed_global_handle_count; 181 heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count; 182 intptr_t memory_allocator_size; 183 heap_stats.memory_allocator_size = &memory_allocator_size; 184 intptr_t memory_allocator_capacity; 185 heap_stats.memory_allocator_capacity = &memory_allocator_capacity; 186 int objects_per_type[LAST_TYPE + 1] = {0}; 187 heap_stats.objects_per_type = objects_per_type; 188 int size_per_type[LAST_TYPE + 1] = {0}; 189 heap_stats.size_per_type = size_per_type; 190 int os_error; 191 heap_stats.os_error = &os_error; 192 int end_marker; 193 heap_stats.end_marker = &end_marker; 194 i::Isolate* isolate = i::Isolate::Current(); 195 isolate->heap()->RecordStats(&heap_stats, take_snapshot); 196 i::V8::SetFatalError(); 197 FatalErrorCallback callback = GetFatalErrorHandler(); 198 { 199 LEAVE_V8(isolate); 200 callback(location, "Allocation failed - process out of memory"); 201 } 202 // If the callback returns, we stop execution. 203 UNREACHABLE(); 204 } 205 206 207 bool Utils::ReportApiFailure(const char* location, const char* message) { 208 FatalErrorCallback callback = GetFatalErrorHandler(); 209 callback(location, message); 210 i::V8::SetFatalError(); 211 return false; 212 } 213 214 215 bool V8::IsDead() { 216 return i::V8::IsDead(); 217 } 218 219 220 static inline bool ApiCheck(bool condition, 221 const char* location, 222 const char* message) { 223 return condition ? true : Utils::ReportApiFailure(location, message); 224 } 225 226 227 static bool ReportV8Dead(const char* location) { 228 FatalErrorCallback callback = GetFatalErrorHandler(); 229 callback(location, "V8 is no longer usable"); 230 return true; 231 } 232 233 234 static bool ReportEmptyHandle(const char* location) { 235 FatalErrorCallback callback = GetFatalErrorHandler(); 236 callback(location, "Reading from empty handle"); 237 return true; 238 } 239 240 241 /** 242 * IsDeadCheck checks that the vm is usable. If, for instance, the vm has been 243 * out of memory at some point this check will fail. It should be called on 244 * entry to all methods that touch anything in the heap, except destructors 245 * which you sometimes can't avoid calling after the vm has crashed. Functions 246 * that call EnsureInitialized or ON_BAILOUT don't have to also call 247 * IsDeadCheck. ON_BAILOUT has the advantage over EnsureInitialized that you 248 * can arrange to return if the VM is dead. This is needed to ensure that no VM 249 * heap allocations are attempted on a dead VM. EnsureInitialized has the 250 * advantage over ON_BAILOUT that it actually initializes the VM if this has not 251 * yet been done. 252 */ 253 static inline bool IsDeadCheck(i::Isolate* isolate, const char* location) { 254 return !isolate->IsInitialized() 255 && i::V8::IsDead() ? ReportV8Dead(location) : false; 256 } 257 258 259 static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) { 260 if (!isolate->IsInitialized()) return false; 261 if (isolate->has_scheduled_exception()) { 262 return isolate->scheduled_exception() == 263 isolate->heap()->termination_exception(); 264 } 265 return false; 266 } 267 268 269 static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) { 270 return obj.IsEmpty() ? ReportEmptyHandle(location) : false; 271 } 272 273 274 static inline bool EmptyCheck(const char* location, const v8::Data* obj) { 275 return (obj == 0) ? ReportEmptyHandle(location) : false; 276 } 277 278 // --- S t a t i c s --- 279 280 281 static bool InitializeHelper() { 282 if (i::Snapshot::Initialize()) return true; 283 return i::V8::Initialize(NULL); 284 } 285 286 287 static inline bool EnsureInitializedForIsolate(i::Isolate* isolate, 288 const char* location) { 289 if (IsDeadCheck(isolate, location)) return false; 290 if (isolate != NULL) { 291 if (isolate->IsInitialized()) return true; 292 } 293 return ApiCheck(InitializeHelper(), location, "Error initializing V8"); 294 } 295 296 // Some initializing API functions are called early and may be 297 // called on a thread different from static initializer thread. 298 // If Isolate API is used, Isolate::Enter() will initialize TLS so 299 // Isolate::Current() works. If it's a legacy case, then the thread 300 // may not have TLS initialized yet. However, in initializing APIs it 301 // may be too early to call EnsureInitialized() - some pre-init 302 // parameters still have to be configured. 303 static inline i::Isolate* EnterIsolateIfNeeded() { 304 i::Isolate* isolate = i::Isolate::UncheckedCurrent(); 305 if (isolate != NULL) 306 return isolate; 307 308 i::Isolate::EnterDefaultIsolate(); 309 isolate = i::Isolate::Current(); 310 return isolate; 311 } 312 313 314 void V8::SetFatalErrorHandler(FatalErrorCallback that) { 315 i::Isolate* isolate = EnterIsolateIfNeeded(); 316 isolate->set_exception_behavior(that); 317 } 318 319 320 #ifdef DEBUG 321 void ImplementationUtilities::ZapHandleRange(i::Object** begin, 322 i::Object** end) { 323 i::HandleScope::ZapRange(begin, end); 324 } 325 #endif 326 327 328 void V8::SetFlagsFromString(const char* str, int length) { 329 i::FlagList::SetFlagsFromString(str, length); 330 } 331 332 333 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) { 334 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags); 335 } 336 337 338 v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) { 339 i::Isolate* isolate = i::Isolate::Current(); 340 if (IsDeadCheck(isolate, "v8::ThrowException()")) { 341 return v8::Handle<Value>(); 342 } 343 ENTER_V8(isolate); 344 // If we're passed an empty handle, we throw an undefined exception 345 // to deal more gracefully with out of memory situations. 346 if (value.IsEmpty()) { 347 isolate->ScheduleThrow(isolate->heap()->undefined_value()); 348 } else { 349 isolate->ScheduleThrow(*Utils::OpenHandle(*value)); 350 } 351 return v8::Undefined(); 352 } 353 354 355 RegisteredExtension* RegisteredExtension::first_extension_ = NULL; 356 357 358 RegisteredExtension::RegisteredExtension(Extension* extension) 359 : extension_(extension), state_(UNVISITED) { } 360 361 362 void RegisteredExtension::Register(RegisteredExtension* that) { 363 that->next_ = first_extension_; 364 first_extension_ = that; 365 } 366 367 368 void RegisterExtension(Extension* that) { 369 RegisteredExtension* extension = new RegisteredExtension(that); 370 RegisteredExtension::Register(extension); 371 } 372 373 374 Extension::Extension(const char* name, 375 const char* source, 376 int dep_count, 377 const char** deps) 378 : name_(name), 379 source_(source), 380 dep_count_(dep_count), 381 deps_(deps), 382 auto_enable_(false) { } 383 384 385 v8::Handle<Primitive> Undefined() { 386 i::Isolate* isolate = i::Isolate::Current(); 387 if (!EnsureInitializedForIsolate(isolate, "v8::Undefined()")) { 388 return v8::Handle<v8::Primitive>(); 389 } 390 return v8::Handle<Primitive>(ToApi<Primitive>( 391 isolate->factory()->undefined_value())); 392 } 393 394 395 v8::Handle<Primitive> Null() { 396 i::Isolate* isolate = i::Isolate::Current(); 397 if (!EnsureInitializedForIsolate(isolate, "v8::Null()")) { 398 return v8::Handle<v8::Primitive>(); 399 } 400 return v8::Handle<Primitive>( 401 ToApi<Primitive>(isolate->factory()->null_value())); 402 } 403 404 405 v8::Handle<Boolean> True() { 406 i::Isolate* isolate = i::Isolate::Current(); 407 if (!EnsureInitializedForIsolate(isolate, "v8::True()")) { 408 return v8::Handle<Boolean>(); 409 } 410 return v8::Handle<Boolean>( 411 ToApi<Boolean>(isolate->factory()->true_value())); 412 } 413 414 415 v8::Handle<Boolean> False() { 416 i::Isolate* isolate = i::Isolate::Current(); 417 if (!EnsureInitializedForIsolate(isolate, "v8::False()")) { 418 return v8::Handle<Boolean>(); 419 } 420 return v8::Handle<Boolean>( 421 ToApi<Boolean>(isolate->factory()->false_value())); 422 } 423 424 425 ResourceConstraints::ResourceConstraints() 426 : max_young_space_size_(0), 427 max_old_space_size_(0), 428 max_executable_size_(0), 429 stack_limit_(NULL) { } 430 431 432 bool SetResourceConstraints(ResourceConstraints* constraints) { 433 i::Isolate* isolate = EnterIsolateIfNeeded(); 434 435 int young_space_size = constraints->max_young_space_size(); 436 int old_gen_size = constraints->max_old_space_size(); 437 int max_executable_size = constraints->max_executable_size(); 438 if (young_space_size != 0 || old_gen_size != 0 || max_executable_size != 0) { 439 // After initialization it's too late to change Heap constraints. 440 ASSERT(!isolate->IsInitialized()); 441 bool result = isolate->heap()->ConfigureHeap(young_space_size / 2, 442 old_gen_size, 443 max_executable_size); 444 if (!result) return false; 445 } 446 if (constraints->stack_limit() != NULL) { 447 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit()); 448 isolate->stack_guard()->SetStackLimit(limit); 449 } 450 return true; 451 } 452 453 454 i::Object** V8::GlobalizeReference(i::Object** obj) { 455 i::Isolate* isolate = i::Isolate::Current(); 456 if (IsDeadCheck(isolate, "V8::Persistent::New")) return NULL; 457 LOG_API(isolate, "Persistent::New"); 458 i::Handle<i::Object> result = 459 isolate->global_handles()->Create(*obj); 460 return result.location(); 461 } 462 463 464 void V8::MakeWeak(i::Object** object, void* parameters, 465 WeakReferenceCallback callback) { 466 i::Isolate* isolate = i::Isolate::Current(); 467 LOG_API(isolate, "MakeWeak"); 468 isolate->global_handles()->MakeWeak(object, parameters, 469 callback); 470 } 471 472 473 void V8::ClearWeak(i::Object** obj) { 474 i::Isolate* isolate = i::Isolate::Current(); 475 LOG_API(isolate, "ClearWeak"); 476 isolate->global_handles()->ClearWeakness(obj); 477 } 478 479 480 bool V8::IsGlobalNearDeath(i::Object** obj) { 481 i::Isolate* isolate = i::Isolate::Current(); 482 LOG_API(isolate, "IsGlobalNearDeath"); 483 if (!isolate->IsInitialized()) return false; 484 return i::GlobalHandles::IsNearDeath(obj); 485 } 486 487 488 bool V8::IsGlobalWeak(i::Object** obj) { 489 i::Isolate* isolate = i::Isolate::Current(); 490 LOG_API(isolate, "IsGlobalWeak"); 491 if (!isolate->IsInitialized()) return false; 492 return i::GlobalHandles::IsWeak(obj); 493 } 494 495 496 void V8::DisposeGlobal(i::Object** obj) { 497 i::Isolate* isolate = i::Isolate::Current(); 498 LOG_API(isolate, "DisposeGlobal"); 499 if (!isolate->IsInitialized()) return; 500 isolate->global_handles()->Destroy(obj); 501 } 502 503 // --- H a n d l e s --- 504 505 506 HandleScope::HandleScope() { 507 API_ENTRY_CHECK("HandleScope::HandleScope"); 508 i::Isolate* isolate = i::Isolate::Current(); 509 v8::ImplementationUtilities::HandleScopeData* current = 510 isolate->handle_scope_data(); 511 isolate_ = isolate; 512 prev_next_ = current->next; 513 prev_limit_ = current->limit; 514 is_closed_ = false; 515 current->level++; 516 } 517 518 519 HandleScope::~HandleScope() { 520 if (!is_closed_) { 521 Leave(); 522 } 523 } 524 525 526 void HandleScope::Leave() { 527 ASSERT(isolate_ == i::Isolate::Current()); 528 v8::ImplementationUtilities::HandleScopeData* current = 529 isolate_->handle_scope_data(); 530 current->level--; 531 ASSERT(current->level >= 0); 532 current->next = prev_next_; 533 if (current->limit != prev_limit_) { 534 current->limit = prev_limit_; 535 i::HandleScope::DeleteExtensions(isolate_); 536 } 537 538 #ifdef DEBUG 539 i::HandleScope::ZapRange(prev_next_, prev_limit_); 540 #endif 541 } 542 543 544 int HandleScope::NumberOfHandles() { 545 EnsureInitializedForIsolate( 546 i::Isolate::Current(), "HandleScope::NumberOfHandles"); 547 return i::HandleScope::NumberOfHandles(); 548 } 549 550 551 i::Object** HandleScope::CreateHandle(i::Object* value) { 552 return i::HandleScope::CreateHandle(value, i::Isolate::Current()); 553 } 554 555 556 i::Object** HandleScope::CreateHandle(i::HeapObject* value) { 557 ASSERT(value->IsHeapObject()); 558 return reinterpret_cast<i::Object**>( 559 i::HandleScope::CreateHandle(value, value->GetIsolate())); 560 } 561 562 563 void Context::Enter() { 564 // TODO(isolates): Context should have a pointer to isolate. 565 i::Isolate* isolate = i::Isolate::Current(); 566 if (IsDeadCheck(isolate, "v8::Context::Enter()")) return; 567 ENTER_V8(isolate); 568 569 i::Handle<i::Context> env = Utils::OpenHandle(this); 570 isolate->handle_scope_implementer()->EnterContext(env); 571 572 isolate->handle_scope_implementer()->SaveContext(isolate->context()); 573 isolate->set_context(*env); 574 } 575 576 577 void Context::Exit() { 578 // TODO(isolates): Context should have a pointer to isolate. 579 i::Isolate* isolate = i::Isolate::Current(); 580 if (!isolate->IsInitialized()) return; 581 582 if (!ApiCheck(isolate->handle_scope_implementer()->LeaveLastContext(), 583 "v8::Context::Exit()", 584 "Cannot exit non-entered context")) { 585 return; 586 } 587 588 // Content of 'last_context' could be NULL. 589 i::Context* last_context = 590 isolate->handle_scope_implementer()->RestoreContext(); 591 isolate->set_context(last_context); 592 } 593 594 595 void Context::SetData(v8::Handle<String> data) { 596 // TODO(isolates): Context should have a pointer to isolate. 597 i::Isolate* isolate = i::Isolate::Current(); 598 if (IsDeadCheck(isolate, "v8::Context::SetData()")) return; 599 ENTER_V8(isolate); 600 { 601 i::HandleScope scope(isolate); 602 i::Handle<i::Context> env = Utils::OpenHandle(this); 603 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data); 604 ASSERT(env->IsGlobalContext()); 605 if (env->IsGlobalContext()) { 606 env->set_data(*raw_data); 607 } 608 } 609 } 610 611 612 v8::Local<v8::Value> Context::GetData() { 613 // TODO(isolates): Context should have a pointer to isolate. 614 i::Isolate* isolate = i::Isolate::Current(); 615 if (IsDeadCheck(isolate, "v8::Context::GetData()")) { 616 return v8::Local<Value>(); 617 } 618 ENTER_V8(isolate); 619 i::Object* raw_result = NULL; 620 { 621 i::HandleScope scope(isolate); 622 i::Handle<i::Context> env = Utils::OpenHandle(this); 623 ASSERT(env->IsGlobalContext()); 624 if (env->IsGlobalContext()) { 625 raw_result = env->data(); 626 } else { 627 return Local<Value>(); 628 } 629 } 630 i::Handle<i::Object> result(raw_result); 631 return Utils::ToLocal(result); 632 } 633 634 635 i::Object** v8::HandleScope::RawClose(i::Object** value) { 636 if (!ApiCheck(!is_closed_, 637 "v8::HandleScope::Close()", 638 "Local scope has already been closed")) { 639 return 0; 640 } 641 LOG_API(isolate_, "CloseHandleScope"); 642 643 // Read the result before popping the handle block. 644 i::Object* result = NULL; 645 if (value != NULL) { 646 result = *value; 647 } 648 is_closed_ = true; 649 Leave(); 650 651 if (value == NULL) { 652 return NULL; 653 } 654 655 // Allocate a new handle on the previous handle block. 656 i::Handle<i::Object> handle(result); 657 return handle.location(); 658 } 659 660 661 // --- N e a n d e r --- 662 663 664 // A constructor cannot easily return an error value, therefore it is necessary 665 // to check for a dead VM with ON_BAILOUT before constructing any Neander 666 // objects. To remind you about this there is no HandleScope in the 667 // NeanderObject constructor. When you add one to the site calling the 668 // constructor you should check that you ensured the VM was not dead first. 669 NeanderObject::NeanderObject(int size) { 670 i::Isolate* isolate = i::Isolate::Current(); 671 EnsureInitializedForIsolate(isolate, "v8::Nowhere"); 672 ENTER_V8(isolate); 673 value_ = isolate->factory()->NewNeanderObject(); 674 i::Handle<i::FixedArray> elements = isolate->factory()->NewFixedArray(size); 675 value_->set_elements(*elements); 676 } 677 678 679 int NeanderObject::size() { 680 return i::FixedArray::cast(value_->elements())->length(); 681 } 682 683 684 NeanderArray::NeanderArray() : obj_(2) { 685 obj_.set(0, i::Smi::FromInt(0)); 686 } 687 688 689 int NeanderArray::length() { 690 return i::Smi::cast(obj_.get(0))->value(); 691 } 692 693 694 i::Object* NeanderArray::get(int offset) { 695 ASSERT(0 <= offset); 696 ASSERT(offset < length()); 697 return obj_.get(offset + 1); 698 } 699 700 701 // This method cannot easily return an error value, therefore it is necessary 702 // to check for a dead VM with ON_BAILOUT before calling it. To remind you 703 // about this there is no HandleScope in this method. When you add one to the 704 // site calling this method you should check that you ensured the VM was not 705 // dead first. 706 void NeanderArray::add(i::Handle<i::Object> value) { 707 int length = this->length(); 708 int size = obj_.size(); 709 if (length == size - 1) { 710 i::Handle<i::FixedArray> new_elms = FACTORY->NewFixedArray(2 * size); 711 for (int i = 0; i < length; i++) 712 new_elms->set(i + 1, get(i)); 713 obj_.value()->set_elements(*new_elms); 714 } 715 obj_.set(length + 1, *value); 716 obj_.set(0, i::Smi::FromInt(length + 1)); 717 } 718 719 720 void NeanderArray::set(int index, i::Object* value) { 721 if (index < 0 || index >= this->length()) return; 722 obj_.set(index + 1, value); 723 } 724 725 726 // --- T e m p l a t e --- 727 728 729 static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) { 730 that->set_tag(i::Smi::FromInt(type)); 731 } 732 733 734 void Template::Set(v8::Handle<String> name, v8::Handle<Data> value, 735 v8::PropertyAttribute attribute) { 736 i::Isolate* isolate = i::Isolate::Current(); 737 if (IsDeadCheck(isolate, "v8::Template::Set()")) return; 738 ENTER_V8(isolate); 739 i::HandleScope scope(isolate); 740 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_list()); 741 if (list->IsUndefined()) { 742 list = NeanderArray().value(); 743 Utils::OpenHandle(this)->set_property_list(*list); 744 } 745 NeanderArray array(list); 746 array.add(Utils::OpenHandle(*name)); 747 array.add(Utils::OpenHandle(*value)); 748 array.add(Utils::OpenHandle(*v8::Integer::New(attribute))); 749 } 750 751 752 // --- F u n c t i o n T e m p l a t e --- 753 static void InitializeFunctionTemplate( 754 i::Handle<i::FunctionTemplateInfo> info) { 755 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE)); 756 info->set_flag(0); 757 } 758 759 760 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() { 761 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 762 if (IsDeadCheck(isolate, "v8::FunctionTemplate::PrototypeTemplate()")) { 763 return Local<ObjectTemplate>(); 764 } 765 ENTER_V8(isolate); 766 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template()); 767 if (result->IsUndefined()) { 768 result = Utils::OpenHandle(*ObjectTemplate::New()); 769 Utils::OpenHandle(this)->set_prototype_template(*result); 770 } 771 return Local<ObjectTemplate>(ToApi<ObjectTemplate>(result)); 772 } 773 774 775 void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) { 776 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 777 if (IsDeadCheck(isolate, "v8::FunctionTemplate::Inherit()")) return; 778 ENTER_V8(isolate); 779 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value)); 780 } 781 782 783 Local<FunctionTemplate> FunctionTemplate::New(InvocationCallback callback, 784 v8::Handle<Value> data, v8::Handle<Signature> signature) { 785 i::Isolate* isolate = i::Isolate::Current(); 786 EnsureInitializedForIsolate(isolate, "v8::FunctionTemplate::New()"); 787 LOG_API(isolate, "FunctionTemplate::New"); 788 ENTER_V8(isolate); 789 i::Handle<i::Struct> struct_obj = 790 isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE); 791 i::Handle<i::FunctionTemplateInfo> obj = 792 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj); 793 InitializeFunctionTemplate(obj); 794 int next_serial_number = isolate->next_serial_number(); 795 isolate->set_next_serial_number(next_serial_number + 1); 796 obj->set_serial_number(i::Smi::FromInt(next_serial_number)); 797 if (callback != 0) { 798 if (data.IsEmpty()) data = v8::Undefined(); 799 Utils::ToLocal(obj)->SetCallHandler(callback, data); 800 } 801 obj->set_undetectable(false); 802 obj->set_needs_access_check(false); 803 804 if (!signature.IsEmpty()) 805 obj->set_signature(*Utils::OpenHandle(*signature)); 806 return Utils::ToLocal(obj); 807 } 808 809 810 Local<Signature> Signature::New(Handle<FunctionTemplate> receiver, 811 int argc, Handle<FunctionTemplate> argv[]) { 812 i::Isolate* isolate = i::Isolate::Current(); 813 EnsureInitializedForIsolate(isolate, "v8::Signature::New()"); 814 LOG_API(isolate, "Signature::New"); 815 ENTER_V8(isolate); 816 i::Handle<i::Struct> struct_obj = 817 isolate->factory()->NewStruct(i::SIGNATURE_INFO_TYPE); 818 i::Handle<i::SignatureInfo> obj = 819 i::Handle<i::SignatureInfo>::cast(struct_obj); 820 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver)); 821 if (argc > 0) { 822 i::Handle<i::FixedArray> args = isolate->factory()->NewFixedArray(argc); 823 for (int i = 0; i < argc; i++) { 824 if (!argv[i].IsEmpty()) 825 args->set(i, *Utils::OpenHandle(*argv[i])); 826 } 827 obj->set_args(*args); 828 } 829 return Utils::ToLocal(obj); 830 } 831 832 833 Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) { 834 Handle<FunctionTemplate> types[1] = { type }; 835 return TypeSwitch::New(1, types); 836 } 837 838 839 Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) { 840 i::Isolate* isolate = i::Isolate::Current(); 841 EnsureInitializedForIsolate(isolate, "v8::TypeSwitch::New()"); 842 LOG_API(isolate, "TypeSwitch::New"); 843 ENTER_V8(isolate); 844 i::Handle<i::FixedArray> vector = isolate->factory()->NewFixedArray(argc); 845 for (int i = 0; i < argc; i++) 846 vector->set(i, *Utils::OpenHandle(*types[i])); 847 i::Handle<i::Struct> struct_obj = 848 isolate->factory()->NewStruct(i::TYPE_SWITCH_INFO_TYPE); 849 i::Handle<i::TypeSwitchInfo> obj = 850 i::Handle<i::TypeSwitchInfo>::cast(struct_obj); 851 obj->set_types(*vector); 852 return Utils::ToLocal(obj); 853 } 854 855 856 int TypeSwitch::match(v8::Handle<Value> value) { 857 i::Isolate* isolate = i::Isolate::Current(); 858 LOG_API(isolate, "TypeSwitch::match"); 859 i::Handle<i::Object> obj = Utils::OpenHandle(*value); 860 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this); 861 i::FixedArray* types = i::FixedArray::cast(info->types()); 862 for (int i = 0; i < types->length(); i++) { 863 if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i)))) 864 return i + 1; 865 } 866 return 0; 867 } 868 869 870 #define SET_FIELD_WRAPPED(obj, setter, cdata) do { \ 871 i::Handle<i::Object> proxy = FromCData(cdata); \ 872 (obj)->setter(*proxy); \ 873 } while (false) 874 875 876 void FunctionTemplate::SetCallHandler(InvocationCallback callback, 877 v8::Handle<Value> data) { 878 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 879 if (IsDeadCheck(isolate, "v8::FunctionTemplate::SetCallHandler()")) return; 880 ENTER_V8(isolate); 881 i::HandleScope scope(isolate); 882 i::Handle<i::Struct> struct_obj = 883 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE); 884 i::Handle<i::CallHandlerInfo> obj = 885 i::Handle<i::CallHandlerInfo>::cast(struct_obj); 886 SET_FIELD_WRAPPED(obj, set_callback, callback); 887 if (data.IsEmpty()) data = v8::Undefined(); 888 obj->set_data(*Utils::OpenHandle(*data)); 889 Utils::OpenHandle(this)->set_call_code(*obj); 890 } 891 892 893 static i::Handle<i::AccessorInfo> MakeAccessorInfo( 894 v8::Handle<String> name, 895 AccessorGetter getter, 896 AccessorSetter setter, 897 v8::Handle<Value> data, 898 v8::AccessControl settings, 899 v8::PropertyAttribute attributes) { 900 i::Handle<i::AccessorInfo> obj = FACTORY->NewAccessorInfo(); 901 ASSERT(getter != NULL); 902 SET_FIELD_WRAPPED(obj, set_getter, getter); 903 SET_FIELD_WRAPPED(obj, set_setter, setter); 904 if (data.IsEmpty()) data = v8::Undefined(); 905 obj->set_data(*Utils::OpenHandle(*data)); 906 obj->set_name(*Utils::OpenHandle(*name)); 907 if (settings & ALL_CAN_READ) obj->set_all_can_read(true); 908 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true); 909 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true); 910 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes)); 911 return obj; 912 } 913 914 915 void FunctionTemplate::AddInstancePropertyAccessor( 916 v8::Handle<String> name, 917 AccessorGetter getter, 918 AccessorSetter setter, 919 v8::Handle<Value> data, 920 v8::AccessControl settings, 921 v8::PropertyAttribute attributes) { 922 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 923 if (IsDeadCheck(isolate, 924 "v8::FunctionTemplate::AddInstancePropertyAccessor()")) { 925 return; 926 } 927 ENTER_V8(isolate); 928 i::HandleScope scope(isolate); 929 930 i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name, 931 getter, setter, data, 932 settings, attributes); 933 i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors()); 934 if (list->IsUndefined()) { 935 list = NeanderArray().value(); 936 Utils::OpenHandle(this)->set_property_accessors(*list); 937 } 938 NeanderArray array(list); 939 array.add(obj); 940 } 941 942 943 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() { 944 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 945 if (IsDeadCheck(isolate, "v8::FunctionTemplate::InstanceTemplate()") 946 || EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this)) 947 return Local<ObjectTemplate>(); 948 ENTER_V8(isolate); 949 if (Utils::OpenHandle(this)->instance_template()->IsUndefined()) { 950 Local<ObjectTemplate> templ = 951 ObjectTemplate::New(v8::Handle<FunctionTemplate>(this)); 952 Utils::OpenHandle(this)->set_instance_template(*Utils::OpenHandle(*templ)); 953 } 954 i::Handle<i::ObjectTemplateInfo> result(i::ObjectTemplateInfo::cast( 955 Utils::OpenHandle(this)->instance_template())); 956 return Utils::ToLocal(result); 957 } 958 959 960 void FunctionTemplate::SetClassName(Handle<String> name) { 961 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 962 if (IsDeadCheck(isolate, "v8::FunctionTemplate::SetClassName()")) return; 963 ENTER_V8(isolate); 964 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name)); 965 } 966 967 968 void FunctionTemplate::SetHiddenPrototype(bool value) { 969 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 970 if (IsDeadCheck(isolate, "v8::FunctionTemplate::SetHiddenPrototype()")) { 971 return; 972 } 973 ENTER_V8(isolate); 974 Utils::OpenHandle(this)->set_hidden_prototype(value); 975 } 976 977 978 void FunctionTemplate::SetNamedInstancePropertyHandler( 979 NamedPropertyGetter getter, 980 NamedPropertySetter setter, 981 NamedPropertyQuery query, 982 NamedPropertyDeleter remover, 983 NamedPropertyEnumerator enumerator, 984 Handle<Value> data) { 985 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 986 if (IsDeadCheck(isolate, 987 "v8::FunctionTemplate::SetNamedInstancePropertyHandler()")) { 988 return; 989 } 990 ENTER_V8(isolate); 991 i::HandleScope scope(isolate); 992 i::Handle<i::Struct> struct_obj = 993 isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE); 994 i::Handle<i::InterceptorInfo> obj = 995 i::Handle<i::InterceptorInfo>::cast(struct_obj); 996 997 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter); 998 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter); 999 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query); 1000 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover); 1001 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); 1002 1003 if (data.IsEmpty()) data = v8::Undefined(); 1004 obj->set_data(*Utils::OpenHandle(*data)); 1005 Utils::OpenHandle(this)->set_named_property_handler(*obj); 1006 } 1007 1008 1009 void FunctionTemplate::SetIndexedInstancePropertyHandler( 1010 IndexedPropertyGetter getter, 1011 IndexedPropertySetter setter, 1012 IndexedPropertyQuery query, 1013 IndexedPropertyDeleter remover, 1014 IndexedPropertyEnumerator enumerator, 1015 Handle<Value> data) { 1016 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1017 if (IsDeadCheck(isolate, 1018 "v8::FunctionTemplate::SetIndexedInstancePropertyHandler()")) { 1019 return; 1020 } 1021 ENTER_V8(isolate); 1022 i::HandleScope scope(isolate); 1023 i::Handle<i::Struct> struct_obj = 1024 isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE); 1025 i::Handle<i::InterceptorInfo> obj = 1026 i::Handle<i::InterceptorInfo>::cast(struct_obj); 1027 1028 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter); 1029 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter); 1030 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query); 1031 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover); 1032 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); 1033 1034 if (data.IsEmpty()) data = v8::Undefined(); 1035 obj->set_data(*Utils::OpenHandle(*data)); 1036 Utils::OpenHandle(this)->set_indexed_property_handler(*obj); 1037 } 1038 1039 1040 void FunctionTemplate::SetInstanceCallAsFunctionHandler( 1041 InvocationCallback callback, 1042 Handle<Value> data) { 1043 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1044 if (IsDeadCheck(isolate, 1045 "v8::FunctionTemplate::SetInstanceCallAsFunctionHandler()")) { 1046 return; 1047 } 1048 ENTER_V8(isolate); 1049 i::HandleScope scope(isolate); 1050 i::Handle<i::Struct> struct_obj = 1051 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE); 1052 i::Handle<i::CallHandlerInfo> obj = 1053 i::Handle<i::CallHandlerInfo>::cast(struct_obj); 1054 SET_FIELD_WRAPPED(obj, set_callback, callback); 1055 if (data.IsEmpty()) data = v8::Undefined(); 1056 obj->set_data(*Utils::OpenHandle(*data)); 1057 Utils::OpenHandle(this)->set_instance_call_handler(*obj); 1058 } 1059 1060 1061 // --- O b j e c t T e m p l a t e --- 1062 1063 1064 Local<ObjectTemplate> ObjectTemplate::New() { 1065 return New(Local<FunctionTemplate>()); 1066 } 1067 1068 1069 Local<ObjectTemplate> ObjectTemplate::New( 1070 v8::Handle<FunctionTemplate> constructor) { 1071 i::Isolate* isolate = i::Isolate::Current(); 1072 if (IsDeadCheck(isolate, "v8::ObjectTemplate::New()")) { 1073 return Local<ObjectTemplate>(); 1074 } 1075 EnsureInitializedForIsolate(isolate, "v8::ObjectTemplate::New()"); 1076 LOG_API(isolate, "ObjectTemplate::New"); 1077 ENTER_V8(isolate); 1078 i::Handle<i::Struct> struct_obj = 1079 isolate->factory()->NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE); 1080 i::Handle<i::ObjectTemplateInfo> obj = 1081 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj); 1082 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE); 1083 if (!constructor.IsEmpty()) 1084 obj->set_constructor(*Utils::OpenHandle(*constructor)); 1085 obj->set_internal_field_count(i::Smi::FromInt(0)); 1086 return Utils::ToLocal(obj); 1087 } 1088 1089 1090 // Ensure that the object template has a constructor. If no 1091 // constructor is available we create one. 1092 static void EnsureConstructor(ObjectTemplate* object_template) { 1093 if (Utils::OpenHandle(object_template)->constructor()->IsUndefined()) { 1094 Local<FunctionTemplate> templ = FunctionTemplate::New(); 1095 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ); 1096 constructor->set_instance_template(*Utils::OpenHandle(object_template)); 1097 Utils::OpenHandle(object_template)->set_constructor(*constructor); 1098 } 1099 } 1100 1101 1102 void ObjectTemplate::SetAccessor(v8::Handle<String> name, 1103 AccessorGetter getter, 1104 AccessorSetter setter, 1105 v8::Handle<Value> data, 1106 AccessControl settings, 1107 PropertyAttribute attribute) { 1108 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1109 if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetAccessor()")) return; 1110 ENTER_V8(isolate); 1111 i::HandleScope scope(isolate); 1112 EnsureConstructor(this); 1113 i::FunctionTemplateInfo* constructor = 1114 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor()); 1115 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1116 Utils::ToLocal(cons)->AddInstancePropertyAccessor(name, 1117 getter, 1118 setter, 1119 data, 1120 settings, 1121 attribute); 1122 } 1123 1124 1125 void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter, 1126 NamedPropertySetter setter, 1127 NamedPropertyQuery query, 1128 NamedPropertyDeleter remover, 1129 NamedPropertyEnumerator enumerator, 1130 Handle<Value> data) { 1131 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1132 if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetNamedPropertyHandler()")) { 1133 return; 1134 } 1135 ENTER_V8(isolate); 1136 i::HandleScope scope(isolate); 1137 EnsureConstructor(this); 1138 i::FunctionTemplateInfo* constructor = 1139 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor()); 1140 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1141 Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter, 1142 setter, 1143 query, 1144 remover, 1145 enumerator, 1146 data); 1147 } 1148 1149 1150 void ObjectTemplate::MarkAsUndetectable() { 1151 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1152 if (IsDeadCheck(isolate, "v8::ObjectTemplate::MarkAsUndetectable()")) return; 1153 ENTER_V8(isolate); 1154 i::HandleScope scope(isolate); 1155 EnsureConstructor(this); 1156 i::FunctionTemplateInfo* constructor = 1157 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor()); 1158 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1159 cons->set_undetectable(true); 1160 } 1161 1162 1163 void ObjectTemplate::SetAccessCheckCallbacks( 1164 NamedSecurityCallback named_callback, 1165 IndexedSecurityCallback indexed_callback, 1166 Handle<Value> data, 1167 bool turned_on_by_default) { 1168 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1169 if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetAccessCheckCallbacks()")) { 1170 return; 1171 } 1172 ENTER_V8(isolate); 1173 i::HandleScope scope(isolate); 1174 EnsureConstructor(this); 1175 1176 i::Handle<i::Struct> struct_info = 1177 isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE); 1178 i::Handle<i::AccessCheckInfo> info = 1179 i::Handle<i::AccessCheckInfo>::cast(struct_info); 1180 1181 SET_FIELD_WRAPPED(info, set_named_callback, named_callback); 1182 SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback); 1183 1184 if (data.IsEmpty()) data = v8::Undefined(); 1185 info->set_data(*Utils::OpenHandle(*data)); 1186 1187 i::FunctionTemplateInfo* constructor = 1188 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor()); 1189 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1190 cons->set_access_check_info(*info); 1191 cons->set_needs_access_check(turned_on_by_default); 1192 } 1193 1194 1195 void ObjectTemplate::SetIndexedPropertyHandler( 1196 IndexedPropertyGetter getter, 1197 IndexedPropertySetter setter, 1198 IndexedPropertyQuery query, 1199 IndexedPropertyDeleter remover, 1200 IndexedPropertyEnumerator enumerator, 1201 Handle<Value> data) { 1202 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1203 if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetIndexedPropertyHandler()")) { 1204 return; 1205 } 1206 ENTER_V8(isolate); 1207 i::HandleScope scope(isolate); 1208 EnsureConstructor(this); 1209 i::FunctionTemplateInfo* constructor = 1210 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor()); 1211 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1212 Utils::ToLocal(cons)->SetIndexedInstancePropertyHandler(getter, 1213 setter, 1214 query, 1215 remover, 1216 enumerator, 1217 data); 1218 } 1219 1220 1221 void ObjectTemplate::SetCallAsFunctionHandler(InvocationCallback callback, 1222 Handle<Value> data) { 1223 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1224 if (IsDeadCheck(isolate, 1225 "v8::ObjectTemplate::SetCallAsFunctionHandler()")) { 1226 return; 1227 } 1228 ENTER_V8(isolate); 1229 i::HandleScope scope(isolate); 1230 EnsureConstructor(this); 1231 i::FunctionTemplateInfo* constructor = 1232 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor()); 1233 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1234 Utils::ToLocal(cons)->SetInstanceCallAsFunctionHandler(callback, data); 1235 } 1236 1237 1238 int ObjectTemplate::InternalFieldCount() { 1239 if (IsDeadCheck(Utils::OpenHandle(this)->GetIsolate(), 1240 "v8::ObjectTemplate::InternalFieldCount()")) { 1241 return 0; 1242 } 1243 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value(); 1244 } 1245 1246 1247 void ObjectTemplate::SetInternalFieldCount(int value) { 1248 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1249 if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetInternalFieldCount()")) { 1250 return; 1251 } 1252 if (!ApiCheck(i::Smi::IsValid(value), 1253 "v8::ObjectTemplate::SetInternalFieldCount()", 1254 "Invalid internal field count")) { 1255 return; 1256 } 1257 ENTER_V8(isolate); 1258 if (value > 0) { 1259 // The internal field count is set by the constructor function's 1260 // construct code, so we ensure that there is a constructor 1261 // function to do the setting. 1262 EnsureConstructor(this); 1263 } 1264 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value)); 1265 } 1266 1267 1268 // --- S c r i p t D a t a --- 1269 1270 1271 ScriptData* ScriptData::PreCompile(const char* input, int length) { 1272 i::Utf8ToUC16CharacterStream stream( 1273 reinterpret_cast<const unsigned char*>(input), length); 1274 return i::ParserApi::PreParse(&stream, NULL); 1275 } 1276 1277 1278 ScriptData* ScriptData::PreCompile(v8::Handle<String> source) { 1279 i::Handle<i::String> str = Utils::OpenHandle(*source); 1280 if (str->IsExternalTwoByteString()) { 1281 i::ExternalTwoByteStringUC16CharacterStream stream( 1282 i::Handle<i::ExternalTwoByteString>::cast(str), 0, str->length()); 1283 return i::ParserApi::PreParse(&stream, NULL); 1284 } else { 1285 i::GenericStringUC16CharacterStream stream(str, 0, str->length()); 1286 return i::ParserApi::PreParse(&stream, NULL); 1287 } 1288 } 1289 1290 1291 ScriptData* ScriptData::New(const char* data, int length) { 1292 // Return an empty ScriptData if the length is obviously invalid. 1293 if (length % sizeof(unsigned) != 0) { 1294 return new i::ScriptDataImpl(); 1295 } 1296 1297 // Copy the data to ensure it is properly aligned. 1298 int deserialized_data_length = length / sizeof(unsigned); 1299 // If aligned, don't create a copy of the data. 1300 if (reinterpret_cast<intptr_t>(data) % sizeof(unsigned) == 0) { 1301 return new i::ScriptDataImpl(data, length); 1302 } 1303 // Copy the data to align it. 1304 unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length); 1305 i::OS::MemCopy(deserialized_data, data, length); 1306 1307 return new i::ScriptDataImpl( 1308 i::Vector<unsigned>(deserialized_data, deserialized_data_length)); 1309 } 1310 1311 1312 // --- S c r i p t --- 1313 1314 1315 Local<Script> Script::New(v8::Handle<String> source, 1316 v8::ScriptOrigin* origin, 1317 v8::ScriptData* pre_data, 1318 v8::Handle<String> script_data) { 1319 i::Isolate* isolate = i::Isolate::Current(); 1320 ON_BAILOUT(isolate, "v8::Script::New()", return Local<Script>()); 1321 LOG_API(isolate, "Script::New"); 1322 ENTER_V8(isolate); 1323 i::Handle<i::String> str = Utils::OpenHandle(*source); 1324 i::Handle<i::Object> name_obj; 1325 int line_offset = 0; 1326 int column_offset = 0; 1327 if (origin != NULL) { 1328 if (!origin->ResourceName().IsEmpty()) { 1329 name_obj = Utils::OpenHandle(*origin->ResourceName()); 1330 } 1331 if (!origin->ResourceLineOffset().IsEmpty()) { 1332 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value()); 1333 } 1334 if (!origin->ResourceColumnOffset().IsEmpty()) { 1335 column_offset = static_cast<int>(origin->ResourceColumnOffset()->Value()); 1336 } 1337 } 1338 EXCEPTION_PREAMBLE(isolate); 1339 i::ScriptDataImpl* pre_data_impl = static_cast<i::ScriptDataImpl*>(pre_data); 1340 // We assert that the pre-data is sane, even though we can actually 1341 // handle it if it turns out not to be in release mode. 1342 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck()); 1343 // If the pre-data isn't sane we simply ignore it 1344 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) { 1345 pre_data_impl = NULL; 1346 } 1347 i::Handle<i::SharedFunctionInfo> result = 1348 i::Compiler::Compile(str, 1349 name_obj, 1350 line_offset, 1351 column_offset, 1352 NULL, 1353 pre_data_impl, 1354 Utils::OpenHandle(*script_data), 1355 i::NOT_NATIVES_CODE); 1356 has_pending_exception = result.is_null(); 1357 EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>()); 1358 return Local<Script>(ToApi<Script>(result)); 1359 } 1360 1361 1362 Local<Script> Script::New(v8::Handle<String> source, 1363 v8::Handle<Value> file_name) { 1364 ScriptOrigin origin(file_name); 1365 return New(source, &origin); 1366 } 1367 1368 1369 Local<Script> Script::Compile(v8::Handle<String> source, 1370 v8::ScriptOrigin* origin, 1371 v8::ScriptData* pre_data, 1372 v8::Handle<String> script_data) { 1373 i::Isolate* isolate = i::Isolate::Current(); 1374 ON_BAILOUT(isolate, "v8::Script::Compile()", return Local<Script>()); 1375 LOG_API(isolate, "Script::Compile"); 1376 ENTER_V8(isolate); 1377 Local<Script> generic = New(source, origin, pre_data, script_data); 1378 if (generic.IsEmpty()) 1379 return generic; 1380 i::Handle<i::Object> obj = Utils::OpenHandle(*generic); 1381 i::Handle<i::SharedFunctionInfo> function = 1382 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj)); 1383 i::Handle<i::JSFunction> result = 1384 isolate->factory()->NewFunctionFromSharedFunctionInfo( 1385 function, 1386 isolate->global_context()); 1387 return Local<Script>(ToApi<Script>(result)); 1388 } 1389 1390 1391 Local<Script> Script::Compile(v8::Handle<String> source, 1392 v8::Handle<Value> file_name, 1393 v8::Handle<String> script_data) { 1394 ScriptOrigin origin(file_name); 1395 return Compile(source, &origin, 0, script_data); 1396 } 1397 1398 1399 Local<Value> Script::Run() { 1400 i::Isolate* isolate = i::Isolate::Current(); 1401 ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>()); 1402 LOG_API(isolate, "Script::Run"); 1403 ENTER_V8(isolate); 1404 i::Object* raw_result = NULL; 1405 { 1406 i::HandleScope scope(isolate); 1407 i::Handle<i::Object> obj = Utils::OpenHandle(this); 1408 i::Handle<i::JSFunction> fun; 1409 if (obj->IsSharedFunctionInfo()) { 1410 i::Handle<i::SharedFunctionInfo> 1411 function_info(i::SharedFunctionInfo::cast(*obj), isolate); 1412 fun = isolate->factory()->NewFunctionFromSharedFunctionInfo( 1413 function_info, isolate->global_context()); 1414 } else { 1415 fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj), isolate); 1416 } 1417 EXCEPTION_PREAMBLE(isolate); 1418 i::Handle<i::Object> receiver( 1419 isolate->context()->global_proxy(), isolate); 1420 i::Handle<i::Object> result = 1421 i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception); 1422 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 1423 raw_result = *result; 1424 } 1425 i::Handle<i::Object> result(raw_result, isolate); 1426 return Utils::ToLocal(result); 1427 } 1428 1429 1430 static i::Handle<i::SharedFunctionInfo> OpenScript(Script* script) { 1431 i::Handle<i::Object> obj = Utils::OpenHandle(script); 1432 i::Handle<i::SharedFunctionInfo> result; 1433 if (obj->IsSharedFunctionInfo()) { 1434 result = 1435 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj)); 1436 } else { 1437 result = 1438 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared()); 1439 } 1440 return result; 1441 } 1442 1443 1444 Local<Value> Script::Id() { 1445 i::Isolate* isolate = i::Isolate::Current(); 1446 ON_BAILOUT(isolate, "v8::Script::Id()", return Local<Value>()); 1447 LOG_API(isolate, "Script::Id"); 1448 i::Object* raw_id = NULL; 1449 { 1450 i::HandleScope scope(isolate); 1451 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this); 1452 i::Handle<i::Script> script(i::Script::cast(function_info->script())); 1453 i::Handle<i::Object> id(script->id()); 1454 raw_id = *id; 1455 } 1456 i::Handle<i::Object> id(raw_id); 1457 return Utils::ToLocal(id); 1458 } 1459 1460 1461 void Script::SetData(v8::Handle<String> data) { 1462 i::Isolate* isolate = i::Isolate::Current(); 1463 ON_BAILOUT(isolate, "v8::Script::SetData()", return); 1464 LOG_API(isolate, "Script::SetData"); 1465 { 1466 i::HandleScope scope(isolate); 1467 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this); 1468 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data); 1469 i::Handle<i::Script> script(i::Script::cast(function_info->script())); 1470 script->set_data(*raw_data); 1471 } 1472 } 1473 1474 1475 // --- E x c e p t i o n s --- 1476 1477 1478 v8::TryCatch::TryCatch() 1479 : next_(i::Isolate::Current()->try_catch_handler_address()), 1480 exception_(HEAP->the_hole_value()), 1481 message_(i::Smi::FromInt(0)), 1482 is_verbose_(false), 1483 can_continue_(true), 1484 capture_message_(true), 1485 rethrow_(false) { 1486 i::Isolate::Current()->RegisterTryCatchHandler(this); 1487 } 1488 1489 1490 v8::TryCatch::~TryCatch() { 1491 i::Isolate* isolate = i::Isolate::Current(); 1492 if (rethrow_) { 1493 v8::HandleScope scope; 1494 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception()); 1495 isolate->UnregisterTryCatchHandler(this); 1496 v8::ThrowException(exc); 1497 } else { 1498 isolate->UnregisterTryCatchHandler(this); 1499 } 1500 } 1501 1502 1503 bool v8::TryCatch::HasCaught() const { 1504 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole(); 1505 } 1506 1507 1508 bool v8::TryCatch::CanContinue() const { 1509 return can_continue_; 1510 } 1511 1512 1513 v8::Handle<v8::Value> v8::TryCatch::ReThrow() { 1514 if (!HasCaught()) return v8::Local<v8::Value>(); 1515 rethrow_ = true; 1516 return v8::Undefined(); 1517 } 1518 1519 1520 v8::Local<Value> v8::TryCatch::Exception() const { 1521 if (HasCaught()) { 1522 // Check for out of memory exception. 1523 i::Object* exception = reinterpret_cast<i::Object*>(exception_); 1524 return v8::Utils::ToLocal(i::Handle<i::Object>(exception)); 1525 } else { 1526 return v8::Local<Value>(); 1527 } 1528 } 1529 1530 1531 v8::Local<Value> v8::TryCatch::StackTrace() const { 1532 if (HasCaught()) { 1533 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_); 1534 if (!raw_obj->IsJSObject()) return v8::Local<Value>(); 1535 v8::HandleScope scope; 1536 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj)); 1537 i::Handle<i::String> name = FACTORY->LookupAsciiSymbol("stack"); 1538 if (!obj->HasProperty(*name)) 1539 return v8::Local<Value>(); 1540 return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name))); 1541 } else { 1542 return v8::Local<Value>(); 1543 } 1544 } 1545 1546 1547 v8::Local<v8::Message> v8::TryCatch::Message() const { 1548 if (HasCaught() && message_ != i::Smi::FromInt(0)) { 1549 i::Object* message = reinterpret_cast<i::Object*>(message_); 1550 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message)); 1551 } else { 1552 return v8::Local<v8::Message>(); 1553 } 1554 } 1555 1556 1557 void v8::TryCatch::Reset() { 1558 exception_ = HEAP->the_hole_value(); 1559 message_ = i::Smi::FromInt(0); 1560 } 1561 1562 1563 void v8::TryCatch::SetVerbose(bool value) { 1564 is_verbose_ = value; 1565 } 1566 1567 1568 void v8::TryCatch::SetCaptureMessage(bool value) { 1569 capture_message_ = value; 1570 } 1571 1572 1573 // --- M e s s a g e --- 1574 1575 1576 Local<String> Message::Get() const { 1577 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1578 ON_BAILOUT(isolate, "v8::Message::Get()", return Local<String>()); 1579 ENTER_V8(isolate); 1580 HandleScope scope; 1581 i::Handle<i::Object> obj = Utils::OpenHandle(this); 1582 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(obj); 1583 Local<String> result = Utils::ToLocal(raw_result); 1584 return scope.Close(result); 1585 } 1586 1587 1588 v8::Handle<Value> Message::GetScriptResourceName() const { 1589 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1590 if (IsDeadCheck(isolate, "v8::Message::GetScriptResourceName()")) { 1591 return Local<String>(); 1592 } 1593 ENTER_V8(isolate); 1594 HandleScope scope; 1595 i::Handle<i::JSMessageObject> message = 1596 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 1597 // Return this.script.name. 1598 i::Handle<i::JSValue> script = 1599 i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script())); 1600 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name()); 1601 return scope.Close(Utils::ToLocal(resource_name)); 1602 } 1603 1604 1605 v8::Handle<Value> Message::GetScriptData() const { 1606 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1607 if (IsDeadCheck(isolate, "v8::Message::GetScriptResourceData()")) { 1608 return Local<Value>(); 1609 } 1610 ENTER_V8(isolate); 1611 HandleScope scope; 1612 i::Handle<i::JSMessageObject> message = 1613 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 1614 // Return this.script.data. 1615 i::Handle<i::JSValue> script = 1616 i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script())); 1617 i::Handle<i::Object> data(i::Script::cast(script->value())->data()); 1618 return scope.Close(Utils::ToLocal(data)); 1619 } 1620 1621 1622 v8::Handle<v8::StackTrace> Message::GetStackTrace() const { 1623 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1624 if (IsDeadCheck(isolate, "v8::Message::GetStackTrace()")) { 1625 return Local<v8::StackTrace>(); 1626 } 1627 ENTER_V8(isolate); 1628 HandleScope scope; 1629 i::Handle<i::JSMessageObject> message = 1630 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 1631 i::Handle<i::Object> stackFramesObj(message->stack_frames()); 1632 if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>(); 1633 i::Handle<i::JSArray> stackTrace = 1634 i::Handle<i::JSArray>::cast(stackFramesObj); 1635 return scope.Close(Utils::StackTraceToLocal(stackTrace)); 1636 } 1637 1638 1639 static i::Handle<i::Object> CallV8HeapFunction(const char* name, 1640 i::Handle<i::Object> recv, 1641 int argc, 1642 i::Object** argv[], 1643 bool* has_pending_exception) { 1644 i::Isolate* isolate = i::Isolate::Current(); 1645 i::Handle<i::String> fmt_str = isolate->factory()->LookupAsciiSymbol(name); 1646 i::Object* object_fun = 1647 isolate->js_builtins_object()->GetPropertyNoExceptionThrown(*fmt_str); 1648 i::Handle<i::JSFunction> fun = 1649 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun)); 1650 i::Handle<i::Object> value = 1651 i::Execution::Call(fun, recv, argc, argv, has_pending_exception); 1652 return value; 1653 } 1654 1655 1656 static i::Handle<i::Object> CallV8HeapFunction(const char* name, 1657 i::Handle<i::Object> data, 1658 bool* has_pending_exception) { 1659 i::Object** argv[1] = { data.location() }; 1660 return CallV8HeapFunction(name, 1661 i::Isolate::Current()->js_builtins_object(), 1662 1, 1663 argv, 1664 has_pending_exception); 1665 } 1666 1667 1668 int Message::GetLineNumber() const { 1669 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1670 ON_BAILOUT(isolate, "v8::Message::GetLineNumber()", return kNoLineNumberInfo); 1671 ENTER_V8(isolate); 1672 i::HandleScope scope(isolate); 1673 1674 EXCEPTION_PREAMBLE(isolate); 1675 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber", 1676 Utils::OpenHandle(this), 1677 &has_pending_exception); 1678 EXCEPTION_BAILOUT_CHECK(isolate, 0); 1679 return static_cast<int>(result->Number()); 1680 } 1681 1682 1683 int Message::GetStartPosition() const { 1684 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1685 if (IsDeadCheck(isolate, "v8::Message::GetStartPosition()")) return 0; 1686 ENTER_V8(isolate); 1687 i::HandleScope scope(isolate); 1688 i::Handle<i::JSMessageObject> message = 1689 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 1690 return message->start_position(); 1691 } 1692 1693 1694 int Message::GetEndPosition() const { 1695 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1696 if (IsDeadCheck(isolate, "v8::Message::GetEndPosition()")) return 0; 1697 ENTER_V8(isolate); 1698 i::HandleScope scope(isolate); 1699 i::Handle<i::JSMessageObject> message = 1700 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 1701 return message->end_position(); 1702 } 1703 1704 1705 int Message::GetStartColumn() const { 1706 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1707 if (IsDeadCheck(isolate, "v8::Message::GetStartColumn()")) { 1708 return kNoColumnInfo; 1709 } 1710 ENTER_V8(isolate); 1711 i::HandleScope scope(isolate); 1712 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this); 1713 EXCEPTION_PREAMBLE(isolate); 1714 i::Handle<i::Object> start_col_obj = CallV8HeapFunction( 1715 "GetPositionInLine", 1716 data_obj, 1717 &has_pending_exception); 1718 EXCEPTION_BAILOUT_CHECK(isolate, 0); 1719 return static_cast<int>(start_col_obj->Number()); 1720 } 1721 1722 1723 int Message::GetEndColumn() const { 1724 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1725 if (IsDeadCheck(isolate, "v8::Message::GetEndColumn()")) return kNoColumnInfo; 1726 ENTER_V8(isolate); 1727 i::HandleScope scope(isolate); 1728 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this); 1729 EXCEPTION_PREAMBLE(isolate); 1730 i::Handle<i::Object> start_col_obj = CallV8HeapFunction( 1731 "GetPositionInLine", 1732 data_obj, 1733 &has_pending_exception); 1734 EXCEPTION_BAILOUT_CHECK(isolate, 0); 1735 i::Handle<i::JSMessageObject> message = 1736 i::Handle<i::JSMessageObject>::cast(data_obj); 1737 int start = message->start_position(); 1738 int end = message->end_position(); 1739 return static_cast<int>(start_col_obj->Number()) + (end - start); 1740 } 1741 1742 1743 Local<String> Message::GetSourceLine() const { 1744 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1745 ON_BAILOUT(isolate, "v8::Message::GetSourceLine()", return Local<String>()); 1746 ENTER_V8(isolate); 1747 HandleScope scope; 1748 EXCEPTION_PREAMBLE(isolate); 1749 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine", 1750 Utils::OpenHandle(this), 1751 &has_pending_exception); 1752 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::String>()); 1753 if (result->IsString()) { 1754 return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result))); 1755 } else { 1756 return Local<String>(); 1757 } 1758 } 1759 1760 1761 void Message::PrintCurrentStackTrace(FILE* out) { 1762 i::Isolate* isolate = i::Isolate::Current(); 1763 if (IsDeadCheck(isolate, "v8::Message::PrintCurrentStackTrace()")) return; 1764 ENTER_V8(isolate); 1765 isolate->PrintCurrentStackTrace(out); 1766 } 1767 1768 1769 // --- S t a c k T r a c e --- 1770 1771 Local<StackFrame> StackTrace::GetFrame(uint32_t index) const { 1772 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1773 if (IsDeadCheck(isolate, "v8::StackTrace::GetFrame()")) { 1774 return Local<StackFrame>(); 1775 } 1776 ENTER_V8(isolate); 1777 HandleScope scope; 1778 i::Handle<i::JSArray> self = Utils::OpenHandle(this); 1779 i::Object* raw_object = self->GetElementNoExceptionThrown(index); 1780 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_object)); 1781 return scope.Close(Utils::StackFrameToLocal(obj)); 1782 } 1783 1784 1785 int StackTrace::GetFrameCount() const { 1786 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1787 if (IsDeadCheck(isolate, "v8::StackTrace::GetFrameCount()")) return -1; 1788 ENTER_V8(isolate); 1789 return i::Smi::cast(Utils::OpenHandle(this)->length())->value(); 1790 } 1791 1792 1793 Local<Array> StackTrace::AsArray() { 1794 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1795 if (IsDeadCheck(isolate, "v8::StackTrace::AsArray()")) Local<Array>(); 1796 ENTER_V8(isolate); 1797 return Utils::ToLocal(Utils::OpenHandle(this)); 1798 } 1799 1800 1801 Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit, 1802 StackTraceOptions options) { 1803 i::Isolate* isolate = i::Isolate::Current(); 1804 if (IsDeadCheck(isolate, "v8::StackTrace::CurrentStackTrace()")) { 1805 Local<StackTrace>(); 1806 } 1807 ENTER_V8(isolate); 1808 i::Handle<i::JSArray> stackTrace = 1809 isolate->CaptureCurrentStackTrace(frame_limit, options); 1810 return Utils::StackTraceToLocal(stackTrace); 1811 } 1812 1813 1814 // --- S t a c k F r a m e --- 1815 1816 int StackFrame::GetLineNumber() const { 1817 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1818 if (IsDeadCheck(isolate, "v8::StackFrame::GetLineNumber()")) { 1819 return Message::kNoLineNumberInfo; 1820 } 1821 ENTER_V8(isolate); 1822 i::HandleScope scope(isolate); 1823 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 1824 i::Handle<i::Object> line = GetProperty(self, "lineNumber"); 1825 if (!line->IsSmi()) { 1826 return Message::kNoLineNumberInfo; 1827 } 1828 return i::Smi::cast(*line)->value(); 1829 } 1830 1831 1832 int StackFrame::GetColumn() const { 1833 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1834 if (IsDeadCheck(isolate, "v8::StackFrame::GetColumn()")) { 1835 return Message::kNoColumnInfo; 1836 } 1837 ENTER_V8(isolate); 1838 i::HandleScope scope(isolate); 1839 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 1840 i::Handle<i::Object> column = GetProperty(self, "column"); 1841 if (!column->IsSmi()) { 1842 return Message::kNoColumnInfo; 1843 } 1844 return i::Smi::cast(*column)->value(); 1845 } 1846 1847 1848 Local<String> StackFrame::GetScriptName() const { 1849 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1850 if (IsDeadCheck(isolate, "v8::StackFrame::GetScriptName()")) { 1851 return Local<String>(); 1852 } 1853 ENTER_V8(isolate); 1854 HandleScope scope; 1855 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 1856 i::Handle<i::Object> name = GetProperty(self, "scriptName"); 1857 if (!name->IsString()) { 1858 return Local<String>(); 1859 } 1860 return scope.Close(Local<String>::Cast(Utils::ToLocal(name))); 1861 } 1862 1863 1864 Local<String> StackFrame::GetScriptNameOrSourceURL() const { 1865 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1866 if (IsDeadCheck(isolate, "v8::StackFrame::GetScriptNameOrSourceURL()")) { 1867 return Local<String>(); 1868 } 1869 ENTER_V8(isolate); 1870 HandleScope scope; 1871 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 1872 i::Handle<i::Object> name = GetProperty(self, "scriptNameOrSourceURL"); 1873 if (!name->IsString()) { 1874 return Local<String>(); 1875 } 1876 return scope.Close(Local<String>::Cast(Utils::ToLocal(name))); 1877 } 1878 1879 1880 Local<String> StackFrame::GetFunctionName() const { 1881 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1882 if (IsDeadCheck(isolate, "v8::StackFrame::GetFunctionName()")) { 1883 return Local<String>(); 1884 } 1885 ENTER_V8(isolate); 1886 HandleScope scope; 1887 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 1888 i::Handle<i::Object> name = GetProperty(self, "functionName"); 1889 if (!name->IsString()) { 1890 return Local<String>(); 1891 } 1892 return scope.Close(Local<String>::Cast(Utils::ToLocal(name))); 1893 } 1894 1895 1896 bool StackFrame::IsEval() const { 1897 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1898 if (IsDeadCheck(isolate, "v8::StackFrame::IsEval()")) return false; 1899 ENTER_V8(isolate); 1900 i::HandleScope scope(isolate); 1901 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 1902 i::Handle<i::Object> is_eval = GetProperty(self, "isEval"); 1903 return is_eval->IsTrue(); 1904 } 1905 1906 1907 bool StackFrame::IsConstructor() const { 1908 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1909 if (IsDeadCheck(isolate, "v8::StackFrame::IsConstructor()")) return false; 1910 ENTER_V8(isolate); 1911 i::HandleScope scope(isolate); 1912 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 1913 i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor"); 1914 return is_constructor->IsTrue(); 1915 } 1916 1917 1918 // --- D a t a --- 1919 1920 bool Value::IsUndefined() const { 1921 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsUndefined()")) { 1922 return false; 1923 } 1924 return Utils::OpenHandle(this)->IsUndefined(); 1925 } 1926 1927 1928 bool Value::IsNull() const { 1929 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsNull()")) return false; 1930 return Utils::OpenHandle(this)->IsNull(); 1931 } 1932 1933 1934 bool Value::IsTrue() const { 1935 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsTrue()")) return false; 1936 return Utils::OpenHandle(this)->IsTrue(); 1937 } 1938 1939 1940 bool Value::IsFalse() const { 1941 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsFalse()")) return false; 1942 return Utils::OpenHandle(this)->IsFalse(); 1943 } 1944 1945 1946 bool Value::IsFunction() const { 1947 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsFunction()")) { 1948 return false; 1949 } 1950 return Utils::OpenHandle(this)->IsJSFunction(); 1951 } 1952 1953 1954 bool Value::FullIsString() const { 1955 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsString()")) return false; 1956 bool result = Utils::OpenHandle(this)->IsString(); 1957 ASSERT_EQ(result, QuickIsString()); 1958 return result; 1959 } 1960 1961 1962 bool Value::IsArray() const { 1963 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsArray()")) return false; 1964 return Utils::OpenHandle(this)->IsJSArray(); 1965 } 1966 1967 1968 bool Value::IsObject() const { 1969 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsObject()")) return false; 1970 return Utils::OpenHandle(this)->IsJSObject(); 1971 } 1972 1973 1974 bool Value::IsNumber() const { 1975 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsNumber()")) return false; 1976 return Utils::OpenHandle(this)->IsNumber(); 1977 } 1978 1979 1980 bool Value::IsBoolean() const { 1981 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsBoolean()")) { 1982 return false; 1983 } 1984 return Utils::OpenHandle(this)->IsBoolean(); 1985 } 1986 1987 1988 bool Value::IsExternal() const { 1989 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsExternal()")) { 1990 return false; 1991 } 1992 return Utils::OpenHandle(this)->IsProxy(); 1993 } 1994 1995 1996 bool Value::IsInt32() const { 1997 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsInt32()")) return false; 1998 i::Handle<i::Object> obj = Utils::OpenHandle(this); 1999 if (obj->IsSmi()) return true; 2000 if (obj->IsNumber()) { 2001 double value = obj->Number(); 2002 return i::FastI2D(i::FastD2I(value)) == value; 2003 } 2004 return false; 2005 } 2006 2007 2008 bool Value::IsUint32() const { 2009 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsUint32()")) return false; 2010 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2011 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0; 2012 if (obj->IsNumber()) { 2013 double value = obj->Number(); 2014 return i::FastUI2D(i::FastD2UI(value)) == value; 2015 } 2016 return false; 2017 } 2018 2019 2020 bool Value::IsDate() const { 2021 i::Isolate* isolate = i::Isolate::Current(); 2022 if (IsDeadCheck(isolate, "v8::Value::IsDate()")) return false; 2023 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2024 return obj->HasSpecificClassOf(isolate->heap()->Date_symbol()); 2025 } 2026 2027 2028 bool Value::IsRegExp() const { 2029 if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsRegExp()")) return false; 2030 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2031 return obj->IsJSRegExp(); 2032 } 2033 2034 2035 Local<String> Value::ToString() const { 2036 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2037 i::Handle<i::Object> str; 2038 if (obj->IsString()) { 2039 str = obj; 2040 } else { 2041 i::Isolate* isolate = i::Isolate::Current(); 2042 if (IsDeadCheck(isolate, "v8::Value::ToString()")) { 2043 return Local<String>(); 2044 } 2045 LOG_API(isolate, "ToString"); 2046 ENTER_V8(isolate); 2047 EXCEPTION_PREAMBLE(isolate); 2048 str = i::Execution::ToString(obj, &has_pending_exception); 2049 EXCEPTION_BAILOUT_CHECK(isolate, Local<String>()); 2050 } 2051 return Local<String>(ToApi<String>(str)); 2052 } 2053 2054 2055 Local<String> Value::ToDetailString() const { 2056 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2057 i::Handle<i::Object> str; 2058 if (obj->IsString()) { 2059 str = obj; 2060 } else { 2061 i::Isolate* isolate = i::Isolate::Current(); 2062 if (IsDeadCheck(isolate, "v8::Value::ToDetailString()")) { 2063 return Local<String>(); 2064 } 2065 LOG_API(isolate, "ToDetailString"); 2066 ENTER_V8(isolate); 2067 EXCEPTION_PREAMBLE(isolate); 2068 str = i::Execution::ToDetailString(obj, &has_pending_exception); 2069 EXCEPTION_BAILOUT_CHECK(isolate, Local<String>()); 2070 } 2071 return Local<String>(ToApi<String>(str)); 2072 } 2073 2074 2075 Local<v8::Object> Value::ToObject() const { 2076 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2077 i::Handle<i::Object> val; 2078 if (obj->IsJSObject()) { 2079 val = obj; 2080 } else { 2081 i::Isolate* isolate = i::Isolate::Current(); 2082 if (IsDeadCheck(isolate, "v8::Value::ToObject()")) { 2083 return Local<v8::Object>(); 2084 } 2085 LOG_API(isolate, "ToObject"); 2086 ENTER_V8(isolate); 2087 EXCEPTION_PREAMBLE(isolate); 2088 val = i::Execution::ToObject(obj, &has_pending_exception); 2089 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); 2090 } 2091 return Local<v8::Object>(ToApi<Object>(val)); 2092 } 2093 2094 2095 Local<Boolean> Value::ToBoolean() const { 2096 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2097 if (obj->IsBoolean()) { 2098 return Local<Boolean>(ToApi<Boolean>(obj)); 2099 } else { 2100 i::Isolate* isolate = i::Isolate::Current(); 2101 if (IsDeadCheck(isolate, "v8::Value::ToBoolean()")) { 2102 return Local<Boolean>(); 2103 } 2104 LOG_API(isolate, "ToBoolean"); 2105 ENTER_V8(isolate); 2106 i::Handle<i::Object> val = i::Execution::ToBoolean(obj); 2107 return Local<Boolean>(ToApi<Boolean>(val)); 2108 } 2109 } 2110 2111 2112 Local<Number> Value::ToNumber() const { 2113 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2114 i::Handle<i::Object> num; 2115 if (obj->IsNumber()) { 2116 num = obj; 2117 } else { 2118 i::Isolate* isolate = i::Isolate::Current(); 2119 if (IsDeadCheck(isolate, "v8::Value::ToNumber()")) { 2120 return Local<Number>(); 2121 } 2122 LOG_API(isolate, "ToNumber"); 2123 ENTER_V8(isolate); 2124 EXCEPTION_PREAMBLE(isolate); 2125 num = i::Execution::ToNumber(obj, &has_pending_exception); 2126 EXCEPTION_BAILOUT_CHECK(isolate, Local<Number>()); 2127 } 2128 return Local<Number>(ToApi<Number>(num)); 2129 } 2130 2131 2132 Local<Integer> Value::ToInteger() const { 2133 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2134 i::Handle<i::Object> num; 2135 if (obj->IsSmi()) { 2136 num = obj; 2137 } else { 2138 i::Isolate* isolate = i::Isolate::Current(); 2139 if (IsDeadCheck(isolate, "v8::Value::ToInteger()")) return Local<Integer>(); 2140 LOG_API(isolate, "ToInteger"); 2141 ENTER_V8(isolate); 2142 EXCEPTION_PREAMBLE(isolate); 2143 num = i::Execution::ToInteger(obj, &has_pending_exception); 2144 EXCEPTION_BAILOUT_CHECK(isolate, Local<Integer>()); 2145 } 2146 return Local<Integer>(ToApi<Integer>(num)); 2147 } 2148 2149 2150 void External::CheckCast(v8::Value* that) { 2151 if (IsDeadCheck(i::Isolate::Current(), "v8::External::Cast()")) return; 2152 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2153 ApiCheck(obj->IsProxy(), 2154 "v8::External::Cast()", 2155 "Could not convert to external"); 2156 } 2157 2158 2159 void v8::Object::CheckCast(Value* that) { 2160 if (IsDeadCheck(i::Isolate::Current(), "v8::Object::Cast()")) return; 2161 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2162 ApiCheck(obj->IsJSObject(), 2163 "v8::Object::Cast()", 2164 "Could not convert to object"); 2165 } 2166 2167 2168 void v8::Function::CheckCast(Value* that) { 2169 if (IsDeadCheck(i::Isolate::Current(), "v8::Function::Cast()")) return; 2170 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2171 ApiCheck(obj->IsJSFunction(), 2172 "v8::Function::Cast()", 2173 "Could not convert to function"); 2174 } 2175 2176 2177 void v8::String::CheckCast(v8::Value* that) { 2178 if (IsDeadCheck(i::Isolate::Current(), "v8::String::Cast()")) return; 2179 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2180 ApiCheck(obj->IsString(), 2181 "v8::String::Cast()", 2182 "Could not convert to string"); 2183 } 2184 2185 2186 void v8::Number::CheckCast(v8::Value* that) { 2187 if (IsDeadCheck(i::Isolate::Current(), "v8::Number::Cast()")) return; 2188 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2189 ApiCheck(obj->IsNumber(), 2190 "v8::Number::Cast()", 2191 "Could not convert to number"); 2192 } 2193 2194 2195 void v8::Integer::CheckCast(v8::Value* that) { 2196 if (IsDeadCheck(i::Isolate::Current(), "v8::Integer::Cast()")) return; 2197 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2198 ApiCheck(obj->IsNumber(), 2199 "v8::Integer::Cast()", 2200 "Could not convert to number"); 2201 } 2202 2203 2204 void v8::Array::CheckCast(Value* that) { 2205 if (IsDeadCheck(i::Isolate::Current(), "v8::Array::Cast()")) return; 2206 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2207 ApiCheck(obj->IsJSArray(), 2208 "v8::Array::Cast()", 2209 "Could not convert to array"); 2210 } 2211 2212 2213 void v8::Date::CheckCast(v8::Value* that) { 2214 i::Isolate* isolate = i::Isolate::Current(); 2215 if (IsDeadCheck(isolate, "v8::Date::Cast()")) return; 2216 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2217 ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Date_symbol()), 2218 "v8::Date::Cast()", 2219 "Could not convert to date"); 2220 } 2221 2222 2223 void v8::RegExp::CheckCast(v8::Value* that) { 2224 if (IsDeadCheck(i::Isolate::Current(), "v8::RegExp::Cast()")) return; 2225 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2226 ApiCheck(obj->IsJSRegExp(), 2227 "v8::RegExp::Cast()", 2228 "Could not convert to regular expression"); 2229 } 2230 2231 2232 bool Value::BooleanValue() const { 2233 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2234 if (obj->IsBoolean()) { 2235 return obj->IsTrue(); 2236 } else { 2237 i::Isolate* isolate = i::Isolate::Current(); 2238 if (IsDeadCheck(isolate, "v8::Value::BooleanValue()")) return false; 2239 LOG_API(isolate, "BooleanValue"); 2240 ENTER_V8(isolate); 2241 i::Handle<i::Object> value = i::Execution::ToBoolean(obj); 2242 return value->IsTrue(); 2243 } 2244 } 2245 2246 2247 double Value::NumberValue() const { 2248 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2249 i::Handle<i::Object> num; 2250 if (obj->IsNumber()) { 2251 num = obj; 2252 } else { 2253 i::Isolate* isolate = i::Isolate::Current(); 2254 if (IsDeadCheck(isolate, "v8::Value::NumberValue()")) { 2255 return i::OS::nan_value(); 2256 } 2257 LOG_API(isolate, "NumberValue"); 2258 ENTER_V8(isolate); 2259 EXCEPTION_PREAMBLE(isolate); 2260 num = i::Execution::ToNumber(obj, &has_pending_exception); 2261 EXCEPTION_BAILOUT_CHECK(isolate, i::OS::nan_value()); 2262 } 2263 return num->Number(); 2264 } 2265 2266 2267 int64_t Value::IntegerValue() const { 2268 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2269 i::Handle<i::Object> num; 2270 if (obj->IsNumber()) { 2271 num = obj; 2272 } else { 2273 i::Isolate* isolate = i::Isolate::Current(); 2274 if (IsDeadCheck(isolate, "v8::Value::IntegerValue()")) return 0; 2275 LOG_API(isolate, "IntegerValue"); 2276 ENTER_V8(isolate); 2277 EXCEPTION_PREAMBLE(isolate); 2278 num = i::Execution::ToInteger(obj, &has_pending_exception); 2279 EXCEPTION_BAILOUT_CHECK(isolate, 0); 2280 } 2281 if (num->IsSmi()) { 2282 return i::Smi::cast(*num)->value(); 2283 } else { 2284 return static_cast<int64_t>(num->Number()); 2285 } 2286 } 2287 2288 2289 Local<Int32> Value::ToInt32() const { 2290 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2291 i::Handle<i::Object> num; 2292 if (obj->IsSmi()) { 2293 num = obj; 2294 } else { 2295 i::Isolate* isolate = i::Isolate::Current(); 2296 if (IsDeadCheck(isolate, "v8::Value::ToInt32()")) return Local<Int32>(); 2297 LOG_API(isolate, "ToInt32"); 2298 ENTER_V8(isolate); 2299 EXCEPTION_PREAMBLE(isolate); 2300 num = i::Execution::ToInt32(obj, &has_pending_exception); 2301 EXCEPTION_BAILOUT_CHECK(isolate, Local<Int32>()); 2302 } 2303 return Local<Int32>(ToApi<Int32>(num)); 2304 } 2305 2306 2307 Local<Uint32> Value::ToUint32() const { 2308 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2309 i::Handle<i::Object> num; 2310 if (obj->IsSmi()) { 2311 num = obj; 2312 } else { 2313 i::Isolate* isolate = i::Isolate::Current(); 2314 if (IsDeadCheck(isolate, "v8::Value::ToUint32()")) return Local<Uint32>(); 2315 LOG_API(isolate, "ToUInt32"); 2316 ENTER_V8(isolate); 2317 EXCEPTION_PREAMBLE(isolate); 2318 num = i::Execution::ToUint32(obj, &has_pending_exception); 2319 EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>()); 2320 } 2321 return Local<Uint32>(ToApi<Uint32>(num)); 2322 } 2323 2324 2325 Local<Uint32> Value::ToArrayIndex() const { 2326 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2327 if (obj->IsSmi()) { 2328 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj); 2329 return Local<Uint32>(); 2330 } 2331 i::Isolate* isolate = i::Isolate::Current(); 2332 if (IsDeadCheck(isolate, "v8::Value::ToArrayIndex()")) return Local<Uint32>(); 2333 LOG_API(isolate, "ToArrayIndex"); 2334 ENTER_V8(isolate); 2335 EXCEPTION_PREAMBLE(isolate); 2336 i::Handle<i::Object> string_obj = 2337 i::Execution::ToString(obj, &has_pending_exception); 2338 EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>()); 2339 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj); 2340 uint32_t index; 2341 if (str->AsArrayIndex(&index)) { 2342 i::Handle<i::Object> value; 2343 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) { 2344 value = i::Handle<i::Object>(i::Smi::FromInt(index)); 2345 } else { 2346 value = isolate->factory()->NewNumber(index); 2347 } 2348 return Utils::Uint32ToLocal(value); 2349 } 2350 return Local<Uint32>(); 2351 } 2352 2353 2354 int32_t Value::Int32Value() const { 2355 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2356 if (obj->IsSmi()) { 2357 return i::Smi::cast(*obj)->value(); 2358 } else { 2359 i::Isolate* isolate = i::Isolate::Current(); 2360 if (IsDeadCheck(isolate, "v8::Value::Int32Value()")) return 0; 2361 LOG_API(isolate, "Int32Value (slow)"); 2362 ENTER_V8(isolate); 2363 EXCEPTION_PREAMBLE(isolate); 2364 i::Handle<i::Object> num = 2365 i::Execution::ToInt32(obj, &has_pending_exception); 2366 EXCEPTION_BAILOUT_CHECK(isolate, 0); 2367 if (num->IsSmi()) { 2368 return i::Smi::cast(*num)->value(); 2369 } else { 2370 return static_cast<int32_t>(num->Number()); 2371 } 2372 } 2373 } 2374 2375 2376 bool Value::Equals(Handle<Value> that) const { 2377 i::Isolate* isolate = i::Isolate::Current(); 2378 if (IsDeadCheck(isolate, "v8::Value::Equals()") 2379 || EmptyCheck("v8::Value::Equals()", this) 2380 || EmptyCheck("v8::Value::Equals()", that)) { 2381 return false; 2382 } 2383 LOG_API(isolate, "Equals"); 2384 ENTER_V8(isolate); 2385 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2386 i::Handle<i::Object> other = Utils::OpenHandle(*that); 2387 // If both obj and other are JSObjects, we'd better compare by identity 2388 // immediately when going into JS builtin. The reason is Invoke 2389 // would overwrite global object receiver with global proxy. 2390 if (obj->IsJSObject() && other->IsJSObject()) { 2391 return *obj == *other; 2392 } 2393 i::Object** args[1] = { other.location() }; 2394 EXCEPTION_PREAMBLE(isolate); 2395 i::Handle<i::Object> result = 2396 CallV8HeapFunction("EQUALS", obj, 1, args, &has_pending_exception); 2397 EXCEPTION_BAILOUT_CHECK(isolate, false); 2398 return *result == i::Smi::FromInt(i::EQUAL); 2399 } 2400 2401 2402 bool Value::StrictEquals(Handle<Value> that) const { 2403 i::Isolate* isolate = i::Isolate::Current(); 2404 if (IsDeadCheck(isolate, "v8::Value::StrictEquals()") 2405 || EmptyCheck("v8::Value::StrictEquals()", this) 2406 || EmptyCheck("v8::Value::StrictEquals()", that)) { 2407 return false; 2408 } 2409 LOG_API(isolate, "StrictEquals"); 2410 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2411 i::Handle<i::Object> other = Utils::OpenHandle(*that); 2412 // Must check HeapNumber first, since NaN !== NaN. 2413 if (obj->IsHeapNumber()) { 2414 if (!other->IsNumber()) return false; 2415 double x = obj->Number(); 2416 double y = other->Number(); 2417 // Must check explicitly for NaN:s on Windows, but -0 works fine. 2418 return x == y && !isnan(x) && !isnan(y); 2419 } else if (*obj == *other) { // Also covers Booleans. 2420 return true; 2421 } else if (obj->IsSmi()) { 2422 return other->IsNumber() && obj->Number() == other->Number(); 2423 } else if (obj->IsString()) { 2424 return other->IsString() && 2425 i::String::cast(*obj)->Equals(i::String::cast(*other)); 2426 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) { 2427 return other->IsUndefined() || other->IsUndetectableObject(); 2428 } else { 2429 return false; 2430 } 2431 } 2432 2433 2434 uint32_t Value::Uint32Value() const { 2435 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2436 if (obj->IsSmi()) { 2437 return i::Smi::cast(*obj)->value(); 2438 } else { 2439 i::Isolate* isolate = i::Isolate::Current(); 2440 if (IsDeadCheck(isolate, "v8::Value::Uint32Value()")) return 0; 2441 LOG_API(isolate, "Uint32Value"); 2442 ENTER_V8(isolate); 2443 EXCEPTION_PREAMBLE(isolate); 2444 i::Handle<i::Object> num = 2445 i::Execution::ToUint32(obj, &has_pending_exception); 2446 EXCEPTION_BAILOUT_CHECK(isolate, 0); 2447 if (num->IsSmi()) { 2448 return i::Smi::cast(*num)->value(); 2449 } else { 2450 return static_cast<uint32_t>(num->Number()); 2451 } 2452 } 2453 } 2454 2455 2456 bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value, 2457 v8::PropertyAttribute attribs) { 2458 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2459 ON_BAILOUT(isolate, "v8::Object::Set()", return false); 2460 ENTER_V8(isolate); 2461 i::HandleScope scope(isolate); 2462 i::Handle<i::Object> self = Utils::OpenHandle(this); 2463 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 2464 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 2465 EXCEPTION_PREAMBLE(isolate); 2466 i::Handle<i::Object> obj = i::SetProperty( 2467 self, 2468 key_obj, 2469 value_obj, 2470 static_cast<PropertyAttributes>(attribs), 2471 i::kNonStrictMode); 2472 has_pending_exception = obj.is_null(); 2473 EXCEPTION_BAILOUT_CHECK(isolate, false); 2474 return true; 2475 } 2476 2477 2478 bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) { 2479 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2480 ON_BAILOUT(isolate, "v8::Object::Set()", return false); 2481 ENTER_V8(isolate); 2482 i::HandleScope scope(isolate); 2483 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2484 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 2485 EXCEPTION_PREAMBLE(isolate); 2486 i::Handle<i::Object> obj = i::SetElement( 2487 self, 2488 index, 2489 value_obj, 2490 i::kNonStrictMode); 2491 has_pending_exception = obj.is_null(); 2492 EXCEPTION_BAILOUT_CHECK(isolate, false); 2493 return true; 2494 } 2495 2496 2497 bool v8::Object::ForceSet(v8::Handle<Value> key, 2498 v8::Handle<Value> value, 2499 v8::PropertyAttribute attribs) { 2500 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2501 ON_BAILOUT(isolate, "v8::Object::ForceSet()", return false); 2502 ENTER_V8(isolate); 2503 i::HandleScope scope(isolate); 2504 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2505 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 2506 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 2507 EXCEPTION_PREAMBLE(isolate); 2508 i::Handle<i::Object> obj = i::ForceSetProperty( 2509 self, 2510 key_obj, 2511 value_obj, 2512 static_cast<PropertyAttributes>(attribs)); 2513 has_pending_exception = obj.is_null(); 2514 EXCEPTION_BAILOUT_CHECK(isolate, false); 2515 return true; 2516 } 2517 2518 2519 bool v8::Object::ForceDelete(v8::Handle<Value> key) { 2520 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2521 ON_BAILOUT(isolate, "v8::Object::ForceDelete()", return false); 2522 ENTER_V8(isolate); 2523 i::HandleScope scope(isolate); 2524 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2525 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 2526 2527 // When turning on access checks for a global object deoptimize all functions 2528 // as optimized code does not always handle access checks. 2529 i::Deoptimizer::DeoptimizeGlobalObject(*self); 2530 2531 EXCEPTION_PREAMBLE(isolate); 2532 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj); 2533 has_pending_exception = obj.is_null(); 2534 EXCEPTION_BAILOUT_CHECK(isolate, false); 2535 return obj->IsTrue(); 2536 } 2537 2538 2539 Local<Value> v8::Object::Get(v8::Handle<Value> key) { 2540 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2541 ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>()); 2542 ENTER_V8(isolate); 2543 i::Handle<i::Object> self = Utils::OpenHandle(this); 2544 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 2545 EXCEPTION_PREAMBLE(isolate); 2546 i::Handle<i::Object> result = i::GetProperty(self, key_obj); 2547 has_pending_exception = result.is_null(); 2548 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 2549 return Utils::ToLocal(result); 2550 } 2551 2552 2553 Local<Value> v8::Object::Get(uint32_t index) { 2554 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2555 ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>()); 2556 ENTER_V8(isolate); 2557 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2558 EXCEPTION_PREAMBLE(isolate); 2559 i::Handle<i::Object> result = i::GetElement(self, index); 2560 has_pending_exception = result.is_null(); 2561 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 2562 return Utils::ToLocal(result); 2563 } 2564 2565 2566 Local<Value> v8::Object::GetPrototype() { 2567 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2568 ON_BAILOUT(isolate, "v8::Object::GetPrototype()", 2569 return Local<v8::Value>()); 2570 ENTER_V8(isolate); 2571 i::Handle<i::Object> self = Utils::OpenHandle(this); 2572 i::Handle<i::Object> result = i::GetPrototype(self); 2573 return Utils::ToLocal(result); 2574 } 2575 2576 2577 bool v8::Object::SetPrototype(Handle<Value> value) { 2578 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2579 ON_BAILOUT(isolate, "v8::Object::SetPrototype()", return false); 2580 ENTER_V8(isolate); 2581 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2582 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 2583 // We do not allow exceptions thrown while setting the prototype 2584 // to propagate outside. 2585 TryCatch try_catch; 2586 EXCEPTION_PREAMBLE(isolate); 2587 i::Handle<i::Object> result = i::SetPrototype(self, value_obj); 2588 has_pending_exception = result.is_null(); 2589 EXCEPTION_BAILOUT_CHECK(isolate, false); 2590 return true; 2591 } 2592 2593 2594 Local<Object> v8::Object::FindInstanceInPrototypeChain( 2595 v8::Handle<FunctionTemplate> tmpl) { 2596 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2597 ON_BAILOUT(isolate, 2598 "v8::Object::FindInstanceInPrototypeChain()", 2599 return Local<v8::Object>()); 2600 ENTER_V8(isolate); 2601 i::JSObject* object = *Utils::OpenHandle(this); 2602 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl); 2603 while (!object->IsInstanceOf(tmpl_info)) { 2604 i::Object* prototype = object->GetPrototype(); 2605 if (!prototype->IsJSObject()) return Local<Object>(); 2606 object = i::JSObject::cast(prototype); 2607 } 2608 return Utils::ToLocal(i::Handle<i::JSObject>(object)); 2609 } 2610 2611 2612 Local<Array> v8::Object::GetPropertyNames() { 2613 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2614 ON_BAILOUT(isolate, "v8::Object::GetPropertyNames()", 2615 return Local<v8::Array>()); 2616 ENTER_V8(isolate); 2617 i::HandleScope scope(isolate); 2618 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2619 i::Handle<i::FixedArray> value = 2620 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS); 2621 // Because we use caching to speed up enumeration it is important 2622 // to never change the result of the basic enumeration function so 2623 // we clone the result. 2624 i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value); 2625 i::Handle<i::JSArray> result = 2626 isolate->factory()->NewJSArrayWithElements(elms); 2627 return Utils::ToLocal(scope.CloseAndEscape(result)); 2628 } 2629 2630 2631 Local<String> v8::Object::ObjectProtoToString() { 2632 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2633 ON_BAILOUT(isolate, "v8::Object::ObjectProtoToString()", 2634 return Local<v8::String>()); 2635 ENTER_V8(isolate); 2636 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2637 2638 i::Handle<i::Object> name(self->class_name()); 2639 2640 // Native implementation of Object.prototype.toString (v8natives.js): 2641 // var c = %ClassOf(this); 2642 // if (c === 'Arguments') c = 'Object'; 2643 // return "[object " + c + "]"; 2644 2645 if (!name->IsString()) { 2646 return v8::String::New("[object ]"); 2647 2648 } else { 2649 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name); 2650 if (class_name->IsEqualTo(i::CStrVector("Arguments"))) { 2651 return v8::String::New("[object Object]"); 2652 2653 } else { 2654 const char* prefix = "[object "; 2655 Local<String> str = Utils::ToLocal(class_name); 2656 const char* postfix = "]"; 2657 2658 int prefix_len = i::StrLength(prefix); 2659 int str_len = str->Length(); 2660 int postfix_len = i::StrLength(postfix); 2661 2662 int buf_len = prefix_len + str_len + postfix_len; 2663 i::ScopedVector<char> buf(buf_len); 2664 2665 // Write prefix. 2666 char* ptr = buf.start(); 2667 memcpy(ptr, prefix, prefix_len * v8::internal::kCharSize); 2668 ptr += prefix_len; 2669 2670 // Write real content. 2671 str->WriteAscii(ptr, 0, str_len); 2672 ptr += str_len; 2673 2674 // Write postfix. 2675 memcpy(ptr, postfix, postfix_len * v8::internal::kCharSize); 2676 2677 // Copy the buffer into a heap-allocated string and return it. 2678 Local<String> result = v8::String::New(buf.start(), buf_len); 2679 return result; 2680 } 2681 } 2682 } 2683 2684 2685 Local<String> v8::Object::GetConstructorName() { 2686 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2687 ON_BAILOUT(isolate, "v8::Object::GetConstructorName()", 2688 return Local<v8::String>()); 2689 ENTER_V8(isolate); 2690 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2691 i::Handle<i::String> name(self->constructor_name()); 2692 return Utils::ToLocal(name); 2693 } 2694 2695 2696 bool v8::Object::Delete(v8::Handle<String> key) { 2697 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2698 ON_BAILOUT(isolate, "v8::Object::Delete()", return false); 2699 ENTER_V8(isolate); 2700 i::HandleScope scope(isolate); 2701 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2702 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 2703 return i::DeleteProperty(self, key_obj)->IsTrue(); 2704 } 2705 2706 2707 bool v8::Object::Has(v8::Handle<String> key) { 2708 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2709 ON_BAILOUT(isolate, "v8::Object::Has()", return false); 2710 ENTER_V8(isolate); 2711 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2712 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 2713 return self->HasProperty(*key_obj); 2714 } 2715 2716 2717 bool v8::Object::Delete(uint32_t index) { 2718 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2719 ON_BAILOUT(isolate, "v8::Object::DeleteProperty()", 2720 return false); 2721 ENTER_V8(isolate); 2722 HandleScope scope; 2723 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2724 return i::DeleteElement(self, index)->IsTrue(); 2725 } 2726 2727 2728 bool v8::Object::Has(uint32_t index) { 2729 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2730 ON_BAILOUT(isolate, "v8::Object::HasProperty()", return false); 2731 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2732 return self->HasElement(index); 2733 } 2734 2735 2736 bool Object::SetAccessor(Handle<String> name, 2737 AccessorGetter getter, 2738 AccessorSetter setter, 2739 v8::Handle<Value> data, 2740 AccessControl settings, 2741 PropertyAttribute attributes) { 2742 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2743 ON_BAILOUT(isolate, "v8::Object::SetAccessor()", return false); 2744 ENTER_V8(isolate); 2745 i::HandleScope scope(isolate); 2746 i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name, 2747 getter, setter, data, 2748 settings, attributes); 2749 i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info); 2750 return !result.is_null() && !result->IsUndefined(); 2751 } 2752 2753 2754 bool v8::Object::HasRealNamedProperty(Handle<String> key) { 2755 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2756 ON_BAILOUT(isolate, "v8::Object::HasRealNamedProperty()", 2757 return false); 2758 return Utils::OpenHandle(this)->HasRealNamedProperty( 2759 *Utils::OpenHandle(*key)); 2760 } 2761 2762 2763 bool v8::Object::HasRealIndexedProperty(uint32_t index) { 2764 ON_BAILOUT(Utils::OpenHandle(this)->GetIsolate(), 2765 "v8::Object::HasRealIndexedProperty()", 2766 return false); 2767 return Utils::OpenHandle(this)->HasRealElementProperty(index); 2768 } 2769 2770 2771 bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) { 2772 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2773 ON_BAILOUT(isolate, 2774 "v8::Object::HasRealNamedCallbackProperty()", 2775 return false); 2776 ENTER_V8(isolate); 2777 return Utils::OpenHandle(this)->HasRealNamedCallbackProperty( 2778 *Utils::OpenHandle(*key)); 2779 } 2780 2781 2782 bool v8::Object::HasNamedLookupInterceptor() { 2783 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2784 ON_BAILOUT(isolate, "v8::Object::HasNamedLookupInterceptor()", 2785 return false); 2786 return Utils::OpenHandle(this)->HasNamedInterceptor(); 2787 } 2788 2789 2790 bool v8::Object::HasIndexedLookupInterceptor() { 2791 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2792 ON_BAILOUT(isolate, "v8::Object::HasIndexedLookupInterceptor()", 2793 return false); 2794 return Utils::OpenHandle(this)->HasIndexedInterceptor(); 2795 } 2796 2797 2798 static Local<Value> GetPropertyByLookup(i::Isolate* isolate, 2799 i::Handle<i::JSObject> receiver, 2800 i::Handle<i::String> name, 2801 i::LookupResult* lookup) { 2802 if (!lookup->IsProperty()) { 2803 // No real property was found. 2804 return Local<Value>(); 2805 } 2806 2807 // If the property being looked up is a callback, it can throw 2808 // an exception. 2809 EXCEPTION_PREAMBLE(isolate); 2810 i::Handle<i::Object> result = i::GetProperty(receiver, name, lookup); 2811 has_pending_exception = result.is_null(); 2812 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 2813 2814 return Utils::ToLocal(result); 2815 } 2816 2817 2818 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain( 2819 Handle<String> key) { 2820 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2821 ON_BAILOUT(isolate, 2822 "v8::Object::GetRealNamedPropertyInPrototypeChain()", 2823 return Local<Value>()); 2824 ENTER_V8(isolate); 2825 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this); 2826 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 2827 i::LookupResult lookup; 2828 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup); 2829 return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup); 2830 } 2831 2832 2833 Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) { 2834 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2835 ON_BAILOUT(isolate, "v8::Object::GetRealNamedProperty()", 2836 return Local<Value>()); 2837 ENTER_V8(isolate); 2838 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this); 2839 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 2840 i::LookupResult lookup; 2841 self_obj->LookupRealNamedProperty(*key_obj, &lookup); 2842 return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup); 2843 } 2844 2845 2846 // Turns on access checks by copying the map and setting the check flag. 2847 // Because the object gets a new map, existing inline cache caching 2848 // the old map of this object will fail. 2849 void v8::Object::TurnOnAccessCheck() { 2850 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2851 ON_BAILOUT(isolate, "v8::Object::TurnOnAccessCheck()", return); 2852 ENTER_V8(isolate); 2853 i::HandleScope scope(isolate); 2854 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 2855 2856 // When turning on access checks for a global object deoptimize all functions 2857 // as optimized code does not always handle access checks. 2858 i::Deoptimizer::DeoptimizeGlobalObject(*obj); 2859 2860 i::Handle<i::Map> new_map = 2861 isolate->factory()->CopyMapDropTransitions(i::Handle<i::Map>(obj->map())); 2862 new_map->set_is_access_check_needed(true); 2863 obj->set_map(*new_map); 2864 } 2865 2866 2867 bool v8::Object::IsDirty() { 2868 return Utils::OpenHandle(this)->IsDirty(); 2869 } 2870 2871 2872 Local<v8::Object> v8::Object::Clone() { 2873 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2874 ON_BAILOUT(isolate, "v8::Object::Clone()", return Local<Object>()); 2875 ENTER_V8(isolate); 2876 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2877 EXCEPTION_PREAMBLE(isolate); 2878 i::Handle<i::JSObject> result = i::Copy(self); 2879 has_pending_exception = result.is_null(); 2880 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>()); 2881 return Utils::ToLocal(result); 2882 } 2883 2884 2885 static i::Context* GetCreationContext(i::JSObject* object) { 2886 i::Object* constructor = object->map()->constructor(); 2887 i::JSFunction* function; 2888 if (!constructor->IsJSFunction()) { 2889 // API functions have null as a constructor, 2890 // but any JSFunction knows its context immediately. 2891 ASSERT(object->IsJSFunction() && 2892 i::JSFunction::cast(object)->shared()->IsApiFunction()); 2893 function = i::JSFunction::cast(object); 2894 } else { 2895 function = i::JSFunction::cast(constructor); 2896 } 2897 return function->context()->global_context(); 2898 } 2899 2900 2901 Local<v8::Context> v8::Object::CreationContext() { 2902 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2903 ON_BAILOUT(isolate, 2904 "v8::Object::CreationContext()", return Local<v8::Context>()); 2905 ENTER_V8(isolate); 2906 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2907 i::Context* context = GetCreationContext(*self); 2908 return Utils::ToLocal(i::Handle<i::Context>(context)); 2909 } 2910 2911 2912 int v8::Object::GetIdentityHash() { 2913 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2914 ON_BAILOUT(isolate, "v8::Object::GetIdentityHash()", return 0); 2915 ENTER_V8(isolate); 2916 i::HandleScope scope(isolate); 2917 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2918 i::Handle<i::Object> hidden_props_obj(i::GetHiddenProperties(self, true)); 2919 if (!hidden_props_obj->IsJSObject()) { 2920 // We failed to create hidden properties. That's a detached 2921 // global proxy. 2922 ASSERT(hidden_props_obj->IsUndefined()); 2923 return 0; 2924 } 2925 i::Handle<i::JSObject> hidden_props = 2926 i::Handle<i::JSObject>::cast(hidden_props_obj); 2927 i::Handle<i::String> hash_symbol = isolate->factory()->identity_hash_symbol(); 2928 if (hidden_props->HasLocalProperty(*hash_symbol)) { 2929 i::Handle<i::Object> hash = i::GetProperty(hidden_props, hash_symbol); 2930 CHECK(!hash.is_null()); 2931 CHECK(hash->IsSmi()); 2932 return i::Smi::cast(*hash)->value(); 2933 } 2934 2935 int hash_value; 2936 int attempts = 0; 2937 do { 2938 // Generate a random 32-bit hash value but limit range to fit 2939 // within a smi. 2940 hash_value = i::V8::Random(self->GetIsolate()) & i::Smi::kMaxValue; 2941 attempts++; 2942 } while (hash_value == 0 && attempts < 30); 2943 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 2944 CHECK(!i::SetLocalPropertyIgnoreAttributes( 2945 hidden_props, 2946 hash_symbol, 2947 i::Handle<i::Object>(i::Smi::FromInt(hash_value)), 2948 static_cast<PropertyAttributes>(None)).is_null()); 2949 2950 return hash_value; 2951 } 2952 2953 2954 bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key, 2955 v8::Handle<v8::Value> value) { 2956 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2957 ON_BAILOUT(isolate, "v8::Object::SetHiddenValue()", return false); 2958 ENTER_V8(isolate); 2959 i::HandleScope scope(isolate); 2960 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2961 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, true)); 2962 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 2963 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 2964 EXCEPTION_PREAMBLE(isolate); 2965 i::Handle<i::Object> obj = i::SetProperty( 2966 hidden_props, 2967 key_obj, 2968 value_obj, 2969 static_cast<PropertyAttributes>(None), 2970 i::kNonStrictMode); 2971 has_pending_exception = obj.is_null(); 2972 EXCEPTION_BAILOUT_CHECK(isolate, false); 2973 return true; 2974 } 2975 2976 2977 v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) { 2978 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2979 ON_BAILOUT(isolate, "v8::Object::GetHiddenValue()", 2980 return Local<v8::Value>()); 2981 ENTER_V8(isolate); 2982 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2983 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false)); 2984 if (hidden_props->IsUndefined()) { 2985 return v8::Local<v8::Value>(); 2986 } 2987 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 2988 EXCEPTION_PREAMBLE(isolate); 2989 i::Handle<i::Object> result = i::GetProperty(hidden_props, key_obj); 2990 has_pending_exception = result.is_null(); 2991 EXCEPTION_BAILOUT_CHECK(isolate, v8::Local<v8::Value>()); 2992 if (result->IsUndefined()) { 2993 return v8::Local<v8::Value>(); 2994 } 2995 return Utils::ToLocal(result); 2996 } 2997 2998 2999 bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) { 3000 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3001 ON_BAILOUT(isolate, "v8::DeleteHiddenValue()", return false); 3002 ENTER_V8(isolate); 3003 i::HandleScope scope(isolate); 3004 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3005 i::Handle<i::Object> hidden_props(i::GetHiddenProperties(self, false)); 3006 if (hidden_props->IsUndefined()) { 3007 return true; 3008 } 3009 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*hidden_props)); 3010 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 3011 return i::DeleteProperty(js_obj, key_obj)->IsTrue(); 3012 } 3013 3014 3015 namespace { 3016 3017 void PrepareExternalArrayElements(i::Handle<i::JSObject> object, 3018 void* data, 3019 ExternalArrayType array_type, 3020 int length) { 3021 i::Isolate* isolate = object->GetIsolate(); 3022 i::Handle<i::ExternalArray> array = 3023 isolate->factory()->NewExternalArray(length, array_type, data); 3024 3025 // If the object already has external elements, create a new, unique 3026 // map if the element type is now changing, because assumptions about 3027 // generated code based on the receiver's map will be invalid. 3028 i::Handle<i::HeapObject> elements(object->elements()); 3029 bool cant_reuse_map = 3030 elements->map()->IsUndefined() || 3031 !elements->map()->has_external_array_elements() || 3032 elements->map() != isolate->heap()->MapForExternalArrayType(array_type); 3033 if (cant_reuse_map) { 3034 i::Handle<i::Map> external_array_map = 3035 isolate->factory()->GetExternalArrayElementsMap( 3036 i::Handle<i::Map>(object->map()), 3037 array_type, 3038 object->HasFastProperties()); 3039 object->set_map(*external_array_map); 3040 } 3041 object->set_elements(*array); 3042 } 3043 3044 } // namespace 3045 3046 3047 void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) { 3048 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3049 ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return); 3050 ENTER_V8(isolate); 3051 i::HandleScope scope(isolate); 3052 if (!ApiCheck(length <= i::ExternalPixelArray::kMaxLength, 3053 "v8::Object::SetIndexedPropertiesToPixelData()", 3054 "length exceeds max acceptable value")) { 3055 return; 3056 } 3057 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3058 if (!ApiCheck(!self->IsJSArray(), 3059 "v8::Object::SetIndexedPropertiesToPixelData()", 3060 "JSArray is not supported")) { 3061 return; 3062 } 3063 PrepareExternalArrayElements(self, data, kExternalPixelArray, length); 3064 } 3065 3066 3067 bool v8::Object::HasIndexedPropertiesInPixelData() { 3068 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3069 ON_BAILOUT(self->GetIsolate(), "v8::HasIndexedPropertiesInPixelData()", 3070 return false); 3071 return self->HasExternalPixelElements(); 3072 } 3073 3074 3075 uint8_t* v8::Object::GetIndexedPropertiesPixelData() { 3076 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3077 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelData()", 3078 return NULL); 3079 if (self->HasExternalPixelElements()) { 3080 return i::ExternalPixelArray::cast(self->elements())-> 3081 external_pixel_pointer(); 3082 } else { 3083 return NULL; 3084 } 3085 } 3086 3087 3088 int v8::Object::GetIndexedPropertiesPixelDataLength() { 3089 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3090 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelDataLength()", 3091 return -1); 3092 if (self->HasExternalPixelElements()) { 3093 return i::ExternalPixelArray::cast(self->elements())->length(); 3094 } else { 3095 return -1; 3096 } 3097 } 3098 3099 void v8::Object::SetIndexedPropertiesToExternalArrayData( 3100 void* data, 3101 ExternalArrayType array_type, 3102 int length) { 3103 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3104 ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return); 3105 ENTER_V8(isolate); 3106 i::HandleScope scope(isolate); 3107 if (!ApiCheck(length <= i::ExternalArray::kMaxLength, 3108 "v8::Object::SetIndexedPropertiesToExternalArrayData()", 3109 "length exceeds max acceptable value")) { 3110 return; 3111 } 3112 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3113 if (!ApiCheck(!self->IsJSArray(), 3114 "v8::Object::SetIndexedPropertiesToExternalArrayData()", 3115 "JSArray is not supported")) { 3116 return; 3117 } 3118 PrepareExternalArrayElements(self, data, array_type, length); 3119 } 3120 3121 3122 bool v8::Object::HasIndexedPropertiesInExternalArrayData() { 3123 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3124 ON_BAILOUT(self->GetIsolate(), 3125 "v8::HasIndexedPropertiesInExternalArrayData()", 3126 return false); 3127 return self->HasExternalArrayElements(); 3128 } 3129 3130 3131 void* v8::Object::GetIndexedPropertiesExternalArrayData() { 3132 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3133 ON_BAILOUT(self->GetIsolate(), 3134 "v8::GetIndexedPropertiesExternalArrayData()", 3135 return NULL); 3136 if (self->HasExternalArrayElements()) { 3137 return i::ExternalArray::cast(self->elements())->external_pointer(); 3138 } else { 3139 return NULL; 3140 } 3141 } 3142 3143 3144 ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() { 3145 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3146 ON_BAILOUT(self->GetIsolate(), 3147 "v8::GetIndexedPropertiesExternalArrayDataType()", 3148 return static_cast<ExternalArrayType>(-1)); 3149 switch (self->elements()->map()->instance_type()) { 3150 case i::EXTERNAL_BYTE_ARRAY_TYPE: 3151 return kExternalByteArray; 3152 case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: 3153 return kExternalUnsignedByteArray; 3154 case i::EXTERNAL_SHORT_ARRAY_TYPE: 3155 return kExternalShortArray; 3156 case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: 3157 return kExternalUnsignedShortArray; 3158 case i::EXTERNAL_INT_ARRAY_TYPE: 3159 return kExternalIntArray; 3160 case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: 3161 return kExternalUnsignedIntArray; 3162 case i::EXTERNAL_FLOAT_ARRAY_TYPE: 3163 return kExternalFloatArray; 3164 case i::EXTERNAL_PIXEL_ARRAY_TYPE: 3165 return kExternalPixelArray; 3166 default: 3167 return static_cast<ExternalArrayType>(-1); 3168 } 3169 } 3170 3171 3172 int v8::Object::GetIndexedPropertiesExternalArrayDataLength() { 3173 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3174 ON_BAILOUT(self->GetIsolate(), 3175 "v8::GetIndexedPropertiesExternalArrayDataLength()", 3176 return 0); 3177 if (self->HasExternalArrayElements()) { 3178 return i::ExternalArray::cast(self->elements())->length(); 3179 } else { 3180 return -1; 3181 } 3182 } 3183 3184 3185 Local<v8::Object> Function::NewInstance() const { 3186 return NewInstance(0, NULL); 3187 } 3188 3189 3190 Local<v8::Object> Function::NewInstance(int argc, 3191 v8::Handle<v8::Value> argv[]) const { 3192 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3193 ON_BAILOUT(isolate, "v8::Function::NewInstance()", 3194 return Local<v8::Object>()); 3195 LOG_API(isolate, "Function::NewInstance"); 3196 ENTER_V8(isolate); 3197 HandleScope scope; 3198 i::Handle<i::JSFunction> function = Utils::OpenHandle(this); 3199 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); 3200 i::Object*** args = reinterpret_cast<i::Object***>(argv); 3201 EXCEPTION_PREAMBLE(isolate); 3202 i::Handle<i::Object> returned = 3203 i::Execution::New(function, argc, args, &has_pending_exception); 3204 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); 3205 return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned))); 3206 } 3207 3208 3209 Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc, 3210 v8::Handle<v8::Value> argv[]) { 3211 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3212 ON_BAILOUT(isolate, "v8::Function::Call()", return Local<v8::Value>()); 3213 LOG_API(isolate, "Function::Call"); 3214 ENTER_V8(isolate); 3215 i::Object* raw_result = NULL; 3216 { 3217 i::HandleScope scope(isolate); 3218 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this); 3219 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv); 3220 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); 3221 i::Object*** args = reinterpret_cast<i::Object***>(argv); 3222 EXCEPTION_PREAMBLE(isolate); 3223 i::Handle<i::Object> returned = 3224 i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception); 3225 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>()); 3226 raw_result = *returned; 3227 } 3228 i::Handle<i::Object> result(raw_result); 3229 return Utils::ToLocal(result); 3230 } 3231 3232 3233 void Function::SetName(v8::Handle<v8::String> name) { 3234 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3235 ENTER_V8(isolate); 3236 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 3237 func->shared()->set_name(*Utils::OpenHandle(*name)); 3238 } 3239 3240 3241 Handle<Value> Function::GetName() const { 3242 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 3243 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name())); 3244 } 3245 3246 3247 ScriptOrigin Function::GetScriptOrigin() const { 3248 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 3249 if (func->shared()->script()->IsScript()) { 3250 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 3251 v8::ScriptOrigin origin( 3252 Utils::ToLocal(i::Handle<i::Object>(script->name())), 3253 v8::Integer::New(script->line_offset()->value()), 3254 v8::Integer::New(script->column_offset()->value())); 3255 return origin; 3256 } 3257 return v8::ScriptOrigin(Handle<Value>()); 3258 } 3259 3260 3261 const int Function::kLineOffsetNotFound = -1; 3262 3263 3264 int Function::GetScriptLineNumber() const { 3265 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 3266 if (func->shared()->script()->IsScript()) { 3267 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 3268 return i::GetScriptLineNumber(script, func->shared()->start_position()); 3269 } 3270 return kLineOffsetNotFound; 3271 } 3272 3273 3274 int String::Length() const { 3275 i::Handle<i::String> str = Utils::OpenHandle(this); 3276 if (IsDeadCheck(str->GetIsolate(), "v8::String::Length()")) return 0; 3277 return str->length(); 3278 } 3279 3280 3281 int String::Utf8Length() const { 3282 i::Handle<i::String> str = Utils::OpenHandle(this); 3283 if (IsDeadCheck(str->GetIsolate(), "v8::String::Utf8Length()")) return 0; 3284 return str->Utf8Length(); 3285 } 3286 3287 3288 int String::WriteUtf8(char* buffer, 3289 int capacity, 3290 int* nchars_ref, 3291 WriteHints hints) const { 3292 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3293 if (IsDeadCheck(isolate, "v8::String::WriteUtf8()")) return 0; 3294 LOG_API(isolate, "String::WriteUtf8"); 3295 ENTER_V8(isolate); 3296 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); 3297 i::Handle<i::String> str = Utils::OpenHandle(this); 3298 isolate->string_tracker()->RecordWrite(str); 3299 if (hints & HINT_MANY_WRITES_EXPECTED) { 3300 // Flatten the string for efficiency. This applies whether we are 3301 // using StringInputBuffer or Get(i) to access the characters. 3302 str->TryFlatten(); 3303 } 3304 write_input_buffer.Reset(0, *str); 3305 int len = str->length(); 3306 // Encode the first K - 3 bytes directly into the buffer since we 3307 // know there's room for them. If no capacity is given we copy all 3308 // of them here. 3309 int fast_end = capacity - (unibrow::Utf8::kMaxEncodedSize - 1); 3310 int i; 3311 int pos = 0; 3312 int nchars = 0; 3313 for (i = 0; i < len && (capacity == -1 || pos < fast_end); i++) { 3314 i::uc32 c = write_input_buffer.GetNext(); 3315 int written = unibrow::Utf8::Encode(buffer + pos, c); 3316 pos += written; 3317 nchars++; 3318 } 3319 if (i < len) { 3320 // For the last characters we need to check the length for each one 3321 // because they may be longer than the remaining space in the 3322 // buffer. 3323 char intermediate[unibrow::Utf8::kMaxEncodedSize]; 3324 for (; i < len && pos < capacity; i++) { 3325 i::uc32 c = write_input_buffer.GetNext(); 3326 int written = unibrow::Utf8::Encode(intermediate, c); 3327 if (pos + written <= capacity) { 3328 for (int j = 0; j < written; j++) 3329 buffer[pos + j] = intermediate[j]; 3330 pos += written; 3331 nchars++; 3332 } else { 3333 // We've reached the end of the buffer 3334 break; 3335 } 3336 } 3337 } 3338 if (nchars_ref != NULL) *nchars_ref = nchars; 3339 if (i == len && (capacity == -1 || pos < capacity)) 3340 buffer[pos++] = '\0'; 3341 return pos; 3342 } 3343 3344 3345 int String::WriteAscii(char* buffer, 3346 int start, 3347 int length, 3348 WriteHints hints) const { 3349 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3350 if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0; 3351 LOG_API(isolate, "String::WriteAscii"); 3352 ENTER_V8(isolate); 3353 i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); 3354 ASSERT(start >= 0 && length >= -1); 3355 i::Handle<i::String> str = Utils::OpenHandle(this); 3356 isolate->string_tracker()->RecordWrite(str); 3357 if (hints & HINT_MANY_WRITES_EXPECTED) { 3358 // Flatten the string for efficiency. This applies whether we are 3359 // using StringInputBuffer or Get(i) to access the characters. 3360 str->TryFlatten(); 3361 } 3362 int end = length; 3363 if ( (length == -1) || (length > str->length() - start) ) 3364 end = str->length() - start; 3365 if (end < 0) return 0; 3366 write_input_buffer.Reset(start, *str); 3367 int i; 3368 for (i = 0; i < end; i++) { 3369 char c = static_cast<char>(write_input_buffer.GetNext()); 3370 if (c == '\0') c = ' '; 3371 buffer[i] = c; 3372 } 3373 if (length == -1 || i < length) 3374 buffer[i] = '\0'; 3375 return i; 3376 } 3377 3378 3379 int String::Write(uint16_t* buffer, 3380 int start, 3381 int length, 3382 WriteHints hints) const { 3383 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3384 if (IsDeadCheck(isolate, "v8::String::Write()")) return 0; 3385 LOG_API(isolate, "String::Write"); 3386 ENTER_V8(isolate); 3387 ASSERT(start >= 0 && length >= -1); 3388 i::Handle<i::String> str = Utils::OpenHandle(this); 3389 isolate->string_tracker()->RecordWrite(str); 3390 if (hints & HINT_MANY_WRITES_EXPECTED) { 3391 // Flatten the string for efficiency. This applies whether we are 3392 // using StringInputBuffer or Get(i) to access the characters. 3393 str->TryFlatten(); 3394 } 3395 int end = start + length; 3396 if ((length == -1) || (length > str->length() - start) ) 3397 end = str->length(); 3398 if (end < 0) return 0; 3399 i::String::WriteToFlat(*str, buffer, start, end); 3400 if (length == -1 || end - start < length) { 3401 buffer[end - start] = '\0'; 3402 } 3403 return end - start; 3404 } 3405 3406 3407 bool v8::String::IsExternal() const { 3408 i::Handle<i::String> str = Utils::OpenHandle(this); 3409 if (IsDeadCheck(str->GetIsolate(), "v8::String::IsExternal()")) { 3410 return false; 3411 } 3412 EnsureInitializedForIsolate(str->GetIsolate(), "v8::String::IsExternal()"); 3413 return i::StringShape(*str).IsExternalTwoByte(); 3414 } 3415 3416 3417 bool v8::String::IsExternalAscii() const { 3418 i::Handle<i::String> str = Utils::OpenHandle(this); 3419 if (IsDeadCheck(str->GetIsolate(), "v8::String::IsExternalAscii()")) { 3420 return false; 3421 } 3422 return i::StringShape(*str).IsExternalAscii(); 3423 } 3424 3425 3426 void v8::String::VerifyExternalStringResource( 3427 v8::String::ExternalStringResource* value) const { 3428 i::Handle<i::String> str = Utils::OpenHandle(this); 3429 v8::String::ExternalStringResource* expected; 3430 if (i::StringShape(*str).IsExternalTwoByte()) { 3431 void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource(); 3432 expected = reinterpret_cast<ExternalStringResource*>(resource); 3433 } else { 3434 expected = NULL; 3435 } 3436 CHECK_EQ(expected, value); 3437 } 3438 3439 3440 v8::String::ExternalAsciiStringResource* 3441 v8::String::GetExternalAsciiStringResource() const { 3442 i::Handle<i::String> str = Utils::OpenHandle(this); 3443 if (IsDeadCheck(str->GetIsolate(), 3444 "v8::String::GetExternalAsciiStringResource()")) { 3445 return NULL; 3446 } 3447 if (i::StringShape(*str).IsExternalAscii()) { 3448 void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource(); 3449 return reinterpret_cast<ExternalAsciiStringResource*>(resource); 3450 } else { 3451 return NULL; 3452 } 3453 } 3454 3455 3456 double Number::Value() const { 3457 if (IsDeadCheck(i::Isolate::Current(), "v8::Number::Value()")) return 0; 3458 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3459 return obj->Number(); 3460 } 3461 3462 3463 bool Boolean::Value() const { 3464 if (IsDeadCheck(i::Isolate::Current(), "v8::Boolean::Value()")) return false; 3465 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3466 return obj->IsTrue(); 3467 } 3468 3469 3470 int64_t Integer::Value() const { 3471 if (IsDeadCheck(i::Isolate::Current(), "v8::Integer::Value()")) return 0; 3472 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3473 if (obj->IsSmi()) { 3474 return i::Smi::cast(*obj)->value(); 3475 } else { 3476 return static_cast<int64_t>(obj->Number()); 3477 } 3478 } 3479 3480 3481 int32_t Int32::Value() const { 3482 if (IsDeadCheck(i::Isolate::Current(), "v8::Int32::Value()")) return 0; 3483 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3484 if (obj->IsSmi()) { 3485 return i::Smi::cast(*obj)->value(); 3486 } else { 3487 return static_cast<int32_t>(obj->Number()); 3488 } 3489 } 3490 3491 3492 uint32_t Uint32::Value() const { 3493 if (IsDeadCheck(i::Isolate::Current(), "v8::Uint32::Value()")) return 0; 3494 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3495 if (obj->IsSmi()) { 3496 return i::Smi::cast(*obj)->value(); 3497 } else { 3498 return static_cast<uint32_t>(obj->Number()); 3499 } 3500 } 3501 3502 3503 int v8::Object::InternalFieldCount() { 3504 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 3505 if (IsDeadCheck(obj->GetIsolate(), "v8::Object::InternalFieldCount()")) { 3506 return 0; 3507 } 3508 return obj->GetInternalFieldCount(); 3509 } 3510 3511 3512 Local<Value> v8::Object::CheckedGetInternalField(int index) { 3513 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 3514 if (IsDeadCheck(obj->GetIsolate(), "v8::Object::GetInternalField()")) { 3515 return Local<Value>(); 3516 } 3517 if (!ApiCheck(index < obj->GetInternalFieldCount(), 3518 "v8::Object::GetInternalField()", 3519 "Reading internal field out of bounds")) { 3520 return Local<Value>(); 3521 } 3522 i::Handle<i::Object> value(obj->GetInternalField(index)); 3523 Local<Value> result = Utils::ToLocal(value); 3524 #ifdef DEBUG 3525 Local<Value> unchecked = UncheckedGetInternalField(index); 3526 ASSERT(unchecked.IsEmpty() || (unchecked == result)); 3527 #endif 3528 return result; 3529 } 3530 3531 3532 void v8::Object::SetInternalField(int index, v8::Handle<Value> value) { 3533 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 3534 i::Isolate* isolate = obj->GetIsolate(); 3535 if (IsDeadCheck(isolate, "v8::Object::SetInternalField()")) { 3536 return; 3537 } 3538 if (!ApiCheck(index < obj->GetInternalFieldCount(), 3539 "v8::Object::SetInternalField()", 3540 "Writing internal field out of bounds")) { 3541 return; 3542 } 3543 ENTER_V8(isolate); 3544 i::Handle<i::Object> val = Utils::OpenHandle(*value); 3545 obj->SetInternalField(index, *val); 3546 } 3547 3548 3549 static bool CanBeEncodedAsSmi(void* ptr) { 3550 const uintptr_t address = reinterpret_cast<uintptr_t>(ptr); 3551 return ((address & i::kEncodablePointerMask) == 0); 3552 } 3553 3554 3555 static i::Smi* EncodeAsSmi(void* ptr) { 3556 ASSERT(CanBeEncodedAsSmi(ptr)); 3557 const uintptr_t address = reinterpret_cast<uintptr_t>(ptr); 3558 i::Smi* result = reinterpret_cast<i::Smi*>(address << i::kPointerToSmiShift); 3559 ASSERT(i::Internals::HasSmiTag(result)); 3560 ASSERT_EQ(result, i::Smi::FromInt(result->value())); 3561 ASSERT_EQ(ptr, i::Internals::GetExternalPointerFromSmi(result)); 3562 return result; 3563 } 3564 3565 3566 void v8::Object::SetPointerInInternalField(int index, void* value) { 3567 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3568 ENTER_V8(isolate); 3569 if (CanBeEncodedAsSmi(value)) { 3570 Utils::OpenHandle(this)->SetInternalField(index, EncodeAsSmi(value)); 3571 } else { 3572 HandleScope scope; 3573 i::Handle<i::Proxy> proxy = 3574 isolate->factory()->NewProxy( 3575 reinterpret_cast<i::Address>(value), i::TENURED); 3576 if (!proxy.is_null()) 3577 Utils::OpenHandle(this)->SetInternalField(index, *proxy); 3578 } 3579 ASSERT_EQ(value, GetPointerFromInternalField(index)); 3580 } 3581 3582 3583 // --- E n v i r o n m e n t --- 3584 3585 3586 bool v8::V8::Initialize() { 3587 i::Isolate* isolate = i::Isolate::UncheckedCurrent(); 3588 if (isolate != NULL && isolate->IsInitialized()) { 3589 return true; 3590 } 3591 return InitializeHelper(); 3592 } 3593 3594 3595 bool v8::V8::Dispose() { 3596 i::Isolate* isolate = i::Isolate::Current(); 3597 if (!ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(), 3598 "v8::V8::Dispose()", 3599 "Use v8::Isolate::Dispose() for a non-default isolate.")) { 3600 return false; 3601 } 3602 i::V8::TearDown(); 3603 return true; 3604 } 3605 3606 3607 HeapStatistics::HeapStatistics(): total_heap_size_(0), 3608 total_heap_size_executable_(0), 3609 used_heap_size_(0), 3610 heap_size_limit_(0) { } 3611 3612 3613 void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) { 3614 i::Heap* heap = i::Isolate::Current()->heap(); 3615 heap_statistics->set_total_heap_size(heap->CommittedMemory()); 3616 heap_statistics->set_total_heap_size_executable( 3617 heap->CommittedMemoryExecutable()); 3618 heap_statistics->set_used_heap_size(heap->SizeOfObjects()); 3619 heap_statistics->set_heap_size_limit(heap->MaxReserved()); 3620 } 3621 3622 3623 bool v8::V8::IdleNotification() { 3624 // Returning true tells the caller that it need not 3625 // continue to call IdleNotification. 3626 if (!i::Isolate::Current()->IsInitialized()) return true; 3627 return i::V8::IdleNotification(); 3628 } 3629 3630 3631 void v8::V8::LowMemoryNotification() { 3632 i::Isolate* isolate = i::Isolate::Current(); 3633 if (!isolate->IsInitialized()) return; 3634 isolate->heap()->CollectAllGarbage(true); 3635 } 3636 3637 3638 int v8::V8::ContextDisposedNotification() { 3639 i::Isolate* isolate = i::Isolate::Current(); 3640 if (!isolate->IsInitialized()) return 0; 3641 return isolate->heap()->NotifyContextDisposed(); 3642 } 3643 3644 3645 const char* v8::V8::GetVersion() { 3646 return i::Version::GetVersion(); 3647 } 3648 3649 3650 static i::Handle<i::FunctionTemplateInfo> 3651 EnsureConstructor(i::Handle<i::ObjectTemplateInfo> templ) { 3652 if (templ->constructor()->IsUndefined()) { 3653 Local<FunctionTemplate> constructor = FunctionTemplate::New(); 3654 Utils::OpenHandle(*constructor)->set_instance_template(*templ); 3655 templ->set_constructor(*Utils::OpenHandle(*constructor)); 3656 } 3657 return i::Handle<i::FunctionTemplateInfo>( 3658 i::FunctionTemplateInfo::cast(templ->constructor())); 3659 } 3660 3661 3662 Persistent<Context> v8::Context::New( 3663 v8::ExtensionConfiguration* extensions, 3664 v8::Handle<ObjectTemplate> global_template, 3665 v8::Handle<Value> global_object) { 3666 i::Isolate* isolate = i::Isolate::Current(); 3667 EnsureInitializedForIsolate(isolate, "v8::Context::New()"); 3668 LOG_API(isolate, "Context::New"); 3669 ON_BAILOUT(isolate, "v8::Context::New()", return Persistent<Context>()); 3670 3671 // Enter V8 via an ENTER_V8 scope. 3672 i::Handle<i::Context> env; 3673 { 3674 ENTER_V8(isolate); 3675 v8::Handle<ObjectTemplate> proxy_template = global_template; 3676 i::Handle<i::FunctionTemplateInfo> proxy_constructor; 3677 i::Handle<i::FunctionTemplateInfo> global_constructor; 3678 3679 if (!global_template.IsEmpty()) { 3680 // Make sure that the global_template has a constructor. 3681 global_constructor = 3682 EnsureConstructor(Utils::OpenHandle(*global_template)); 3683 3684 // Create a fresh template for the global proxy object. 3685 proxy_template = ObjectTemplate::New(); 3686 proxy_constructor = 3687 EnsureConstructor(Utils::OpenHandle(*proxy_template)); 3688 3689 // Set the global template to be the prototype template of 3690 // global proxy template. 3691 proxy_constructor->set_prototype_template( 3692 *Utils::OpenHandle(*global_template)); 3693 3694 // Migrate security handlers from global_template to 3695 // proxy_template. Temporarily removing access check 3696 // information from the global template. 3697 if (!global_constructor->access_check_info()->IsUndefined()) { 3698 proxy_constructor->set_access_check_info( 3699 global_constructor->access_check_info()); 3700 proxy_constructor->set_needs_access_check( 3701 global_constructor->needs_access_check()); 3702 global_constructor->set_needs_access_check(false); 3703 global_constructor->set_access_check_info( 3704 isolate->heap()->undefined_value()); 3705 } 3706 } 3707 3708 // Create the environment. 3709 env = isolate->bootstrapper()->CreateEnvironment( 3710 Utils::OpenHandle(*global_object), 3711 proxy_template, 3712 extensions); 3713 3714 // Restore the access check info on the global template. 3715 if (!global_template.IsEmpty()) { 3716 ASSERT(!global_constructor.is_null()); 3717 ASSERT(!proxy_constructor.is_null()); 3718 global_constructor->set_access_check_info( 3719 proxy_constructor->access_check_info()); 3720 global_constructor->set_needs_access_check( 3721 proxy_constructor->needs_access_check()); 3722 } 3723 isolate->runtime_profiler()->Reset(); 3724 } 3725 // Leave V8. 3726 3727 if (env.is_null()) 3728 return Persistent<Context>(); 3729 return Persistent<Context>(Utils::ToLocal(env)); 3730 } 3731 3732 3733 void v8::Context::SetSecurityToken(Handle<Value> token) { 3734 i::Isolate* isolate = i::Isolate::Current(); 3735 if (IsDeadCheck(isolate, "v8::Context::SetSecurityToken()")) { 3736 return; 3737 } 3738 ENTER_V8(isolate); 3739 i::Handle<i::Context> env = Utils::OpenHandle(this); 3740 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token); 3741 env->set_security_token(*token_handle); 3742 } 3743 3744 3745 void v8::Context::UseDefaultSecurityToken() { 3746 i::Isolate* isolate = i::Isolate::Current(); 3747 if (IsDeadCheck(isolate, 3748 "v8::Context::UseDefaultSecurityToken()")) { 3749 return; 3750 } 3751 ENTER_V8(isolate); 3752 i::Handle<i::Context> env = Utils::OpenHandle(this); 3753 env->set_security_token(env->global()); 3754 } 3755 3756 3757 Handle<Value> v8::Context::GetSecurityToken() { 3758 i::Isolate* isolate = i::Isolate::Current(); 3759 if (IsDeadCheck(isolate, "v8::Context::GetSecurityToken()")) { 3760 return Handle<Value>(); 3761 } 3762 i::Handle<i::Context> env = Utils::OpenHandle(this); 3763 i::Object* security_token = env->security_token(); 3764 i::Handle<i::Object> token_handle(security_token); 3765 return Utils::ToLocal(token_handle); 3766 } 3767 3768 3769 bool Context::HasOutOfMemoryException() { 3770 i::Handle<i::Context> env = Utils::OpenHandle(this); 3771 return env->has_out_of_memory(); 3772 } 3773 3774 3775 bool Context::InContext() { 3776 return i::Isolate::Current()->context() != NULL; 3777 } 3778 3779 3780 v8::Local<v8::Context> Context::GetEntered() { 3781 i::Isolate* isolate = i::Isolate::Current(); 3782 if (!EnsureInitializedForIsolate(isolate, "v8::Context::GetEntered()")) { 3783 return Local<Context>(); 3784 } 3785 i::Handle<i::Object> last = 3786 isolate->handle_scope_implementer()->LastEnteredContext(); 3787 if (last.is_null()) return Local<Context>(); 3788 i::Handle<i::Context> context = i::Handle<i::Context>::cast(last); 3789 return Utils::ToLocal(context); 3790 } 3791 3792 3793 v8::Local<v8::Context> Context::GetCurrent() { 3794 i::Isolate* isolate = i::Isolate::Current(); 3795 if (IsDeadCheck(isolate, "v8::Context::GetCurrent()")) { 3796 return Local<Context>(); 3797 } 3798 i::Handle<i::Object> current = isolate->global_context(); 3799 if (current.is_null()) return Local<Context>(); 3800 i::Handle<i::Context> context = i::Handle<i::Context>::cast(current); 3801 return Utils::ToLocal(context); 3802 } 3803 3804 3805 v8::Local<v8::Context> Context::GetCalling() { 3806 i::Isolate* isolate = i::Isolate::Current(); 3807 if (IsDeadCheck(isolate, "v8::Context::GetCalling()")) { 3808 return Local<Context>(); 3809 } 3810 i::Handle<i::Object> calling = 3811 isolate->GetCallingGlobalContext(); 3812 if (calling.is_null()) return Local<Context>(); 3813 i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling); 3814 return Utils::ToLocal(context); 3815 } 3816 3817 3818 v8::Local<v8::Object> Context::Global() { 3819 if (IsDeadCheck(i::Isolate::Current(), "v8::Context::Global()")) { 3820 return Local<v8::Object>(); 3821 } 3822 i::Object** ctx = reinterpret_cast<i::Object**>(this); 3823 i::Handle<i::Context> context = 3824 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx)); 3825 i::Handle<i::Object> global(context->global_proxy()); 3826 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global)); 3827 } 3828 3829 3830 void Context::DetachGlobal() { 3831 i::Isolate* isolate = i::Isolate::Current(); 3832 if (IsDeadCheck(isolate, "v8::Context::DetachGlobal()")) return; 3833 ENTER_V8(isolate); 3834 i::Object** ctx = reinterpret_cast<i::Object**>(this); 3835 i::Handle<i::Context> context = 3836 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx)); 3837 isolate->bootstrapper()->DetachGlobal(context); 3838 } 3839 3840 3841 void Context::ReattachGlobal(Handle<Object> global_object) { 3842 i::Isolate* isolate = i::Isolate::Current(); 3843 if (IsDeadCheck(isolate, "v8::Context::ReattachGlobal()")) return; 3844 ENTER_V8(isolate); 3845 i::Object** ctx = reinterpret_cast<i::Object**>(this); 3846 i::Handle<i::Context> context = 3847 i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx)); 3848 isolate->bootstrapper()->ReattachGlobal( 3849 context, 3850 Utils::OpenHandle(*global_object)); 3851 } 3852 3853 3854 void V8::SetWrapperClassId(i::Object** global_handle, uint16_t class_id) { 3855 i::GlobalHandles::SetWrapperClassId(global_handle, class_id); 3856 } 3857 3858 3859 Local<v8::Object> ObjectTemplate::NewInstance() { 3860 i::Isolate* isolate = i::Isolate::Current(); 3861 ON_BAILOUT(isolate, "v8::ObjectTemplate::NewInstance()", 3862 return Local<v8::Object>()); 3863 LOG_API(isolate, "ObjectTemplate::NewInstance"); 3864 ENTER_V8(isolate); 3865 EXCEPTION_PREAMBLE(isolate); 3866 i::Handle<i::Object> obj = 3867 i::Execution::InstantiateObject(Utils::OpenHandle(this), 3868 &has_pending_exception); 3869 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); 3870 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj)); 3871 } 3872 3873 3874 Local<v8::Function> FunctionTemplate::GetFunction() { 3875 i::Isolate* isolate = i::Isolate::Current(); 3876 ON_BAILOUT(isolate, "v8::FunctionTemplate::GetFunction()", 3877 return Local<v8::Function>()); 3878 LOG_API(isolate, "FunctionTemplate::GetFunction"); 3879 ENTER_V8(isolate); 3880 EXCEPTION_PREAMBLE(isolate); 3881 i::Handle<i::Object> obj = 3882 i::Execution::InstantiateFunction(Utils::OpenHandle(this), 3883 &has_pending_exception); 3884 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Function>()); 3885 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj)); 3886 } 3887 3888 3889 bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) { 3890 ON_BAILOUT(i::Isolate::Current(), "v8::FunctionTemplate::HasInstanceOf()", 3891 return false); 3892 i::Object* obj = *Utils::OpenHandle(*value); 3893 return obj->IsInstanceOf(*Utils::OpenHandle(this)); 3894 } 3895 3896 3897 static Local<External> ExternalNewImpl(void* data) { 3898 return Utils::ToLocal(FACTORY->NewProxy(static_cast<i::Address>(data))); 3899 } 3900 3901 static void* ExternalValueImpl(i::Handle<i::Object> obj) { 3902 return reinterpret_cast<void*>(i::Proxy::cast(*obj)->proxy()); 3903 } 3904 3905 3906 Local<Value> v8::External::Wrap(void* data) { 3907 i::Isolate* isolate = i::Isolate::Current(); 3908 STATIC_ASSERT(sizeof(data) == sizeof(i::Address)); 3909 EnsureInitializedForIsolate(isolate, "v8::External::Wrap()"); 3910 LOG_API(isolate, "External::Wrap"); 3911 ENTER_V8(isolate); 3912 3913 v8::Local<v8::Value> result = CanBeEncodedAsSmi(data) 3914 ? Utils::ToLocal(i::Handle<i::Object>(EncodeAsSmi(data))) 3915 : v8::Local<v8::Value>(ExternalNewImpl(data)); 3916 3917 ASSERT_EQ(data, Unwrap(result)); 3918 return result; 3919 } 3920 3921 3922 void* v8::Object::SlowGetPointerFromInternalField(int index) { 3923 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 3924 i::Object* value = obj->GetInternalField(index); 3925 if (value->IsSmi()) { 3926 return i::Internals::GetExternalPointerFromSmi(value); 3927 } else if (value->IsProxy()) { 3928 return reinterpret_cast<void*>(i::Proxy::cast(value)->proxy()); 3929 } else { 3930 return NULL; 3931 } 3932 } 3933 3934 3935 void* v8::External::FullUnwrap(v8::Handle<v8::Value> wrapper) { 3936 if (IsDeadCheck(i::Isolate::Current(), "v8::External::Unwrap()")) return 0; 3937 i::Handle<i::Object> obj = Utils::OpenHandle(*wrapper); 3938 void* result; 3939 if (obj->IsSmi()) { 3940 result = i::Internals::GetExternalPointerFromSmi(*obj); 3941 } else if (obj->IsProxy()) { 3942 result = ExternalValueImpl(obj); 3943 } else { 3944 result = NULL; 3945 } 3946 ASSERT_EQ(result, QuickUnwrap(wrapper)); 3947 return result; 3948 } 3949 3950 3951 Local<External> v8::External::New(void* data) { 3952 STATIC_ASSERT(sizeof(data) == sizeof(i::Address)); 3953 i::Isolate* isolate = i::Isolate::Current(); 3954 EnsureInitializedForIsolate(isolate, "v8::External::New()"); 3955 LOG_API(isolate, "External::New"); 3956 ENTER_V8(isolate); 3957 return ExternalNewImpl(data); 3958 } 3959 3960 3961 void* External::Value() const { 3962 if (IsDeadCheck(i::Isolate::Current(), "v8::External::Value()")) return 0; 3963 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3964 return ExternalValueImpl(obj); 3965 } 3966 3967 3968 Local<String> v8::String::Empty() { 3969 i::Isolate* isolate = i::Isolate::Current(); 3970 EnsureInitializedForIsolate(isolate, "v8::String::Empty()"); 3971 LOG_API(isolate, "String::Empty()"); 3972 return Utils::ToLocal(isolate->factory()->empty_symbol()); 3973 } 3974 3975 3976 Local<String> v8::String::New(const char* data, int length) { 3977 i::Isolate* isolate = i::Isolate::Current(); 3978 EnsureInitializedForIsolate(isolate, "v8::String::New()"); 3979 LOG_API(isolate, "String::New(char)"); 3980 if (length == 0) return Empty(); 3981 ENTER_V8(isolate); 3982 if (length == -1) length = i::StrLength(data); 3983 i::Handle<i::String> result = 3984 isolate->factory()->NewStringFromUtf8( 3985 i::Vector<const char>(data, length)); 3986 return Utils::ToLocal(result); 3987 } 3988 3989 3990 Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) { 3991 i::Handle<i::String> left_string = Utils::OpenHandle(*left); 3992 i::Isolate* isolate = left_string->GetIsolate(); 3993 EnsureInitializedForIsolate(isolate, "v8::String::New()"); 3994 LOG_API(isolate, "String::New(char)"); 3995 ENTER_V8(isolate); 3996 i::Handle<i::String> right_string = Utils::OpenHandle(*right); 3997 i::Handle<i::String> result = isolate->factory()->NewConsString(left_string, 3998 right_string); 3999 return Utils::ToLocal(result); 4000 } 4001 4002 4003 Local<String> v8::String::NewUndetectable(const char* data, int length) { 4004 i::Isolate* isolate = i::Isolate::Current(); 4005 EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()"); 4006 LOG_API(isolate, "String::NewUndetectable(char)"); 4007 ENTER_V8(isolate); 4008 if (length == -1) length = i::StrLength(data); 4009 i::Handle<i::String> result = 4010 isolate->factory()->NewStringFromUtf8( 4011 i::Vector<const char>(data, length)); 4012 result->MarkAsUndetectable(); 4013 return Utils::ToLocal(result); 4014 } 4015 4016 4017 static int TwoByteStringLength(const uint16_t* data) { 4018 int length = 0; 4019 while (data[length] != '\0') length++; 4020 return length; 4021 } 4022 4023 4024 Local<String> v8::String::New(const uint16_t* data, int length) { 4025 i::Isolate* isolate = i::Isolate::Current(); 4026 EnsureInitializedForIsolate(isolate, "v8::String::New()"); 4027 LOG_API(isolate, "String::New(uint16_)"); 4028 if (length == 0) return Empty(); 4029 ENTER_V8(isolate); 4030 if (length == -1) length = TwoByteStringLength(data); 4031 i::Handle<i::String> result = 4032 isolate->factory()->NewStringFromTwoByte( 4033 i::Vector<const uint16_t>(data, length)); 4034 return Utils::ToLocal(result); 4035 } 4036 4037 4038 Local<String> v8::String::NewUndetectable(const uint16_t* data, int length) { 4039 i::Isolate* isolate = i::Isolate::Current(); 4040 EnsureInitializedForIsolate(isolate, "v8::String::NewUndetectable()"); 4041 LOG_API(isolate, "String::NewUndetectable(uint16_)"); 4042 ENTER_V8(isolate); 4043 if (length == -1) length = TwoByteStringLength(data); 4044 i::Handle<i::String> result = 4045 isolate->factory()->NewStringFromTwoByte( 4046 i::Vector<const uint16_t>(data, length)); 4047 result->MarkAsUndetectable(); 4048 return Utils::ToLocal(result); 4049 } 4050 4051 4052 i::Handle<i::String> NewExternalStringHandle(i::Isolate* isolate, 4053 v8::String::ExternalStringResource* resource) { 4054 i::Handle<i::String> result = 4055 isolate->factory()->NewExternalStringFromTwoByte(resource); 4056 return result; 4057 } 4058 4059 4060 i::Handle<i::String> NewExternalAsciiStringHandle(i::Isolate* isolate, 4061 v8::String::ExternalAsciiStringResource* resource) { 4062 i::Handle<i::String> result = 4063 isolate->factory()->NewExternalStringFromAscii(resource); 4064 return result; 4065 } 4066 4067 4068 Local<String> v8::String::NewExternal( 4069 v8::String::ExternalStringResource* resource) { 4070 i::Isolate* isolate = i::Isolate::Current(); 4071 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); 4072 LOG_API(isolate, "String::NewExternal"); 4073 ENTER_V8(isolate); 4074 i::Handle<i::String> result = NewExternalStringHandle(isolate, resource); 4075 isolate->heap()->external_string_table()->AddString(*result); 4076 return Utils::ToLocal(result); 4077 } 4078 4079 4080 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { 4081 i::Handle<i::String> obj = Utils::OpenHandle(this); 4082 i::Isolate* isolate = obj->GetIsolate(); 4083 if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false; 4084 if (i::StringShape(*obj).IsExternalTwoByte()) { 4085 return false; // Already an external string. 4086 } 4087 ENTER_V8(isolate); 4088 if (isolate->string_tracker()->IsFreshUnusedString(obj)) { 4089 return false; 4090 } 4091 bool result = obj->MakeExternal(resource); 4092 if (result && !obj->IsSymbol()) { 4093 isolate->heap()->external_string_table()->AddString(*obj); 4094 } 4095 return result; 4096 } 4097 4098 4099 Local<String> v8::String::NewExternal( 4100 v8::String::ExternalAsciiStringResource* resource) { 4101 i::Isolate* isolate = i::Isolate::Current(); 4102 EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); 4103 LOG_API(isolate, "String::NewExternal"); 4104 ENTER_V8(isolate); 4105 i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource); 4106 isolate->heap()->external_string_table()->AddString(*result); 4107 return Utils::ToLocal(result); 4108 } 4109 4110 4111 bool v8::String::MakeExternal( 4112 v8::String::ExternalAsciiStringResource* resource) { 4113 i::Handle<i::String> obj = Utils::OpenHandle(this); 4114 i::Isolate* isolate = obj->GetIsolate(); 4115 if (IsDeadCheck(isolate, "v8::String::MakeExternal()")) return false; 4116 if (i::StringShape(*obj).IsExternalTwoByte()) { 4117 return false; // Already an external string. 4118 } 4119 ENTER_V8(isolate); 4120 if (isolate->string_tracker()->IsFreshUnusedString(obj)) { 4121 return false; 4122 } 4123 bool result = obj->MakeExternal(resource); 4124 if (result && !obj->IsSymbol()) { 4125 isolate->heap()->external_string_table()->AddString(*obj); 4126 } 4127 return result; 4128 } 4129 4130 4131 bool v8::String::CanMakeExternal() { 4132 i::Handle<i::String> obj = Utils::OpenHandle(this); 4133 i::Isolate* isolate = obj->GetIsolate(); 4134 if (IsDeadCheck(isolate, "v8::String::CanMakeExternal()")) return false; 4135 if (isolate->string_tracker()->IsFreshUnusedString(obj)) { 4136 return false; 4137 } 4138 int size = obj->Size(); // Byte size of the original string. 4139 if (size < i::ExternalString::kSize) 4140 return false; 4141 i::StringShape shape(*obj); 4142 return !shape.IsExternal(); 4143 } 4144 4145 4146 Local<v8::Object> v8::Object::New() { 4147 i::Isolate* isolate = i::Isolate::Current(); 4148 EnsureInitializedForIsolate(isolate, "v8::Object::New()"); 4149 LOG_API(isolate, "Object::New"); 4150 ENTER_V8(isolate); 4151 i::Handle<i::JSObject> obj = 4152 isolate->factory()->NewJSObject(isolate->object_function()); 4153 return Utils::ToLocal(obj); 4154 } 4155 4156 4157 Local<v8::Value> v8::Date::New(double time) { 4158 i::Isolate* isolate = i::Isolate::Current(); 4159 EnsureInitializedForIsolate(isolate, "v8::Date::New()"); 4160 LOG_API(isolate, "Date::New"); 4161 if (isnan(time)) { 4162 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs. 4163 time = i::OS::nan_value(); 4164 } 4165 ENTER_V8(isolate); 4166 EXCEPTION_PREAMBLE(isolate); 4167 i::Handle<i::Object> obj = 4168 i::Execution::NewDate(time, &has_pending_exception); 4169 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Value>()); 4170 return Utils::ToLocal(obj); 4171 } 4172 4173 4174 double v8::Date::NumberValue() const { 4175 i::Isolate* isolate = i::Isolate::Current(); 4176 if (IsDeadCheck(isolate, "v8::Date::NumberValue()")) return 0; 4177 LOG_API(isolate, "Date::NumberValue"); 4178 i::Handle<i::Object> obj = Utils::OpenHandle(this); 4179 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj); 4180 return jsvalue->value()->Number(); 4181 } 4182 4183 4184 void v8::Date::DateTimeConfigurationChangeNotification() { 4185 i::Isolate* isolate = i::Isolate::Current(); 4186 ON_BAILOUT(isolate, "v8::Date::DateTimeConfigurationChangeNotification()", 4187 return); 4188 LOG_API(isolate, "Date::DateTimeConfigurationChangeNotification"); 4189 ENTER_V8(isolate); 4190 4191 i::HandleScope scope(isolate); 4192 // Get the function ResetDateCache (defined in date-delay.js). 4193 i::Handle<i::String> func_name_str = 4194 isolate->factory()->LookupAsciiSymbol("ResetDateCache"); 4195 i::MaybeObject* result = 4196 isolate->js_builtins_object()->GetProperty(*func_name_str); 4197 i::Object* object_func; 4198 if (!result->ToObject(&object_func)) { 4199 return; 4200 } 4201 4202 if (object_func->IsJSFunction()) { 4203 i::Handle<i::JSFunction> func = 4204 i::Handle<i::JSFunction>(i::JSFunction::cast(object_func)); 4205 4206 // Call ResetDateCache(0 but expect no exceptions: 4207 bool caught_exception = false; 4208 i::Execution::TryCall(func, 4209 isolate->js_builtins_object(), 4210 0, 4211 NULL, 4212 &caught_exception); 4213 } 4214 } 4215 4216 4217 static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) { 4218 char flags_buf[3]; 4219 int num_flags = 0; 4220 if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g'; 4221 if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm'; 4222 if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i'; 4223 ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf))); 4224 return FACTORY->LookupSymbol( 4225 i::Vector<const char>(flags_buf, num_flags)); 4226 } 4227 4228 4229 Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern, 4230 Flags flags) { 4231 i::Isolate* isolate = Utils::OpenHandle(*pattern)->GetIsolate(); 4232 EnsureInitializedForIsolate(isolate, "v8::RegExp::New()"); 4233 LOG_API(isolate, "RegExp::New"); 4234 ENTER_V8(isolate); 4235 EXCEPTION_PREAMBLE(isolate); 4236 i::Handle<i::JSRegExp> obj = i::Execution::NewJSRegExp( 4237 Utils::OpenHandle(*pattern), 4238 RegExpFlagsToString(flags), 4239 &has_pending_exception); 4240 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::RegExp>()); 4241 return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj)); 4242 } 4243 4244 4245 Local<v8::String> v8::RegExp::GetSource() const { 4246 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4247 if (IsDeadCheck(isolate, "v8::RegExp::GetSource()")) { 4248 return Local<v8::String>(); 4249 } 4250 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this); 4251 return Utils::ToLocal(i::Handle<i::String>(obj->Pattern())); 4252 } 4253 4254 4255 // Assert that the static flags cast in GetFlags is valid. 4256 #define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \ 4257 STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \ 4258 static_cast<int>(i::JSRegExp::internal_flag)) 4259 REGEXP_FLAG_ASSERT_EQ(kNone, NONE); 4260 REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL); 4261 REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE); 4262 REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE); 4263 #undef REGEXP_FLAG_ASSERT_EQ 4264 4265 v8::RegExp::Flags v8::RegExp::GetFlags() const { 4266 if (IsDeadCheck(i::Isolate::Current(), "v8::RegExp::GetFlags()")) { 4267 return v8::RegExp::kNone; 4268 } 4269 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this); 4270 return static_cast<RegExp::Flags>(obj->GetFlags().value()); 4271 } 4272 4273 4274 Local<v8::Array> v8::Array::New(int length) { 4275 i::Isolate* isolate = i::Isolate::Current(); 4276 EnsureInitializedForIsolate(isolate, "v8::Array::New()"); 4277 LOG_API(isolate, "Array::New"); 4278 ENTER_V8(isolate); 4279 int real_length = length > 0 ? length : 0; 4280 i::Handle<i::JSArray> obj = isolate->factory()->NewJSArray(real_length); 4281 i::Handle<i::Object> length_obj = 4282 isolate->factory()->NewNumberFromInt(real_length); 4283 obj->set_length(*length_obj); 4284 return Utils::ToLocal(obj); 4285 } 4286 4287 4288 uint32_t v8::Array::Length() const { 4289 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4290 if (IsDeadCheck(isolate, "v8::Array::Length()")) return 0; 4291 i::Handle<i::JSArray> obj = Utils::OpenHandle(this); 4292 i::Object* length = obj->length(); 4293 if (length->IsSmi()) { 4294 return i::Smi::cast(length)->value(); 4295 } else { 4296 return static_cast<uint32_t>(length->Number()); 4297 } 4298 } 4299 4300 4301 Local<Object> Array::CloneElementAt(uint32_t index) { 4302 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4303 ON_BAILOUT(isolate, "v8::Array::CloneElementAt()", return Local<Object>()); 4304 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 4305 if (!self->HasFastElements()) { 4306 return Local<Object>(); 4307 } 4308 i::FixedArray* elms = i::FixedArray::cast(self->elements()); 4309 i::Object* paragon = elms->get(index); 4310 if (!paragon->IsJSObject()) { 4311 return Local<Object>(); 4312 } 4313 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon)); 4314 EXCEPTION_PREAMBLE(isolate); 4315 ENTER_V8(isolate); 4316 i::Handle<i::JSObject> result = i::Copy(paragon_handle); 4317 has_pending_exception = result.is_null(); 4318 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>()); 4319 return Utils::ToLocal(result); 4320 } 4321 4322 4323 Local<String> v8::String::NewSymbol(const char* data, int length) { 4324 i::Isolate* isolate = i::Isolate::Current(); 4325 EnsureInitializedForIsolate(isolate, "v8::String::NewSymbol()"); 4326 LOG_API(isolate, "String::NewSymbol(char)"); 4327 ENTER_V8(isolate); 4328 if (length == -1) length = i::StrLength(data); 4329 i::Handle<i::String> result = 4330 isolate->factory()->LookupSymbol(i::Vector<const char>(data, length)); 4331 return Utils::ToLocal(result); 4332 } 4333 4334 4335 Local<Number> v8::Number::New(double value) { 4336 i::Isolate* isolate = i::Isolate::Current(); 4337 EnsureInitializedForIsolate(isolate, "v8::Number::New()"); 4338 if (isnan(value)) { 4339 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs. 4340 value = i::OS::nan_value(); 4341 } 4342 ENTER_V8(isolate); 4343 i::Handle<i::Object> result = isolate->factory()->NewNumber(value); 4344 return Utils::NumberToLocal(result); 4345 } 4346 4347 4348 Local<Integer> v8::Integer::New(int32_t value) { 4349 i::Isolate* isolate = i::Isolate::UncheckedCurrent(); 4350 EnsureInitializedForIsolate(isolate, "v8::Integer::New()"); 4351 if (i::Smi::IsValid(value)) { 4352 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value), 4353 isolate)); 4354 } 4355 ENTER_V8(isolate); 4356 i::Handle<i::Object> result = isolate->factory()->NewNumber(value); 4357 return Utils::IntegerToLocal(result); 4358 } 4359 4360 4361 Local<Integer> Integer::NewFromUnsigned(uint32_t value) { 4362 bool fits_into_int32_t = (value & (1 << 31)) == 0; 4363 if (fits_into_int32_t) { 4364 return Integer::New(static_cast<int32_t>(value)); 4365 } 4366 i::Isolate* isolate = i::Isolate::Current(); 4367 ENTER_V8(isolate); 4368 i::Handle<i::Object> result = isolate->factory()->NewNumber(value); 4369 return Utils::IntegerToLocal(result); 4370 } 4371 4372 4373 void V8::IgnoreOutOfMemoryException() { 4374 EnterIsolateIfNeeded()->set_ignore_out_of_memory(true); 4375 } 4376 4377 4378 bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) { 4379 i::Isolate* isolate = i::Isolate::Current(); 4380 EnsureInitializedForIsolate(isolate, "v8::V8::AddMessageListener()"); 4381 ON_BAILOUT(isolate, "v8::V8::AddMessageListener()", return false); 4382 ENTER_V8(isolate); 4383 i::HandleScope scope(isolate); 4384 NeanderArray listeners(isolate->factory()->message_listeners()); 4385 NeanderObject obj(2); 4386 obj.set(0, *isolate->factory()->NewProxy(FUNCTION_ADDR(that))); 4387 obj.set(1, data.IsEmpty() ? 4388 isolate->heap()->undefined_value() : 4389 *Utils::OpenHandle(*data)); 4390 listeners.add(obj.value()); 4391 return true; 4392 } 4393 4394 4395 void V8::RemoveMessageListeners(MessageCallback that) { 4396 i::Isolate* isolate = i::Isolate::Current(); 4397 EnsureInitializedForIsolate(isolate, "v8::V8::RemoveMessageListener()"); 4398 ON_BAILOUT(isolate, "v8::V8::RemoveMessageListeners()", return); 4399 ENTER_V8(isolate); 4400 i::HandleScope scope(isolate); 4401 NeanderArray listeners(isolate->factory()->message_listeners()); 4402 for (int i = 0; i < listeners.length(); i++) { 4403 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones 4404 4405 NeanderObject listener(i::JSObject::cast(listeners.get(i))); 4406 i::Handle<i::Proxy> callback_obj(i::Proxy::cast(listener.get(0))); 4407 if (callback_obj->proxy() == FUNCTION_ADDR(that)) { 4408 listeners.set(i, isolate->heap()->undefined_value()); 4409 } 4410 } 4411 } 4412 4413 4414 void V8::SetCaptureStackTraceForUncaughtExceptions( 4415 bool capture, 4416 int frame_limit, 4417 StackTrace::StackTraceOptions options) { 4418 i::Isolate::Current()->SetCaptureStackTraceForUncaughtExceptions( 4419 capture, 4420 frame_limit, 4421 options); 4422 } 4423 4424 4425 void V8::SetCounterFunction(CounterLookupCallback callback) { 4426 i::Isolate* isolate = EnterIsolateIfNeeded(); 4427 if (IsDeadCheck(isolate, "v8::V8::SetCounterFunction()")) return; 4428 isolate->stats_table()->SetCounterFunction(callback); 4429 } 4430 4431 void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) { 4432 i::Isolate* isolate = EnterIsolateIfNeeded(); 4433 if (IsDeadCheck(isolate, "v8::V8::SetCreateHistogramFunction()")) return; 4434 isolate->stats_table()->SetCreateHistogramFunction(callback); 4435 } 4436 4437 void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) { 4438 i::Isolate* isolate = EnterIsolateIfNeeded(); 4439 if (IsDeadCheck(isolate, "v8::V8::SetAddHistogramSampleFunction()")) return; 4440 isolate->stats_table()-> 4441 SetAddHistogramSampleFunction(callback); 4442 } 4443 4444 void V8::EnableSlidingStateWindow() { 4445 i::Isolate* isolate = i::Isolate::Current(); 4446 if (IsDeadCheck(isolate, "v8::V8::EnableSlidingStateWindow()")) return; 4447 isolate->logger()->EnableSlidingStateWindow(); 4448 } 4449 4450 4451 void V8::SetFailedAccessCheckCallbackFunction( 4452 FailedAccessCheckCallback callback) { 4453 i::Isolate* isolate = i::Isolate::Current(); 4454 if (IsDeadCheck(isolate, "v8::V8::SetFailedAccessCheckCallbackFunction()")) { 4455 return; 4456 } 4457 isolate->SetFailedAccessCheckCallback(callback); 4458 } 4459 4460 void V8::AddObjectGroup(Persistent<Value>* objects, 4461 size_t length, 4462 RetainedObjectInfo* info) { 4463 i::Isolate* isolate = i::Isolate::Current(); 4464 if (IsDeadCheck(isolate, "v8::V8::AddObjectGroup()")) return; 4465 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**)); 4466 isolate->global_handles()->AddObjectGroup( 4467 reinterpret_cast<i::Object***>(objects), length, info); 4468 } 4469 4470 4471 void V8::AddImplicitReferences(Persistent<Object> parent, 4472 Persistent<Value>* children, 4473 size_t length) { 4474 i::Isolate* isolate = i::Isolate::Current(); 4475 if (IsDeadCheck(isolate, "v8::V8::AddImplicitReferences()")) return; 4476 STATIC_ASSERT(sizeof(Persistent<Value>) == sizeof(i::Object**)); 4477 isolate->global_handles()->AddImplicitReferences( 4478 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(*parent)).location(), 4479 reinterpret_cast<i::Object***>(children), length); 4480 } 4481 4482 4483 int V8::AdjustAmountOfExternalAllocatedMemory(int change_in_bytes) { 4484 i::Isolate* isolate = i::Isolate::Current(); 4485 if (IsDeadCheck(isolate, "v8::V8::AdjustAmountOfExternalAllocatedMemory()")) { 4486 return 0; 4487 } 4488 return isolate->heap()->AdjustAmountOfExternalAllocatedMemory( 4489 change_in_bytes); 4490 } 4491 4492 4493 void V8::SetGlobalGCPrologueCallback(GCCallback callback) { 4494 i::Isolate* isolate = i::Isolate::Current(); 4495 if (IsDeadCheck(isolate, "v8::V8::SetGlobalGCPrologueCallback()")) return; 4496 isolate->heap()->SetGlobalGCPrologueCallback(callback); 4497 } 4498 4499 4500 void V8::SetGlobalGCEpilogueCallback(GCCallback callback) { 4501 i::Isolate* isolate = i::Isolate::Current(); 4502 if (IsDeadCheck(isolate, "v8::V8::SetGlobalGCEpilogueCallback()")) return; 4503 isolate->heap()->SetGlobalGCEpilogueCallback(callback); 4504 } 4505 4506 4507 void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) { 4508 i::Isolate* isolate = i::Isolate::Current(); 4509 if (IsDeadCheck(isolate, "v8::V8::AddGCPrologueCallback()")) return; 4510 isolate->heap()->AddGCPrologueCallback(callback, gc_type); 4511 } 4512 4513 4514 void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) { 4515 i::Isolate* isolate = i::Isolate::Current(); 4516 if (IsDeadCheck(isolate, "v8::V8::RemoveGCPrologueCallback()")) return; 4517 isolate->heap()->RemoveGCPrologueCallback(callback); 4518 } 4519 4520 4521 void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) { 4522 i::Isolate* isolate = i::Isolate::Current(); 4523 if (IsDeadCheck(isolate, "v8::V8::AddGCEpilogueCallback()")) return; 4524 isolate->heap()->AddGCEpilogueCallback(callback, gc_type); 4525 } 4526 4527 4528 void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) { 4529 i::Isolate* isolate = i::Isolate::Current(); 4530 if (IsDeadCheck(isolate, "v8::V8::RemoveGCEpilogueCallback()")) return; 4531 isolate->heap()->RemoveGCEpilogueCallback(callback); 4532 } 4533 4534 4535 void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback, 4536 ObjectSpace space, 4537 AllocationAction action) { 4538 i::Isolate* isolate = i::Isolate::Current(); 4539 if (IsDeadCheck(isolate, "v8::V8::AddMemoryAllocationCallback()")) return; 4540 isolate->memory_allocator()->AddMemoryAllocationCallback( 4541 callback, space, action); 4542 } 4543 4544 4545 void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) { 4546 i::Isolate* isolate = i::Isolate::Current(); 4547 if (IsDeadCheck(isolate, "v8::V8::RemoveMemoryAllocationCallback()")) return; 4548 isolate->memory_allocator()->RemoveMemoryAllocationCallback( 4549 callback); 4550 } 4551 4552 4553 void V8::PauseProfiler() { 4554 #ifdef ENABLE_LOGGING_AND_PROFILING 4555 PauseProfilerEx(PROFILER_MODULE_CPU); 4556 #endif 4557 } 4558 4559 4560 void V8::ResumeProfiler() { 4561 #ifdef ENABLE_LOGGING_AND_PROFILING 4562 ResumeProfilerEx(PROFILER_MODULE_CPU); 4563 #endif 4564 } 4565 4566 4567 bool V8::IsProfilerPaused() { 4568 #ifdef ENABLE_LOGGING_AND_PROFILING 4569 return LOGGER->GetActiveProfilerModules() & PROFILER_MODULE_CPU; 4570 #else 4571 return true; 4572 #endif 4573 } 4574 4575 4576 void V8::ResumeProfilerEx(int flags, int tag) { 4577 #ifdef ENABLE_LOGGING_AND_PROFILING 4578 i::Isolate* isolate = i::Isolate::Current(); 4579 if (flags & PROFILER_MODULE_HEAP_SNAPSHOT) { 4580 // Snapshot mode: resume modules, perform GC, then pause only 4581 // those modules which haven't been started prior to making a 4582 // snapshot. 4583 4584 // Make a GC prior to taking a snapshot. 4585 isolate->heap()->CollectAllGarbage(false); 4586 // Reset snapshot flag and CPU module flags. 4587 flags &= ~(PROFILER_MODULE_HEAP_SNAPSHOT | PROFILER_MODULE_CPU); 4588 const int current_flags = isolate->logger()->GetActiveProfilerModules(); 4589 isolate->logger()->ResumeProfiler(flags, tag); 4590 isolate->heap()->CollectAllGarbage(false); 4591 isolate->logger()->PauseProfiler(~current_flags & flags, tag); 4592 } else { 4593 isolate->logger()->ResumeProfiler(flags, tag); 4594 } 4595 #endif 4596 } 4597 4598 4599 void V8::PauseProfilerEx(int flags, int tag) { 4600 #ifdef ENABLE_LOGGING_AND_PROFILING 4601 LOGGER->PauseProfiler(flags, tag); 4602 #endif 4603 } 4604 4605 4606 int V8::GetActiveProfilerModules() { 4607 #ifdef ENABLE_LOGGING_AND_PROFILING 4608 return LOGGER->GetActiveProfilerModules(); 4609 #else 4610 return PROFILER_MODULE_NONE; 4611 #endif 4612 } 4613 4614 4615 int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) { 4616 #ifdef ENABLE_LOGGING_AND_PROFILING 4617 ASSERT(max_size >= kMinimumSizeForLogLinesBuffer); 4618 return LOGGER->GetLogLines(from_pos, dest_buf, max_size); 4619 #endif 4620 return 0; 4621 } 4622 4623 4624 int V8::GetCurrentThreadId() { 4625 i::Isolate* isolate = i::Isolate::Current(); 4626 EnsureInitializedForIsolate(isolate, "V8::GetCurrentThreadId()"); 4627 return isolate->thread_id().ToInteger(); 4628 } 4629 4630 4631 void V8::TerminateExecution(int thread_id) { 4632 i::Isolate* isolate = i::Isolate::Current(); 4633 if (!isolate->IsInitialized()) return; 4634 API_ENTRY_CHECK("V8::TerminateExecution()"); 4635 // If the thread_id identifies the current thread just terminate 4636 // execution right away. Otherwise, ask the thread manager to 4637 // terminate the thread with the given id if any. 4638 i::ThreadId internal_tid = i::ThreadId::FromInteger(thread_id); 4639 if (isolate->thread_id().Equals(internal_tid)) { 4640 isolate->stack_guard()->TerminateExecution(); 4641 } else { 4642 isolate->thread_manager()->TerminateExecution(internal_tid); 4643 } 4644 } 4645 4646 4647 void V8::TerminateExecution(Isolate* isolate) { 4648 // If no isolate is supplied, use the default isolate. 4649 if (isolate != NULL) { 4650 reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->TerminateExecution(); 4651 } else { 4652 i::Isolate::GetDefaultIsolateStackGuard()->TerminateExecution(); 4653 } 4654 } 4655 4656 4657 bool V8::IsExecutionTerminating() { 4658 i::Isolate* isolate = i::Isolate::Current(); 4659 return IsExecutionTerminatingCheck(isolate); 4660 } 4661 4662 4663 Isolate* Isolate::GetCurrent() { 4664 i::Isolate* isolate = i::Isolate::UncheckedCurrent(); 4665 return reinterpret_cast<Isolate*>(isolate); 4666 } 4667 4668 4669 Isolate* Isolate::New() { 4670 i::Isolate* isolate = new i::Isolate(); 4671 return reinterpret_cast<Isolate*>(isolate); 4672 } 4673 4674 4675 void Isolate::Dispose() { 4676 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 4677 if (!ApiCheck(!isolate->IsInUse(), 4678 "v8::Isolate::Dispose()", 4679 "Disposing the isolate that is entered by a thread.")) { 4680 return; 4681 } 4682 isolate->TearDown(); 4683 } 4684 4685 4686 void Isolate::Enter() { 4687 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 4688 isolate->Enter(); 4689 } 4690 4691 4692 void Isolate::Exit() { 4693 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 4694 isolate->Exit(); 4695 } 4696 4697 4698 String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) { 4699 i::Isolate* isolate = i::Isolate::Current(); 4700 if (IsDeadCheck(isolate, "v8::String::Utf8Value::Utf8Value()")) return; 4701 if (obj.IsEmpty()) { 4702 str_ = NULL; 4703 length_ = 0; 4704 return; 4705 } 4706 ENTER_V8(isolate); 4707 i::HandleScope scope(isolate); 4708 TryCatch try_catch; 4709 Handle<String> str = obj->ToString(); 4710 if (str.IsEmpty()) { 4711 str_ = NULL; 4712 length_ = 0; 4713 } else { 4714 length_ = str->Utf8Length(); 4715 str_ = i::NewArray<char>(length_ + 1); 4716 str->WriteUtf8(str_); 4717 } 4718 } 4719 4720 4721 String::Utf8Value::~Utf8Value() { 4722 i::DeleteArray(str_); 4723 } 4724 4725 4726 String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) { 4727 i::Isolate* isolate = i::Isolate::Current(); 4728 if (IsDeadCheck(isolate, "v8::String::AsciiValue::AsciiValue()")) return; 4729 if (obj.IsEmpty()) { 4730 str_ = NULL; 4731 length_ = 0; 4732 return; 4733 } 4734 ENTER_V8(isolate); 4735 i::HandleScope scope(isolate); 4736 TryCatch try_catch; 4737 Handle<String> str = obj->ToString(); 4738 if (str.IsEmpty()) { 4739 str_ = NULL; 4740 length_ = 0; 4741 } else { 4742 length_ = str->Length(); 4743 str_ = i::NewArray<char>(length_ + 1); 4744 str->WriteAscii(str_); 4745 } 4746 } 4747 4748 4749 String::AsciiValue::~AsciiValue() { 4750 i::DeleteArray(str_); 4751 } 4752 4753 4754 String::Value::Value(v8::Handle<v8::Value> obj) { 4755 i::Isolate* isolate = i::Isolate::Current(); 4756 if (IsDeadCheck(isolate, "v8::String::Value::Value()")) return; 4757 if (obj.IsEmpty()) { 4758 str_ = NULL; 4759 length_ = 0; 4760 return; 4761 } 4762 ENTER_V8(isolate); 4763 i::HandleScope scope(isolate); 4764 TryCatch try_catch; 4765 Handle<String> str = obj->ToString(); 4766 if (str.IsEmpty()) { 4767 str_ = NULL; 4768 length_ = 0; 4769 } else { 4770 length_ = str->Length(); 4771 str_ = i::NewArray<uint16_t>(length_ + 1); 4772 str->Write(str_); 4773 } 4774 } 4775 4776 4777 String::Value::~Value() { 4778 i::DeleteArray(str_); 4779 } 4780 4781 Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) { 4782 i::Isolate* isolate = i::Isolate::Current(); 4783 LOG_API(isolate, "RangeError"); 4784 ON_BAILOUT(isolate, "v8::Exception::RangeError()", return Local<Value>()); 4785 ENTER_V8(isolate); 4786 i::Object* error; 4787 { 4788 i::HandleScope scope(isolate); 4789 i::Handle<i::String> message = Utils::OpenHandle(*raw_message); 4790 i::Handle<i::Object> result = isolate->factory()->NewRangeError(message); 4791 error = *result; 4792 } 4793 i::Handle<i::Object> result(error); 4794 return Utils::ToLocal(result); 4795 } 4796 4797 Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) { 4798 i::Isolate* isolate = i::Isolate::Current(); 4799 LOG_API(isolate, "ReferenceError"); 4800 ON_BAILOUT(isolate, "v8::Exception::ReferenceError()", return Local<Value>()); 4801 ENTER_V8(isolate); 4802 i::Object* error; 4803 { 4804 i::HandleScope scope(isolate); 4805 i::Handle<i::String> message = Utils::OpenHandle(*raw_message); 4806 i::Handle<i::Object> result = 4807 isolate->factory()->NewReferenceError(message); 4808 error = *result; 4809 } 4810 i::Handle<i::Object> result(error); 4811 return Utils::ToLocal(result); 4812 } 4813 4814 Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) { 4815 i::Isolate* isolate = i::Isolate::Current(); 4816 LOG_API(isolate, "SyntaxError"); 4817 ON_BAILOUT(isolate, "v8::Exception::SyntaxError()", return Local<Value>()); 4818 ENTER_V8(isolate); 4819 i::Object* error; 4820 { 4821 i::HandleScope scope(isolate); 4822 i::Handle<i::String> message = Utils::OpenHandle(*raw_message); 4823 i::Handle<i::Object> result = isolate->factory()->NewSyntaxError(message); 4824 error = *result; 4825 } 4826 i::Handle<i::Object> result(error); 4827 return Utils::ToLocal(result); 4828 } 4829 4830 Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) { 4831 i::Isolate* isolate = i::Isolate::Current(); 4832 LOG_API(isolate, "TypeError"); 4833 ON_BAILOUT(isolate, "v8::Exception::TypeError()", return Local<Value>()); 4834 ENTER_V8(isolate); 4835 i::Object* error; 4836 { 4837 i::HandleScope scope(isolate); 4838 i::Handle<i::String> message = Utils::OpenHandle(*raw_message); 4839 i::Handle<i::Object> result = isolate->factory()->NewTypeError(message); 4840 error = *result; 4841 } 4842 i::Handle<i::Object> result(error); 4843 return Utils::ToLocal(result); 4844 } 4845 4846 Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) { 4847 i::Isolate* isolate = i::Isolate::Current(); 4848 LOG_API(isolate, "Error"); 4849 ON_BAILOUT(isolate, "v8::Exception::Error()", return Local<Value>()); 4850 ENTER_V8(isolate); 4851 i::Object* error; 4852 { 4853 i::HandleScope scope(isolate); 4854 i::Handle<i::String> message = Utils::OpenHandle(*raw_message); 4855 i::Handle<i::Object> result = isolate->factory()->NewError(message); 4856 error = *result; 4857 } 4858 i::Handle<i::Object> result(error); 4859 return Utils::ToLocal(result); 4860 } 4861 4862 4863 // --- D e b u g S u p p o r t --- 4864 4865 #ifdef ENABLE_DEBUGGER_SUPPORT 4866 4867 static void EventCallbackWrapper(const v8::Debug::EventDetails& event_details) { 4868 i::Isolate* isolate = i::Isolate::Current(); 4869 if (isolate->debug_event_callback() != NULL) { 4870 isolate->debug_event_callback()(event_details.GetEvent(), 4871 event_details.GetExecutionState(), 4872 event_details.GetEventData(), 4873 event_details.GetCallbackData()); 4874 } 4875 } 4876 4877 4878 bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) { 4879 i::Isolate* isolate = i::Isolate::Current(); 4880 EnsureInitializedForIsolate(isolate, "v8::Debug::SetDebugEventListener()"); 4881 ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false); 4882 ENTER_V8(isolate); 4883 4884 isolate->set_debug_event_callback(that); 4885 4886 i::HandleScope scope(isolate); 4887 i::Handle<i::Object> proxy = isolate->factory()->undefined_value(); 4888 if (that != NULL) { 4889 proxy = isolate->factory()->NewProxy(FUNCTION_ADDR(EventCallbackWrapper)); 4890 } 4891 isolate->debugger()->SetEventListener(proxy, Utils::OpenHandle(*data)); 4892 return true; 4893 } 4894 4895 4896 bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) { 4897 i::Isolate* isolate = i::Isolate::Current(); 4898 EnsureInitializedForIsolate(isolate, "v8::Debug::SetDebugEventListener2()"); 4899 ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener2()", return false); 4900 ENTER_V8(isolate); 4901 i::HandleScope scope(isolate); 4902 i::Handle<i::Object> proxy = isolate->factory()->undefined_value(); 4903 if (that != NULL) { 4904 proxy = isolate->factory()->NewProxy(FUNCTION_ADDR(that)); 4905 } 4906 isolate->debugger()->SetEventListener(proxy, 4907 Utils::OpenHandle(*data)); 4908 return true; 4909 } 4910 4911 4912 bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that, 4913 Handle<Value> data) { 4914 i::Isolate* isolate = i::Isolate::Current(); 4915 ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false); 4916 ENTER_V8(isolate); 4917 isolate->debugger()->SetEventListener(Utils::OpenHandle(*that), 4918 Utils::OpenHandle(*data)); 4919 return true; 4920 } 4921 4922 4923 void Debug::DebugBreak(Isolate* isolate) { 4924 // If no isolate is supplied, use the default isolate. 4925 if (isolate != NULL) { 4926 reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->DebugBreak(); 4927 } else { 4928 i::Isolate::GetDefaultIsolateStackGuard()->DebugBreak(); 4929 } 4930 } 4931 4932 4933 void Debug::CancelDebugBreak(Isolate* isolate) { 4934 // If no isolate is supplied, use the default isolate. 4935 if (isolate != NULL) { 4936 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 4937 internal_isolate->stack_guard()->Continue(i::DEBUGBREAK); 4938 } else { 4939 i::Isolate::GetDefaultIsolateStackGuard()->Continue(i::DEBUGBREAK); 4940 } 4941 } 4942 4943 4944 void Debug::DebugBreakForCommand(ClientData* data, Isolate* isolate) { 4945 // If no isolate is supplied, use the default isolate. 4946 if (isolate != NULL) { 4947 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 4948 internal_isolate->debugger()->EnqueueDebugCommand(data); 4949 } else { 4950 i::Isolate::GetDefaultIsolateDebugger()->EnqueueDebugCommand(data); 4951 } 4952 } 4953 4954 4955 static void MessageHandlerWrapper(const v8::Debug::Message& message) { 4956 i::Isolate* isolate = i::Isolate::Current(); 4957 if (isolate->message_handler()) { 4958 v8::String::Value json(message.GetJSON()); 4959 (isolate->message_handler())(*json, json.length(), message.GetClientData()); 4960 } 4961 } 4962 4963 4964 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler, 4965 bool message_handler_thread) { 4966 i::Isolate* isolate = i::Isolate::Current(); 4967 EnsureInitializedForIsolate(isolate, "v8::Debug::SetMessageHandler"); 4968 ENTER_V8(isolate); 4969 4970 // Message handler thread not supported any more. Parameter temporally left in 4971 // the API for client compatibility reasons. 4972 CHECK(!message_handler_thread); 4973 4974 // TODO(sgjesse) support the old message handler API through a simple wrapper. 4975 isolate->set_message_handler(handler); 4976 if (handler != NULL) { 4977 isolate->debugger()->SetMessageHandler(MessageHandlerWrapper); 4978 } else { 4979 isolate->debugger()->SetMessageHandler(NULL); 4980 } 4981 } 4982 4983 4984 void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) { 4985 i::Isolate* isolate = i::Isolate::Current(); 4986 EnsureInitializedForIsolate(isolate, "v8::Debug::SetMessageHandler"); 4987 ENTER_V8(isolate); 4988 isolate->debugger()->SetMessageHandler(handler); 4989 } 4990 4991 4992 void Debug::SendCommand(const uint16_t* command, int length, 4993 ClientData* client_data, 4994 Isolate* isolate) { 4995 // If no isolate is supplied, use the default isolate. 4996 if (isolate != NULL) { 4997 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 4998 internal_isolate->debugger()->ProcessCommand( 4999 i::Vector<const uint16_t>(command, length), client_data); 5000 } else { 5001 i::Isolate::GetDefaultIsolateDebugger()->ProcessCommand( 5002 i::Vector<const uint16_t>(command, length), client_data); 5003 } 5004 } 5005 5006 5007 void Debug::SetHostDispatchHandler(HostDispatchHandler handler, 5008 int period) { 5009 i::Isolate* isolate = i::Isolate::Current(); 5010 EnsureInitializedForIsolate(isolate, "v8::Debug::SetHostDispatchHandler"); 5011 ENTER_V8(isolate); 5012 isolate->debugger()->SetHostDispatchHandler(handler, period); 5013 } 5014 5015 5016 void Debug::SetDebugMessageDispatchHandler( 5017 DebugMessageDispatchHandler handler, bool provide_locker) { 5018 i::Isolate* isolate = i::Isolate::Current(); 5019 EnsureInitializedForIsolate(isolate, 5020 "v8::Debug::SetDebugMessageDispatchHandler"); 5021 ENTER_V8(isolate); 5022 isolate->debugger()->SetDebugMessageDispatchHandler( 5023 handler, provide_locker); 5024 } 5025 5026 5027 Local<Value> Debug::Call(v8::Handle<v8::Function> fun, 5028 v8::Handle<v8::Value> data) { 5029 i::Isolate* isolate = i::Isolate::Current(); 5030 if (!isolate->IsInitialized()) return Local<Value>(); 5031 ON_BAILOUT(isolate, "v8::Debug::Call()", return Local<Value>()); 5032 ENTER_V8(isolate); 5033 i::Handle<i::Object> result; 5034 EXCEPTION_PREAMBLE(isolate); 5035 if (data.IsEmpty()) { 5036 result = isolate->debugger()->Call(Utils::OpenHandle(*fun), 5037 isolate->factory()->undefined_value(), 5038 &has_pending_exception); 5039 } else { 5040 result = isolate->debugger()->Call(Utils::OpenHandle(*fun), 5041 Utils::OpenHandle(*data), 5042 &has_pending_exception); 5043 } 5044 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 5045 return Utils::ToLocal(result); 5046 } 5047 5048 5049 Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) { 5050 i::Isolate* isolate = i::Isolate::Current(); 5051 if (!isolate->IsInitialized()) return Local<Value>(); 5052 ON_BAILOUT(isolate, "v8::Debug::GetMirror()", return Local<Value>()); 5053 ENTER_V8(isolate); 5054 v8::HandleScope scope; 5055 i::Debug* isolate_debug = isolate->debug(); 5056 isolate_debug->Load(); 5057 i::Handle<i::JSObject> debug(isolate_debug->debug_context()->global()); 5058 i::Handle<i::String> name = 5059 isolate->factory()->LookupAsciiSymbol("MakeMirror"); 5060 i::Handle<i::Object> fun_obj = i::GetProperty(debug, name); 5061 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj); 5062 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun); 5063 const int kArgc = 1; 5064 v8::Handle<v8::Value> argv[kArgc] = { obj }; 5065 EXCEPTION_PREAMBLE(isolate); 5066 v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug), 5067 kArgc, 5068 argv); 5069 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 5070 return scope.Close(result); 5071 } 5072 5073 5074 bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) { 5075 return i::Isolate::Current()->debugger()->StartAgent(name, port, 5076 wait_for_connection); 5077 } 5078 5079 void Debug::ProcessDebugMessages() { 5080 i::Execution::ProcessDebugMesssages(true); 5081 } 5082 5083 Local<Context> Debug::GetDebugContext() { 5084 i::Isolate* isolate = i::Isolate::Current(); 5085 EnsureInitializedForIsolate(isolate, "v8::Debug::GetDebugContext()"); 5086 ENTER_V8(isolate); 5087 return Utils::ToLocal(i::Isolate::Current()->debugger()->GetDebugContext()); 5088 } 5089 5090 #endif // ENABLE_DEBUGGER_SUPPORT 5091 5092 5093 #ifdef ENABLE_LOGGING_AND_PROFILING 5094 5095 Handle<String> CpuProfileNode::GetFunctionName() const { 5096 i::Isolate* isolate = i::Isolate::Current(); 5097 IsDeadCheck(isolate, "v8::CpuProfileNode::GetFunctionName"); 5098 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this); 5099 const i::CodeEntry* entry = node->entry(); 5100 if (!entry->has_name_prefix()) { 5101 return Handle<String>(ToApi<String>( 5102 isolate->factory()->LookupAsciiSymbol(entry->name()))); 5103 } else { 5104 return Handle<String>(ToApi<String>(isolate->factory()->NewConsString( 5105 isolate->factory()->LookupAsciiSymbol(entry->name_prefix()), 5106 isolate->factory()->LookupAsciiSymbol(entry->name())))); 5107 } 5108 } 5109 5110 5111 Handle<String> CpuProfileNode::GetScriptResourceName() const { 5112 i::Isolate* isolate = i::Isolate::Current(); 5113 IsDeadCheck(isolate, "v8::CpuProfileNode::GetScriptResourceName"); 5114 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this); 5115 return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol( 5116 node->entry()->resource_name()))); 5117 } 5118 5119 5120 int CpuProfileNode::GetLineNumber() const { 5121 i::Isolate* isolate = i::Isolate::Current(); 5122 IsDeadCheck(isolate, "v8::CpuProfileNode::GetLineNumber"); 5123 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number(); 5124 } 5125 5126 5127 double CpuProfileNode::GetTotalTime() const { 5128 i::Isolate* isolate = i::Isolate::Current(); 5129 IsDeadCheck(isolate, "v8::CpuProfileNode::GetTotalTime"); 5130 return reinterpret_cast<const i::ProfileNode*>(this)->GetTotalMillis(); 5131 } 5132 5133 5134 double CpuProfileNode::GetSelfTime() const { 5135 i::Isolate* isolate = i::Isolate::Current(); 5136 IsDeadCheck(isolate, "v8::CpuProfileNode::GetSelfTime"); 5137 return reinterpret_cast<const i::ProfileNode*>(this)->GetSelfMillis(); 5138 } 5139 5140 5141 double CpuProfileNode::GetTotalSamplesCount() const { 5142 i::Isolate* isolate = i::Isolate::Current(); 5143 IsDeadCheck(isolate, "v8::CpuProfileNode::GetTotalSamplesCount"); 5144 return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks(); 5145 } 5146 5147 5148 double CpuProfileNode::GetSelfSamplesCount() const { 5149 i::Isolate* isolate = i::Isolate::Current(); 5150 IsDeadCheck(isolate, "v8::CpuProfileNode::GetSelfSamplesCount"); 5151 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks(); 5152 } 5153 5154 5155 unsigned CpuProfileNode::GetCallUid() const { 5156 i::Isolate* isolate = i::Isolate::Current(); 5157 IsDeadCheck(isolate, "v8::CpuProfileNode::GetCallUid"); 5158 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid(); 5159 } 5160 5161 5162 int CpuProfileNode::GetChildrenCount() const { 5163 i::Isolate* isolate = i::Isolate::Current(); 5164 IsDeadCheck(isolate, "v8::CpuProfileNode::GetChildrenCount"); 5165 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length(); 5166 } 5167 5168 5169 const CpuProfileNode* CpuProfileNode::GetChild(int index) const { 5170 i::Isolate* isolate = i::Isolate::Current(); 5171 IsDeadCheck(isolate, "v8::CpuProfileNode::GetChild"); 5172 const i::ProfileNode* child = 5173 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index); 5174 return reinterpret_cast<const CpuProfileNode*>(child); 5175 } 5176 5177 5178 void CpuProfile::Delete() { 5179 i::Isolate* isolate = i::Isolate::Current(); 5180 IsDeadCheck(isolate, "v8::CpuProfile::Delete"); 5181 i::CpuProfiler::DeleteProfile(reinterpret_cast<i::CpuProfile*>(this)); 5182 if (i::CpuProfiler::GetProfilesCount() == 0 && 5183 !i::CpuProfiler::HasDetachedProfiles()) { 5184 // If this was the last profile, clean up all accessory data as well. 5185 i::CpuProfiler::DeleteAllProfiles(); 5186 } 5187 } 5188 5189 5190 unsigned CpuProfile::GetUid() const { 5191 i::Isolate* isolate = i::Isolate::Current(); 5192 IsDeadCheck(isolate, "v8::CpuProfile::GetUid"); 5193 return reinterpret_cast<const i::CpuProfile*>(this)->uid(); 5194 } 5195 5196 5197 Handle<String> CpuProfile::GetTitle() const { 5198 i::Isolate* isolate = i::Isolate::Current(); 5199 IsDeadCheck(isolate, "v8::CpuProfile::GetTitle"); 5200 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this); 5201 return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol( 5202 profile->title()))); 5203 } 5204 5205 5206 const CpuProfileNode* CpuProfile::GetBottomUpRoot() const { 5207 i::Isolate* isolate = i::Isolate::Current(); 5208 IsDeadCheck(isolate, "v8::CpuProfile::GetBottomUpRoot"); 5209 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this); 5210 return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root()); 5211 } 5212 5213 5214 const CpuProfileNode* CpuProfile::GetTopDownRoot() const { 5215 i::Isolate* isolate = i::Isolate::Current(); 5216 IsDeadCheck(isolate, "v8::CpuProfile::GetTopDownRoot"); 5217 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this); 5218 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root()); 5219 } 5220 5221 5222 int CpuProfiler::GetProfilesCount() { 5223 i::Isolate* isolate = i::Isolate::Current(); 5224 IsDeadCheck(isolate, "v8::CpuProfiler::GetProfilesCount"); 5225 return i::CpuProfiler::GetProfilesCount(); 5226 } 5227 5228 5229 const CpuProfile* CpuProfiler::GetProfile(int index, 5230 Handle<Value> security_token) { 5231 i::Isolate* isolate = i::Isolate::Current(); 5232 IsDeadCheck(isolate, "v8::CpuProfiler::GetProfile"); 5233 return reinterpret_cast<const CpuProfile*>( 5234 i::CpuProfiler::GetProfile( 5235 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token), 5236 index)); 5237 } 5238 5239 5240 const CpuProfile* CpuProfiler::FindProfile(unsigned uid, 5241 Handle<Value> security_token) { 5242 i::Isolate* isolate = i::Isolate::Current(); 5243 IsDeadCheck(isolate, "v8::CpuProfiler::FindProfile"); 5244 return reinterpret_cast<const CpuProfile*>( 5245 i::CpuProfiler::FindProfile( 5246 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token), 5247 uid)); 5248 } 5249 5250 5251 void CpuProfiler::StartProfiling(Handle<String> title) { 5252 i::Isolate* isolate = i::Isolate::Current(); 5253 IsDeadCheck(isolate, "v8::CpuProfiler::StartProfiling"); 5254 i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title)); 5255 } 5256 5257 5258 const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title, 5259 Handle<Value> security_token) { 5260 i::Isolate* isolate = i::Isolate::Current(); 5261 IsDeadCheck(isolate, "v8::CpuProfiler::StopProfiling"); 5262 return reinterpret_cast<const CpuProfile*>( 5263 i::CpuProfiler::StopProfiling( 5264 security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token), 5265 *Utils::OpenHandle(*title))); 5266 } 5267 5268 5269 void CpuProfiler::DeleteAllProfiles() { 5270 i::Isolate* isolate = i::Isolate::Current(); 5271 IsDeadCheck(isolate, "v8::CpuProfiler::DeleteAllProfiles"); 5272 i::CpuProfiler::DeleteAllProfiles(); 5273 } 5274 5275 5276 static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) { 5277 return const_cast<i::HeapGraphEdge*>( 5278 reinterpret_cast<const i::HeapGraphEdge*>(edge)); 5279 } 5280 5281 HeapGraphEdge::Type HeapGraphEdge::GetType() const { 5282 i::Isolate* isolate = i::Isolate::Current(); 5283 IsDeadCheck(isolate, "v8::HeapGraphEdge::GetType"); 5284 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type()); 5285 } 5286 5287 5288 Handle<Value> HeapGraphEdge::GetName() const { 5289 i::Isolate* isolate = i::Isolate::Current(); 5290 IsDeadCheck(isolate, "v8::HeapGraphEdge::GetName"); 5291 i::HeapGraphEdge* edge = ToInternal(this); 5292 switch (edge->type()) { 5293 case i::HeapGraphEdge::kContextVariable: 5294 case i::HeapGraphEdge::kInternal: 5295 case i::HeapGraphEdge::kProperty: 5296 case i::HeapGraphEdge::kShortcut: 5297 return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol( 5298 edge->name()))); 5299 case i::HeapGraphEdge::kElement: 5300 case i::HeapGraphEdge::kHidden: 5301 return Handle<Number>(ToApi<Number>(isolate->factory()->NewNumberFromInt( 5302 edge->index()))); 5303 default: UNREACHABLE(); 5304 } 5305 return v8::Undefined(); 5306 } 5307 5308 5309 const HeapGraphNode* HeapGraphEdge::GetFromNode() const { 5310 i::Isolate* isolate = i::Isolate::Current(); 5311 IsDeadCheck(isolate, "v8::HeapGraphEdge::GetFromNode"); 5312 const i::HeapEntry* from = ToInternal(this)->From(); 5313 return reinterpret_cast<const HeapGraphNode*>(from); 5314 } 5315 5316 5317 const HeapGraphNode* HeapGraphEdge::GetToNode() const { 5318 i::Isolate* isolate = i::Isolate::Current(); 5319 IsDeadCheck(isolate, "v8::HeapGraphEdge::GetToNode"); 5320 const i::HeapEntry* to = ToInternal(this)->to(); 5321 return reinterpret_cast<const HeapGraphNode*>(to); 5322 } 5323 5324 5325 static i::HeapEntry* ToInternal(const HeapGraphNode* entry) { 5326 return const_cast<i::HeapEntry*>( 5327 reinterpret_cast<const i::HeapEntry*>(entry)); 5328 } 5329 5330 5331 HeapGraphNode::Type HeapGraphNode::GetType() const { 5332 i::Isolate* isolate = i::Isolate::Current(); 5333 IsDeadCheck(isolate, "v8::HeapGraphNode::GetType"); 5334 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type()); 5335 } 5336 5337 5338 Handle<String> HeapGraphNode::GetName() const { 5339 i::Isolate* isolate = i::Isolate::Current(); 5340 IsDeadCheck(isolate, "v8::HeapGraphNode::GetName"); 5341 return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol( 5342 ToInternal(this)->name()))); 5343 } 5344 5345 5346 uint64_t HeapGraphNode::GetId() const { 5347 i::Isolate* isolate = i::Isolate::Current(); 5348 IsDeadCheck(isolate, "v8::HeapGraphNode::GetId"); 5349 ASSERT(ToInternal(this)->snapshot()->type() != i::HeapSnapshot::kAggregated); 5350 return ToInternal(this)->id(); 5351 } 5352 5353 5354 int HeapGraphNode::GetInstancesCount() const { 5355 i::Isolate* isolate = i::Isolate::Current(); 5356 IsDeadCheck(isolate, "v8::HeapGraphNode::GetInstancesCount"); 5357 ASSERT(ToInternal(this)->snapshot()->type() == i::HeapSnapshot::kAggregated); 5358 return static_cast<int>(ToInternal(this)->id()); 5359 } 5360 5361 5362 int HeapGraphNode::GetSelfSize() const { 5363 i::Isolate* isolate = i::Isolate::Current(); 5364 IsDeadCheck(isolate, "v8::HeapGraphNode::GetSelfSize"); 5365 return ToInternal(this)->self_size(); 5366 } 5367 5368 5369 int HeapGraphNode::GetRetainedSize(bool exact) const { 5370 i::Isolate* isolate = i::Isolate::Current(); 5371 IsDeadCheck(isolate, "v8::HeapSnapshot::GetRetainedSize"); 5372 return ToInternal(this)->RetainedSize(exact); 5373 } 5374 5375 5376 int HeapGraphNode::GetChildrenCount() const { 5377 i::Isolate* isolate = i::Isolate::Current(); 5378 IsDeadCheck(isolate, "v8::HeapSnapshot::GetChildrenCount"); 5379 return ToInternal(this)->children().length(); 5380 } 5381 5382 5383 const HeapGraphEdge* HeapGraphNode::GetChild(int index) const { 5384 i::Isolate* isolate = i::Isolate::Current(); 5385 IsDeadCheck(isolate, "v8::HeapSnapshot::GetChild"); 5386 return reinterpret_cast<const HeapGraphEdge*>( 5387 &ToInternal(this)->children()[index]); 5388 } 5389 5390 5391 int HeapGraphNode::GetRetainersCount() const { 5392 i::Isolate* isolate = i::Isolate::Current(); 5393 IsDeadCheck(isolate, "v8::HeapSnapshot::GetRetainersCount"); 5394 return ToInternal(this)->retainers().length(); 5395 } 5396 5397 5398 const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const { 5399 i::Isolate* isolate = i::Isolate::Current(); 5400 IsDeadCheck(isolate, "v8::HeapSnapshot::GetRetainer"); 5401 return reinterpret_cast<const HeapGraphEdge*>( 5402 ToInternal(this)->retainers()[index]); 5403 } 5404 5405 5406 const HeapGraphNode* HeapGraphNode::GetDominatorNode() const { 5407 i::Isolate* isolate = i::Isolate::Current(); 5408 IsDeadCheck(isolate, "v8::HeapSnapshot::GetDominatorNode"); 5409 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->dominator()); 5410 } 5411 5412 5413 static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) { 5414 return const_cast<i::HeapSnapshot*>( 5415 reinterpret_cast<const i::HeapSnapshot*>(snapshot)); 5416 } 5417 5418 5419 void HeapSnapshot::Delete() { 5420 i::Isolate* isolate = i::Isolate::Current(); 5421 IsDeadCheck(isolate, "v8::HeapSnapshot::Delete"); 5422 if (i::HeapProfiler::GetSnapshotsCount() > 1) { 5423 ToInternal(this)->Delete(); 5424 } else { 5425 // If this is the last snapshot, clean up all accessory data as well. 5426 i::HeapProfiler::DeleteAllSnapshots(); 5427 } 5428 } 5429 5430 5431 HeapSnapshot::Type HeapSnapshot::GetType() const { 5432 i::Isolate* isolate = i::Isolate::Current(); 5433 IsDeadCheck(isolate, "v8::HeapSnapshot::GetType"); 5434 return static_cast<HeapSnapshot::Type>(ToInternal(this)->type()); 5435 } 5436 5437 5438 unsigned HeapSnapshot::GetUid() const { 5439 i::Isolate* isolate = i::Isolate::Current(); 5440 IsDeadCheck(isolate, "v8::HeapSnapshot::GetUid"); 5441 return ToInternal(this)->uid(); 5442 } 5443 5444 5445 Handle<String> HeapSnapshot::GetTitle() const { 5446 i::Isolate* isolate = i::Isolate::Current(); 5447 IsDeadCheck(isolate, "v8::HeapSnapshot::GetTitle"); 5448 return Handle<String>(ToApi<String>(isolate->factory()->LookupAsciiSymbol( 5449 ToInternal(this)->title()))); 5450 } 5451 5452 5453 const HeapGraphNode* HeapSnapshot::GetRoot() const { 5454 i::Isolate* isolate = i::Isolate::Current(); 5455 IsDeadCheck(isolate, "v8::HeapSnapshot::GetHead"); 5456 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root()); 5457 } 5458 5459 5460 const HeapGraphNode* HeapSnapshot::GetNodeById(uint64_t id) const { 5461 i::Isolate* isolate = i::Isolate::Current(); 5462 IsDeadCheck(isolate, "v8::HeapSnapshot::GetNodeById"); 5463 return reinterpret_cast<const HeapGraphNode*>( 5464 ToInternal(this)->GetEntryById(id)); 5465 } 5466 5467 5468 void HeapSnapshot::Serialize(OutputStream* stream, 5469 HeapSnapshot::SerializationFormat format) const { 5470 i::Isolate* isolate = i::Isolate::Current(); 5471 IsDeadCheck(isolate, "v8::HeapSnapshot::Serialize"); 5472 ApiCheck(format == kJSON, 5473 "v8::HeapSnapshot::Serialize", 5474 "Unknown serialization format"); 5475 ApiCheck(stream->GetOutputEncoding() == OutputStream::kAscii, 5476 "v8::HeapSnapshot::Serialize", 5477 "Unsupported output encoding"); 5478 ApiCheck(stream->GetChunkSize() > 0, 5479 "v8::HeapSnapshot::Serialize", 5480 "Invalid stream chunk size"); 5481 i::HeapSnapshotJSONSerializer serializer(ToInternal(this)); 5482 serializer.Serialize(stream); 5483 } 5484 5485 5486 int HeapProfiler::GetSnapshotsCount() { 5487 i::Isolate* isolate = i::Isolate::Current(); 5488 IsDeadCheck(isolate, "v8::HeapProfiler::GetSnapshotsCount"); 5489 return i::HeapProfiler::GetSnapshotsCount(); 5490 } 5491 5492 5493 const HeapSnapshot* HeapProfiler::GetSnapshot(int index) { 5494 i::Isolate* isolate = i::Isolate::Current(); 5495 IsDeadCheck(isolate, "v8::HeapProfiler::GetSnapshot"); 5496 return reinterpret_cast<const HeapSnapshot*>( 5497 i::HeapProfiler::GetSnapshot(index)); 5498 } 5499 5500 5501 const HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) { 5502 i::Isolate* isolate = i::Isolate::Current(); 5503 IsDeadCheck(isolate, "v8::HeapProfiler::FindSnapshot"); 5504 return reinterpret_cast<const HeapSnapshot*>( 5505 i::HeapProfiler::FindSnapshot(uid)); 5506 } 5507 5508 5509 const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title, 5510 HeapSnapshot::Type type, 5511 ActivityControl* control) { 5512 i::Isolate* isolate = i::Isolate::Current(); 5513 IsDeadCheck(isolate, "v8::HeapProfiler::TakeSnapshot"); 5514 i::HeapSnapshot::Type internal_type = i::HeapSnapshot::kFull; 5515 switch (type) { 5516 case HeapSnapshot::kFull: 5517 internal_type = i::HeapSnapshot::kFull; 5518 break; 5519 case HeapSnapshot::kAggregated: 5520 internal_type = i::HeapSnapshot::kAggregated; 5521 break; 5522 default: 5523 UNREACHABLE(); 5524 } 5525 return reinterpret_cast<const HeapSnapshot*>( 5526 i::HeapProfiler::TakeSnapshot( 5527 *Utils::OpenHandle(*title), internal_type, control)); 5528 } 5529 5530 5531 void HeapProfiler::DeleteAllSnapshots() { 5532 i::Isolate* isolate = i::Isolate::Current(); 5533 IsDeadCheck(isolate, "v8::HeapProfiler::DeleteAllSnapshots"); 5534 i::HeapProfiler::DeleteAllSnapshots(); 5535 } 5536 5537 5538 void HeapProfiler::DefineWrapperClass(uint16_t class_id, 5539 WrapperInfoCallback callback) { 5540 i::Isolate::Current()->heap_profiler()->DefineWrapperClass(class_id, 5541 callback); 5542 } 5543 5544 #endif // ENABLE_LOGGING_AND_PROFILING 5545 5546 5547 v8::Testing::StressType internal::Testing::stress_type_ = 5548 v8::Testing::kStressTypeOpt; 5549 5550 5551 void Testing::SetStressRunType(Testing::StressType type) { 5552 internal::Testing::set_stress_type(type); 5553 } 5554 5555 int Testing::GetStressRuns() { 5556 if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs; 5557 #ifdef DEBUG 5558 // In debug mode the code runs much slower so stressing will only make two 5559 // runs. 5560 return 2; 5561 #else 5562 return 5; 5563 #endif 5564 } 5565 5566 5567 static void SetFlagsFromString(const char* flags) { 5568 V8::SetFlagsFromString(flags, i::StrLength(flags)); 5569 } 5570 5571 5572 void Testing::PrepareStressRun(int run) { 5573 static const char* kLazyOptimizations = 5574 "--prepare-always-opt --nolimit-inlining " 5575 "--noalways-opt --noopt-eagerly"; 5576 static const char* kEagerOptimizations = "--opt-eagerly"; 5577 static const char* kForcedOptimizations = "--always-opt"; 5578 5579 // If deoptimization stressed turn on frequent deoptimization. If no value 5580 // is spefified through --deopt-every-n-times use a default default value. 5581 static const char* kDeoptEvery13Times = "--deopt-every-n-times=13"; 5582 if (internal::Testing::stress_type() == Testing::kStressTypeDeopt && 5583 internal::FLAG_deopt_every_n_times == 0) { 5584 SetFlagsFromString(kDeoptEvery13Times); 5585 } 5586 5587 #ifdef DEBUG 5588 // As stressing in debug mode only make two runs skip the deopt stressing 5589 // here. 5590 if (run == GetStressRuns() - 1) { 5591 SetFlagsFromString(kForcedOptimizations); 5592 } else { 5593 SetFlagsFromString(kEagerOptimizations); 5594 SetFlagsFromString(kLazyOptimizations); 5595 } 5596 #else 5597 if (run == GetStressRuns() - 1) { 5598 SetFlagsFromString(kForcedOptimizations); 5599 } else if (run == GetStressRuns() - 2) { 5600 SetFlagsFromString(kEagerOptimizations); 5601 } else { 5602 SetFlagsFromString(kLazyOptimizations); 5603 } 5604 #endif 5605 } 5606 5607 5608 void Testing::DeoptimizeAll() { 5609 internal::Deoptimizer::DeoptimizeAll(); 5610 } 5611 5612 5613 namespace internal { 5614 5615 5616 void HandleScopeImplementer::FreeThreadResources() { 5617 Free(); 5618 } 5619 5620 5621 char* HandleScopeImplementer::ArchiveThread(char* storage) { 5622 Isolate* isolate = Isolate::Current(); 5623 v8::ImplementationUtilities::HandleScopeData* current = 5624 isolate->handle_scope_data(); 5625 handle_scope_data_ = *current; 5626 memcpy(storage, this, sizeof(*this)); 5627 5628 ResetAfterArchive(); 5629 current->Initialize(); 5630 5631 return storage + ArchiveSpacePerThread(); 5632 } 5633 5634 5635 int HandleScopeImplementer::ArchiveSpacePerThread() { 5636 return sizeof(HandleScopeImplementer); 5637 } 5638 5639 5640 char* HandleScopeImplementer::RestoreThread(char* storage) { 5641 memcpy(this, storage, sizeof(*this)); 5642 *Isolate::Current()->handle_scope_data() = handle_scope_data_; 5643 return storage + ArchiveSpacePerThread(); 5644 } 5645 5646 5647 void HandleScopeImplementer::IterateThis(ObjectVisitor* v) { 5648 // Iterate over all handles in the blocks except for the last. 5649 for (int i = blocks()->length() - 2; i >= 0; --i) { 5650 Object** block = blocks()->at(i); 5651 v->VisitPointers(block, &block[kHandleBlockSize]); 5652 } 5653 5654 // Iterate over live handles in the last block (if any). 5655 if (!blocks()->is_empty()) { 5656 v->VisitPointers(blocks()->last(), handle_scope_data_.next); 5657 } 5658 5659 if (!saved_contexts_.is_empty()) { 5660 Object** start = reinterpret_cast<Object**>(&saved_contexts_.first()); 5661 v->VisitPointers(start, start + saved_contexts_.length()); 5662 } 5663 } 5664 5665 5666 void HandleScopeImplementer::Iterate(ObjectVisitor* v) { 5667 v8::ImplementationUtilities::HandleScopeData* current = 5668 Isolate::Current()->handle_scope_data(); 5669 handle_scope_data_ = *current; 5670 IterateThis(v); 5671 } 5672 5673 5674 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) { 5675 HandleScopeImplementer* scope_implementer = 5676 reinterpret_cast<HandleScopeImplementer*>(storage); 5677 scope_implementer->IterateThis(v); 5678 return storage + ArchiveSpacePerThread(); 5679 } 5680 5681 } } // namespace v8::internal 5682