1 // Copyright 2012 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 "api.h" 29 30 #include <string.h> // For memcpy, strlen. 31 #include <cmath> // For isnan. 32 #include "../include/v8-debug.h" 33 #include "../include/v8-profiler.h" 34 #include "../include/v8-testing.h" 35 #include "assert-scope.h" 36 #include "bootstrapper.h" 37 #include "code-stubs.h" 38 #include "compiler.h" 39 #include "conversions-inl.h" 40 #include "counters.h" 41 #include "cpu-profiler.h" 42 #include "debug.h" 43 #include "deoptimizer.h" 44 #include "execution.h" 45 #include "global-handles.h" 46 #include "heap-profiler.h" 47 #include "heap-snapshot-generator-inl.h" 48 #include "icu_util.h" 49 #include "json-parser.h" 50 #include "messages.h" 51 #ifdef COMPRESS_STARTUP_DATA_BZ2 52 #include "natives.h" 53 #endif 54 #include "parser.h" 55 #include "platform.h" 56 #include "platform/time.h" 57 #include "profile-generator-inl.h" 58 #include "property-details.h" 59 #include "property.h" 60 #include "runtime.h" 61 #include "runtime-profiler.h" 62 #include "scanner-character-streams.h" 63 #include "snapshot.h" 64 #include "unicode-inl.h" 65 #include "utils/random-number-generator.h" 66 #include "v8threads.h" 67 #include "version.h" 68 #include "vm-state-inl.h" 69 70 71 #define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr)) 72 73 #define ENTER_V8(isolate) \ 74 ASSERT((isolate)->IsInitialized()); \ 75 i::VMState<i::OTHER> __state__((isolate)) 76 77 namespace v8 { 78 79 #define ON_BAILOUT(isolate, location, code) \ 80 if (IsExecutionTerminatingCheck(isolate)) { \ 81 code; \ 82 UNREACHABLE(); \ 83 } 84 85 86 #define EXCEPTION_PREAMBLE(isolate) \ 87 (isolate)->handle_scope_implementer()->IncrementCallDepth(); \ 88 ASSERT(!(isolate)->external_caught_exception()); \ 89 bool has_pending_exception = false 90 91 92 #define EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, do_callback) \ 93 do { \ 94 i::HandleScopeImplementer* handle_scope_implementer = \ 95 (isolate)->handle_scope_implementer(); \ 96 handle_scope_implementer->DecrementCallDepth(); \ 97 if (has_pending_exception) { \ 98 if (handle_scope_implementer->CallDepthIsZero() && \ 99 (isolate)->is_out_of_memory()) { \ 100 if (!(isolate)->ignore_out_of_memory()) \ 101 i::V8::FatalProcessOutOfMemory(NULL); \ 102 } \ 103 bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero(); \ 104 (isolate)->OptionalRescheduleException(call_depth_is_zero); \ 105 do_callback \ 106 return value; \ 107 } \ 108 do_callback \ 109 } while (false) 110 111 112 #define EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, value) \ 113 EXCEPTION_BAILOUT_CHECK_GENERIC( \ 114 isolate, value, i::V8::FireCallCompletedCallback(isolate);) 115 116 117 #define EXCEPTION_BAILOUT_CHECK(isolate, value) \ 118 EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, ;) 119 120 121 #define API_ENTRY_CHECK(isolate, msg) \ 122 do { \ 123 if (v8::Locker::IsActive()) { \ 124 ApiCheck(isolate->thread_manager()->IsLockedByCurrentThread(), \ 125 msg, \ 126 "Entering the V8 API without proper locking in place"); \ 127 } \ 128 } while (false) 129 130 131 // --- E x c e p t i o n B e h a v i o r --- 132 133 134 static void DefaultFatalErrorHandler(const char* location, 135 const char* message) { 136 i::Isolate* isolate = i::Isolate::Current(); 137 if (isolate->IsInitialized()) { 138 i::VMState<i::OTHER> state(isolate); 139 API_Fatal(location, message); 140 } else { 141 API_Fatal(location, message); 142 } 143 } 144 145 146 static FatalErrorCallback GetFatalErrorHandler() { 147 i::Isolate* isolate = i::Isolate::Current(); 148 if (isolate->exception_behavior() == NULL) { 149 isolate->set_exception_behavior(DefaultFatalErrorHandler); 150 } 151 return isolate->exception_behavior(); 152 } 153 154 155 void i::FatalProcessOutOfMemory(const char* location) { 156 i::V8::FatalProcessOutOfMemory(location, false); 157 } 158 159 160 // When V8 cannot allocated memory FatalProcessOutOfMemory is called. 161 // The default fatal error handler is called and execution is stopped. 162 void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) { 163 i::HeapStats heap_stats; 164 int start_marker; 165 heap_stats.start_marker = &start_marker; 166 int new_space_size; 167 heap_stats.new_space_size = &new_space_size; 168 int new_space_capacity; 169 heap_stats.new_space_capacity = &new_space_capacity; 170 intptr_t old_pointer_space_size; 171 heap_stats.old_pointer_space_size = &old_pointer_space_size; 172 intptr_t old_pointer_space_capacity; 173 heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity; 174 intptr_t old_data_space_size; 175 heap_stats.old_data_space_size = &old_data_space_size; 176 intptr_t old_data_space_capacity; 177 heap_stats.old_data_space_capacity = &old_data_space_capacity; 178 intptr_t code_space_size; 179 heap_stats.code_space_size = &code_space_size; 180 intptr_t code_space_capacity; 181 heap_stats.code_space_capacity = &code_space_capacity; 182 intptr_t map_space_size; 183 heap_stats.map_space_size = &map_space_size; 184 intptr_t map_space_capacity; 185 heap_stats.map_space_capacity = &map_space_capacity; 186 intptr_t cell_space_size; 187 heap_stats.cell_space_size = &cell_space_size; 188 intptr_t cell_space_capacity; 189 heap_stats.cell_space_capacity = &cell_space_capacity; 190 intptr_t property_cell_space_size; 191 heap_stats.property_cell_space_size = &property_cell_space_size; 192 intptr_t property_cell_space_capacity; 193 heap_stats.property_cell_space_capacity = &property_cell_space_capacity; 194 intptr_t lo_space_size; 195 heap_stats.lo_space_size = &lo_space_size; 196 int global_handle_count; 197 heap_stats.global_handle_count = &global_handle_count; 198 int weak_global_handle_count; 199 heap_stats.weak_global_handle_count = &weak_global_handle_count; 200 int pending_global_handle_count; 201 heap_stats.pending_global_handle_count = &pending_global_handle_count; 202 int near_death_global_handle_count; 203 heap_stats.near_death_global_handle_count = &near_death_global_handle_count; 204 int free_global_handle_count; 205 heap_stats.free_global_handle_count = &free_global_handle_count; 206 intptr_t memory_allocator_size; 207 heap_stats.memory_allocator_size = &memory_allocator_size; 208 intptr_t memory_allocator_capacity; 209 heap_stats.memory_allocator_capacity = &memory_allocator_capacity; 210 int objects_per_type[LAST_TYPE + 1] = {0}; 211 heap_stats.objects_per_type = objects_per_type; 212 int size_per_type[LAST_TYPE + 1] = {0}; 213 heap_stats.size_per_type = size_per_type; 214 int os_error; 215 heap_stats.os_error = &os_error; 216 int end_marker; 217 heap_stats.end_marker = &end_marker; 218 i::Isolate* isolate = i::Isolate::Current(); 219 if (isolate->heap()->HasBeenSetUp()) { 220 // BUG(1718): Don't use the take_snapshot since we don't support 221 // HeapIterator here without doing a special GC. 222 isolate->heap()->RecordStats(&heap_stats, false); 223 } 224 isolate->SignalFatalError(); 225 FatalErrorCallback callback = GetFatalErrorHandler(); 226 const char* message = "Allocation failed - process out of memory"; 227 callback(location, message); 228 // If the callback returns, we stop execution. 229 FATAL("API fatal error handler returned after process out of memory"); 230 } 231 232 233 bool Utils::ReportApiFailure(const char* location, const char* message) { 234 FatalErrorCallback callback = GetFatalErrorHandler(); 235 callback(location, message); 236 i::Isolate* isolate = i::Isolate::Current(); 237 isolate->SignalFatalError(); 238 return false; 239 } 240 241 242 bool V8::IsDead() { 243 i::Isolate* isolate = i::Isolate::Current(); 244 return isolate->IsDead(); 245 } 246 247 248 static inline bool ApiCheck(bool condition, 249 const char* location, 250 const char* message) { 251 return condition ? true : Utils::ReportApiFailure(location, message); 252 } 253 254 255 static bool ReportEmptyHandle(const char* location) { 256 FatalErrorCallback callback = GetFatalErrorHandler(); 257 callback(location, "Reading from empty handle"); 258 return true; 259 } 260 261 262 static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) { 263 if (!isolate->IsInitialized()) return false; 264 if (isolate->has_scheduled_exception()) { 265 return isolate->scheduled_exception() == 266 isolate->heap()->termination_exception(); 267 } 268 return false; 269 } 270 271 272 static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) { 273 return obj.IsEmpty() ? ReportEmptyHandle(location) : false; 274 } 275 276 277 static inline bool EmptyCheck(const char* location, const v8::Data* obj) { 278 return (obj == 0) ? ReportEmptyHandle(location) : false; 279 } 280 281 282 // --- S t a t i c s --- 283 284 285 static bool InitializeHelper(i::Isolate* isolate) { 286 // If the isolate has a function entry hook, it needs to re-build all its 287 // code stubs with entry hooks embedded, so let's deserialize a snapshot. 288 if (isolate == NULL || isolate->function_entry_hook() == NULL) { 289 if (i::Snapshot::Initialize()) 290 return true; 291 } 292 return i::V8::Initialize(NULL); 293 } 294 295 296 static inline bool EnsureInitializedForIsolate(i::Isolate* isolate, 297 const char* location) { 298 if (isolate != NULL) { 299 if (isolate->IsInitialized()) return true; 300 } 301 ASSERT(isolate == i::Isolate::Current()); 302 return ApiCheck(InitializeHelper(isolate), location, "Error initializing V8"); 303 } 304 305 306 // Some initializing API functions are called early and may be 307 // called on a thread different from static initializer thread. 308 // If Isolate API is used, Isolate::Enter() will initialize TLS so 309 // Isolate::Current() works. If it's a legacy case, then the thread 310 // may not have TLS initialized yet. However, in initializing APIs it 311 // may be too early to call EnsureInitialized() - some pre-init 312 // parameters still have to be configured. 313 static inline i::Isolate* EnterIsolateIfNeeded() { 314 i::Isolate* isolate = i::Isolate::UncheckedCurrent(); 315 if (isolate != NULL) 316 return isolate; 317 318 i::Isolate::EnterDefaultIsolate(); 319 isolate = i::Isolate::Current(); 320 return isolate; 321 } 322 323 324 StartupDataDecompressor::StartupDataDecompressor() 325 : raw_data(i::NewArray<char*>(V8::GetCompressedStartupDataCount())) { 326 for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) { 327 raw_data[i] = NULL; 328 } 329 } 330 331 332 StartupDataDecompressor::~StartupDataDecompressor() { 333 for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) { 334 i::DeleteArray(raw_data[i]); 335 } 336 i::DeleteArray(raw_data); 337 } 338 339 340 int StartupDataDecompressor::Decompress() { 341 int compressed_data_count = V8::GetCompressedStartupDataCount(); 342 StartupData* compressed_data = 343 i::NewArray<StartupData>(compressed_data_count); 344 V8::GetCompressedStartupData(compressed_data); 345 for (int i = 0; i < compressed_data_count; ++i) { 346 char* decompressed = raw_data[i] = 347 i::NewArray<char>(compressed_data[i].raw_size); 348 if (compressed_data[i].compressed_size != 0) { 349 int result = DecompressData(decompressed, 350 &compressed_data[i].raw_size, 351 compressed_data[i].data, 352 compressed_data[i].compressed_size); 353 if (result != 0) return result; 354 } else { 355 ASSERT_EQ(0, compressed_data[i].raw_size); 356 } 357 compressed_data[i].data = decompressed; 358 } 359 V8::SetDecompressedStartupData(compressed_data); 360 i::DeleteArray(compressed_data); 361 return 0; 362 } 363 364 365 StartupData::CompressionAlgorithm V8::GetCompressedStartupDataAlgorithm() { 366 #ifdef COMPRESS_STARTUP_DATA_BZ2 367 return StartupData::kBZip2; 368 #else 369 return StartupData::kUncompressed; 370 #endif 371 } 372 373 374 enum CompressedStartupDataItems { 375 kSnapshot = 0, 376 kSnapshotContext, 377 kLibraries, 378 kExperimentalLibraries, 379 kCompressedStartupDataCount 380 }; 381 382 383 int V8::GetCompressedStartupDataCount() { 384 #ifdef COMPRESS_STARTUP_DATA_BZ2 385 return kCompressedStartupDataCount; 386 #else 387 return 0; 388 #endif 389 } 390 391 392 void V8::GetCompressedStartupData(StartupData* compressed_data) { 393 #ifdef COMPRESS_STARTUP_DATA_BZ2 394 compressed_data[kSnapshot].data = 395 reinterpret_cast<const char*>(i::Snapshot::data()); 396 compressed_data[kSnapshot].compressed_size = i::Snapshot::size(); 397 compressed_data[kSnapshot].raw_size = i::Snapshot::raw_size(); 398 399 compressed_data[kSnapshotContext].data = 400 reinterpret_cast<const char*>(i::Snapshot::context_data()); 401 compressed_data[kSnapshotContext].compressed_size = 402 i::Snapshot::context_size(); 403 compressed_data[kSnapshotContext].raw_size = i::Snapshot::context_raw_size(); 404 405 i::Vector<const i::byte> libraries_source = i::Natives::GetScriptsSource(); 406 compressed_data[kLibraries].data = 407 reinterpret_cast<const char*>(libraries_source.start()); 408 compressed_data[kLibraries].compressed_size = libraries_source.length(); 409 compressed_data[kLibraries].raw_size = i::Natives::GetRawScriptsSize(); 410 411 i::Vector<const i::byte> exp_libraries_source = 412 i::ExperimentalNatives::GetScriptsSource(); 413 compressed_data[kExperimentalLibraries].data = 414 reinterpret_cast<const char*>(exp_libraries_source.start()); 415 compressed_data[kExperimentalLibraries].compressed_size = 416 exp_libraries_source.length(); 417 compressed_data[kExperimentalLibraries].raw_size = 418 i::ExperimentalNatives::GetRawScriptsSize(); 419 #endif 420 } 421 422 423 void V8::SetDecompressedStartupData(StartupData* decompressed_data) { 424 #ifdef COMPRESS_STARTUP_DATA_BZ2 425 ASSERT_EQ(i::Snapshot::raw_size(), decompressed_data[kSnapshot].raw_size); 426 i::Snapshot::set_raw_data( 427 reinterpret_cast<const i::byte*>(decompressed_data[kSnapshot].data)); 428 429 ASSERT_EQ(i::Snapshot::context_raw_size(), 430 decompressed_data[kSnapshotContext].raw_size); 431 i::Snapshot::set_context_raw_data( 432 reinterpret_cast<const i::byte*>( 433 decompressed_data[kSnapshotContext].data)); 434 435 ASSERT_EQ(i::Natives::GetRawScriptsSize(), 436 decompressed_data[kLibraries].raw_size); 437 i::Vector<const char> libraries_source( 438 decompressed_data[kLibraries].data, 439 decompressed_data[kLibraries].raw_size); 440 i::Natives::SetRawScriptsSource(libraries_source); 441 442 ASSERT_EQ(i::ExperimentalNatives::GetRawScriptsSize(), 443 decompressed_data[kExperimentalLibraries].raw_size); 444 i::Vector<const char> exp_libraries_source( 445 decompressed_data[kExperimentalLibraries].data, 446 decompressed_data[kExperimentalLibraries].raw_size); 447 i::ExperimentalNatives::SetRawScriptsSource(exp_libraries_source); 448 #endif 449 } 450 451 452 void V8::SetFatalErrorHandler(FatalErrorCallback that) { 453 i::Isolate* isolate = EnterIsolateIfNeeded(); 454 isolate->set_exception_behavior(that); 455 } 456 457 458 void V8::SetAllowCodeGenerationFromStringsCallback( 459 AllowCodeGenerationFromStringsCallback callback) { 460 i::Isolate* isolate = EnterIsolateIfNeeded(); 461 isolate->set_allow_code_gen_callback(callback); 462 } 463 464 465 void V8::SetFlagsFromString(const char* str, int length) { 466 i::FlagList::SetFlagsFromString(str, length); 467 } 468 469 470 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) { 471 i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags); 472 } 473 474 475 v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) { 476 return v8::Isolate::GetCurrent()->ThrowException(value); 477 } 478 479 480 RegisteredExtension* RegisteredExtension::first_extension_ = NULL; 481 482 483 RegisteredExtension::RegisteredExtension(Extension* extension) 484 : extension_(extension) { } 485 486 487 void RegisteredExtension::Register(RegisteredExtension* that) { 488 that->next_ = first_extension_; 489 first_extension_ = that; 490 } 491 492 493 void RegisteredExtension::UnregisterAll() { 494 RegisteredExtension* re = first_extension_; 495 while (re != NULL) { 496 RegisteredExtension* next = re->next(); 497 delete re; 498 re = next; 499 } 500 } 501 502 503 void RegisterExtension(Extension* that) { 504 RegisteredExtension* extension = new RegisteredExtension(that); 505 RegisteredExtension::Register(extension); 506 } 507 508 509 Extension::Extension(const char* name, 510 const char* source, 511 int dep_count, 512 const char** deps, 513 int source_length) 514 : name_(name), 515 source_length_(source_length >= 0 ? 516 source_length : 517 (source ? static_cast<int>(strlen(source)) : 0)), 518 source_(source, source_length_), 519 dep_count_(dep_count), 520 deps_(deps), 521 auto_enable_(false) { 522 CHECK(source != NULL || source_length_ == 0); 523 } 524 525 526 v8::Handle<Primitive> Undefined() { 527 i::Isolate* isolate = i::Isolate::Current(); 528 if (!EnsureInitializedForIsolate(isolate, "v8::Undefined()")) { 529 return v8::Handle<v8::Primitive>(); 530 } 531 return ToApiHandle<Primitive>(isolate->factory()->undefined_value()); 532 } 533 534 535 v8::Handle<Primitive> Null() { 536 i::Isolate* isolate = i::Isolate::Current(); 537 if (!EnsureInitializedForIsolate(isolate, "v8::Null()")) { 538 return v8::Handle<v8::Primitive>(); 539 } 540 return ToApiHandle<Primitive>(isolate->factory()->null_value()); 541 } 542 543 544 v8::Handle<Boolean> True() { 545 i::Isolate* isolate = i::Isolate::Current(); 546 if (!EnsureInitializedForIsolate(isolate, "v8::True()")) { 547 return v8::Handle<Boolean>(); 548 } 549 return ToApiHandle<Boolean>(isolate->factory()->true_value()); 550 } 551 552 553 v8::Handle<Boolean> False() { 554 i::Isolate* isolate = i::Isolate::Current(); 555 if (!EnsureInitializedForIsolate(isolate, "v8::False()")) { 556 return v8::Handle<Boolean>(); 557 } 558 return ToApiHandle<Boolean>(isolate->factory()->false_value()); 559 } 560 561 562 ResourceConstraints::ResourceConstraints() 563 : max_young_space_size_(0), 564 max_old_space_size_(0), 565 max_executable_size_(0), 566 stack_limit_(NULL), 567 max_available_threads_(0) { } 568 569 void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory, 570 uint32_t number_of_processors) { 571 const int lump_of_memory = (i::kPointerSize / 4) * i::MB; 572 #if V8_OS_ANDROID 573 // Android has higher physical memory requirements before raising the maximum 574 // heap size limits since it has no swap space. 575 const uint64_t low_limit = 512ul * i::MB; 576 const uint64_t medium_limit = 1ul * i::GB; 577 const uint64_t high_limit = 2ul * i::GB; 578 #else 579 const uint64_t low_limit = 512ul * i::MB; 580 const uint64_t medium_limit = 768ul * i::MB; 581 const uint64_t high_limit = 1ul * i::GB; 582 #endif 583 584 // The young_space_size should be a power of 2 and old_generation_size should 585 // be a multiple of Page::kPageSize. 586 if (physical_memory <= low_limit) { 587 set_max_young_space_size(2 * lump_of_memory); 588 set_max_old_space_size(128 * lump_of_memory); 589 set_max_executable_size(96 * lump_of_memory); 590 } else if (physical_memory <= medium_limit) { 591 set_max_young_space_size(8 * lump_of_memory); 592 set_max_old_space_size(256 * lump_of_memory); 593 set_max_executable_size(192 * lump_of_memory); 594 } else if (physical_memory <= high_limit) { 595 set_max_young_space_size(16 * lump_of_memory); 596 set_max_old_space_size(512 * lump_of_memory); 597 set_max_executable_size(256 * lump_of_memory); 598 } else { 599 set_max_young_space_size(16 * lump_of_memory); 600 set_max_old_space_size(700 * lump_of_memory); 601 set_max_executable_size(256 * lump_of_memory); 602 } 603 604 set_max_available_threads(i::Max(i::Min(number_of_processors, 4u), 1u)); 605 } 606 607 608 void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory) { 609 ConfigureDefaults(physical_memory, i::CPU::NumberOfProcessorsOnline()); 610 } 611 612 613 bool SetResourceConstraints(Isolate* v8_isolate, 614 ResourceConstraints* constraints) { 615 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 616 int young_space_size = constraints->max_young_space_size(); 617 int old_gen_size = constraints->max_old_space_size(); 618 int max_executable_size = constraints->max_executable_size(); 619 if (young_space_size != 0 || old_gen_size != 0 || max_executable_size != 0) { 620 // After initialization it's too late to change Heap constraints. 621 ASSERT(!isolate->IsInitialized()); 622 bool result = isolate->heap()->ConfigureHeap(young_space_size / 2, 623 old_gen_size, 624 max_executable_size); 625 if (!result) return false; 626 } 627 if (constraints->stack_limit() != NULL) { 628 uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit()); 629 isolate->stack_guard()->SetStackLimit(limit); 630 } 631 632 isolate->set_max_available_threads(constraints->max_available_threads()); 633 return true; 634 } 635 636 637 i::Object** V8::GlobalizeReference(i::Isolate* isolate, i::Object** obj) { 638 LOG_API(isolate, "Persistent::New"); 639 i::Handle<i::Object> result = isolate->global_handles()->Create(*obj); 640 #ifdef DEBUG 641 (*obj)->Verify(); 642 #endif // DEBUG 643 return result.location(); 644 } 645 646 647 i::Object** V8::CopyPersistent(i::Object** obj) { 648 i::Handle<i::Object> result = i::GlobalHandles::CopyGlobal(obj); 649 #ifdef DEBUG 650 (*obj)->Verify(); 651 #endif // DEBUG 652 return result.location(); 653 } 654 655 656 void V8::MakeWeak(i::Object** object, 657 void* parameters, 658 WeakCallback weak_callback, 659 RevivableCallback weak_reference_callback) { 660 i::GlobalHandles::MakeWeak(object, 661 parameters, 662 weak_callback, 663 weak_reference_callback); 664 } 665 666 667 void V8::ClearWeak(i::Object** obj) { 668 i::GlobalHandles::ClearWeakness(obj); 669 } 670 671 672 void V8::DisposeGlobal(i::Object** obj) { 673 i::GlobalHandles::Destroy(obj); 674 } 675 676 677 void V8::Eternalize(Isolate* v8_isolate, Value* value, int* index) { 678 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 679 i::Object* object = *Utils::OpenHandle(value); 680 isolate->eternal_handles()->Create(isolate, object, index); 681 } 682 683 684 Local<Value> V8::GetEternal(Isolate* v8_isolate, int index) { 685 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 686 return Utils::ToLocal(isolate->eternal_handles()->Get(index)); 687 } 688 689 690 // --- H a n d l e s --- 691 692 693 HandleScope::HandleScope(Isolate* isolate) { 694 Initialize(isolate); 695 } 696 697 698 void HandleScope::Initialize(Isolate* isolate) { 699 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 700 API_ENTRY_CHECK(internal_isolate, "HandleScope::HandleScope"); 701 v8::ImplementationUtilities::HandleScopeData* current = 702 internal_isolate->handle_scope_data(); 703 isolate_ = internal_isolate; 704 prev_next_ = current->next; 705 prev_limit_ = current->limit; 706 is_closed_ = false; 707 current->level++; 708 } 709 710 711 HandleScope::~HandleScope() { 712 if (!is_closed_) { 713 Leave(); 714 } 715 } 716 717 718 void HandleScope::Leave() { 719 return i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_); 720 } 721 722 723 int HandleScope::NumberOfHandles() { 724 i::Isolate* isolate = i::Isolate::Current(); 725 if (!EnsureInitializedForIsolate(isolate, "HandleScope::NumberOfHandles")) { 726 return 0; 727 } 728 return i::HandleScope::NumberOfHandles(isolate); 729 } 730 731 732 i::Object** HandleScope::CreateHandle(i::Isolate* isolate, i::Object* value) { 733 return i::HandleScope::CreateHandle(isolate, value); 734 } 735 736 737 i::Object** HandleScope::CreateHandle(i::HeapObject* heap_object, 738 i::Object* value) { 739 ASSERT(heap_object->IsHeapObject()); 740 return i::HandleScope::CreateHandle(heap_object->GetIsolate(), value); 741 } 742 743 744 EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) { 745 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 746 escape_slot_ = CreateHandle(isolate, isolate->heap()->the_hole_value()); 747 Initialize(v8_isolate); 748 } 749 750 751 i::Object** EscapableHandleScope::Escape(i::Object** escape_value) { 752 ApiCheck(*escape_slot_ == isolate_->heap()->the_hole_value(), 753 "EscapeableHandleScope::Escape", 754 "Escape value set twice"); 755 if (escape_value == NULL) { 756 *escape_slot_ = isolate_->heap()->undefined_value(); 757 return NULL; 758 } 759 *escape_slot_ = *escape_value; 760 return escape_slot_; 761 } 762 763 764 void Context::Enter() { 765 i::Handle<i::Context> env = Utils::OpenHandle(this); 766 i::Isolate* isolate = env->GetIsolate(); 767 ENTER_V8(isolate); 768 isolate->handle_scope_implementer()->EnterContext(env); 769 isolate->handle_scope_implementer()->SaveContext(isolate->context()); 770 isolate->set_context(*env); 771 } 772 773 774 void Context::Exit() { 775 // TODO(dcarney): fix this once chrome is fixed. 776 i::Isolate* isolate = i::Isolate::Current(); 777 i::Handle<i::Context> context = i::Handle<i::Context>::null(); 778 ENTER_V8(isolate); 779 if (!ApiCheck(isolate->handle_scope_implementer()->LeaveContext(context), 780 "v8::Context::Exit()", 781 "Cannot exit non-entered context")) { 782 return; 783 } 784 // Content of 'last_context' could be NULL. 785 i::Context* last_context = 786 isolate->handle_scope_implementer()->RestoreContext(); 787 isolate->set_context(last_context); 788 } 789 790 791 static void* DecodeSmiToAligned(i::Object* value, const char* location) { 792 ApiCheck(value->IsSmi(), location, "Not a Smi"); 793 return reinterpret_cast<void*>(value); 794 } 795 796 797 static i::Smi* EncodeAlignedAsSmi(void* value, const char* location) { 798 i::Smi* smi = reinterpret_cast<i::Smi*>(value); 799 ApiCheck(smi->IsSmi(), location, "Pointer is not aligned"); 800 return smi; 801 } 802 803 804 static i::Handle<i::FixedArray> EmbedderDataFor(Context* context, 805 int index, 806 bool can_grow, 807 const char* location) { 808 i::Handle<i::Context> env = Utils::OpenHandle(context); 809 bool ok = 810 ApiCheck(env->IsNativeContext(), location, "Not a native context") && 811 ApiCheck(index >= 0, location, "Negative index"); 812 if (!ok) return i::Handle<i::FixedArray>(); 813 i::Handle<i::FixedArray> data(env->embedder_data()); 814 if (index < data->length()) return data; 815 if (!can_grow) { 816 Utils::ReportApiFailure(location, "Index too large"); 817 return i::Handle<i::FixedArray>(); 818 } 819 int new_size = i::Max(index, data->length() << 1) + 1; 820 data = env->GetIsolate()->factory()->CopySizeFixedArray(data, new_size); 821 env->set_embedder_data(*data); 822 return data; 823 } 824 825 826 v8::Local<v8::Value> Context::SlowGetEmbedderData(int index) { 827 const char* location = "v8::Context::GetEmbedderData()"; 828 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location); 829 if (data.is_null()) return Local<Value>(); 830 i::Handle<i::Object> result(data->get(index), data->GetIsolate()); 831 return Utils::ToLocal(result); 832 } 833 834 835 void Context::SetEmbedderData(int index, v8::Handle<Value> value) { 836 const char* location = "v8::Context::SetEmbedderData()"; 837 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location); 838 if (data.is_null()) return; 839 i::Handle<i::Object> val = Utils::OpenHandle(*value); 840 data->set(index, *val); 841 ASSERT_EQ(*Utils::OpenHandle(*value), 842 *Utils::OpenHandle(*GetEmbedderData(index))); 843 } 844 845 846 void* Context::SlowGetAlignedPointerFromEmbedderData(int index) { 847 const char* location = "v8::Context::GetAlignedPointerFromEmbedderData()"; 848 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location); 849 if (data.is_null()) return NULL; 850 return DecodeSmiToAligned(data->get(index), location); 851 } 852 853 854 void Context::SetAlignedPointerInEmbedderData(int index, void* value) { 855 const char* location = "v8::Context::SetAlignedPointerInEmbedderData()"; 856 i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location); 857 data->set(index, EncodeAlignedAsSmi(value, location)); 858 ASSERT_EQ(value, GetAlignedPointerFromEmbedderData(index)); 859 } 860 861 862 i::Object** v8::HandleScope::RawClose(i::Object** value) { 863 if (!ApiCheck(!is_closed_, 864 "v8::HandleScope::Close()", 865 "Local scope has already been closed")) { 866 return 0; 867 } 868 LOG_API(isolate_, "CloseHandleScope"); 869 870 // Read the result before popping the handle block. 871 i::Object* result = NULL; 872 if (value != NULL) { 873 result = *value; 874 } 875 is_closed_ = true; 876 Leave(); 877 878 if (value == NULL) { 879 return NULL; 880 } 881 882 // Allocate a new handle on the previous handle block. 883 i::Handle<i::Object> handle(result, isolate_); 884 return handle.location(); 885 } 886 887 888 // --- N e a n d e r --- 889 890 891 // A constructor cannot easily return an error value, therefore it is necessary 892 // to check for a dead VM with ON_BAILOUT before constructing any Neander 893 // objects. To remind you about this there is no HandleScope in the 894 // NeanderObject constructor. When you add one to the site calling the 895 // constructor you should check that you ensured the VM was not dead first. 896 NeanderObject::NeanderObject(int size) { 897 i::Isolate* isolate = i::Isolate::Current(); 898 EnsureInitializedForIsolate(isolate, "v8::Nowhere"); 899 ENTER_V8(isolate); 900 value_ = isolate->factory()->NewNeanderObject(); 901 i::Handle<i::FixedArray> elements = isolate->factory()->NewFixedArray(size); 902 value_->set_elements(*elements); 903 } 904 905 906 int NeanderObject::size() { 907 return i::FixedArray::cast(value_->elements())->length(); 908 } 909 910 911 NeanderArray::NeanderArray() : obj_(2) { 912 obj_.set(0, i::Smi::FromInt(0)); 913 } 914 915 916 int NeanderArray::length() { 917 return i::Smi::cast(obj_.get(0))->value(); 918 } 919 920 921 i::Object* NeanderArray::get(int offset) { 922 ASSERT(0 <= offset); 923 ASSERT(offset < length()); 924 return obj_.get(offset + 1); 925 } 926 927 928 // This method cannot easily return an error value, therefore it is necessary 929 // to check for a dead VM with ON_BAILOUT before calling it. To remind you 930 // about this there is no HandleScope in this method. When you add one to the 931 // site calling this method you should check that you ensured the VM was not 932 // dead first. 933 void NeanderArray::add(i::Handle<i::Object> value) { 934 int length = this->length(); 935 int size = obj_.size(); 936 if (length == size - 1) { 937 i::Factory* factory = i::Isolate::Current()->factory(); 938 i::Handle<i::FixedArray> new_elms = factory->NewFixedArray(2 * size); 939 for (int i = 0; i < length; i++) 940 new_elms->set(i + 1, get(i)); 941 obj_.value()->set_elements(*new_elms); 942 } 943 obj_.set(length + 1, *value); 944 obj_.set(0, i::Smi::FromInt(length + 1)); 945 } 946 947 948 void NeanderArray::set(int index, i::Object* value) { 949 if (index < 0 || index >= this->length()) return; 950 obj_.set(index + 1, value); 951 } 952 953 954 // --- T e m p l a t e --- 955 956 957 static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) { 958 that->set_tag(i::Smi::FromInt(type)); 959 } 960 961 962 static void TemplateSet(i::Isolate* isolate, 963 v8::Template* templ, 964 int length, 965 v8::Handle<v8::Data>* data) { 966 i::Handle<i::Object> list(Utils::OpenHandle(templ)->property_list(), isolate); 967 if (list->IsUndefined()) { 968 list = NeanderArray().value(); 969 Utils::OpenHandle(templ)->set_property_list(*list); 970 } 971 NeanderArray array(list); 972 array.add(Utils::OpenHandle(*v8::Integer::New(length))); 973 for (int i = 0; i < length; i++) { 974 i::Handle<i::Object> value = data[i].IsEmpty() ? 975 i::Handle<i::Object>(isolate->factory()->undefined_value()) : 976 Utils::OpenHandle(*data[i]); 977 array.add(value); 978 } 979 } 980 981 982 void Template::Set(v8::Handle<String> name, 983 v8::Handle<Data> value, 984 v8::PropertyAttribute attribute) { 985 i::Isolate* isolate = i::Isolate::Current(); 986 ENTER_V8(isolate); 987 i::HandleScope scope(isolate); 988 const int kSize = 3; 989 v8::Handle<v8::Data> data[kSize] = { 990 name, 991 value, 992 v8::Integer::New(attribute)}; 993 TemplateSet(isolate, this, kSize, data); 994 } 995 996 997 void Template::SetAccessorProperty( 998 v8::Local<v8::String> name, 999 v8::Local<FunctionTemplate> getter, 1000 v8::Local<FunctionTemplate> setter, 1001 v8::PropertyAttribute attribute, 1002 v8::AccessControl access_control) { 1003 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1004 ENTER_V8(isolate); 1005 ASSERT(!name.IsEmpty()); 1006 ASSERT(!getter.IsEmpty() || !setter.IsEmpty()); 1007 i::HandleScope scope(isolate); 1008 const int kSize = 5; 1009 v8::Handle<v8::Data> data[kSize] = { 1010 name, 1011 getter, 1012 setter, 1013 v8::Integer::New(attribute), 1014 v8::Integer::New(access_control)}; 1015 TemplateSet(isolate, this, kSize, data); 1016 } 1017 1018 1019 // --- F u n c t i o n T e m p l a t e --- 1020 static void InitializeFunctionTemplate( 1021 i::Handle<i::FunctionTemplateInfo> info) { 1022 info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE)); 1023 info->set_flag(0); 1024 } 1025 1026 1027 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() { 1028 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1029 ENTER_V8(isolate); 1030 i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template(), 1031 isolate); 1032 if (result->IsUndefined()) { 1033 result = Utils::OpenHandle(*ObjectTemplate::New()); 1034 Utils::OpenHandle(this)->set_prototype_template(*result); 1035 } 1036 return ToApiHandle<ObjectTemplate>(result); 1037 } 1038 1039 1040 void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) { 1041 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1042 ENTER_V8(isolate); 1043 Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value)); 1044 } 1045 1046 1047 static Local<FunctionTemplate> FunctionTemplateNew( 1048 i::Isolate* isolate, 1049 FunctionCallback callback, 1050 v8::Handle<Value> data, 1051 v8::Handle<Signature> signature, 1052 int length, 1053 bool do_not_cache) { 1054 i::Handle<i::Struct> struct_obj = 1055 isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE); 1056 i::Handle<i::FunctionTemplateInfo> obj = 1057 i::Handle<i::FunctionTemplateInfo>::cast(struct_obj); 1058 InitializeFunctionTemplate(obj); 1059 obj->set_do_not_cache(do_not_cache); 1060 int next_serial_number = 0; 1061 if (!do_not_cache) { 1062 next_serial_number = isolate->next_serial_number() + 1; 1063 isolate->set_next_serial_number(next_serial_number); 1064 } 1065 obj->set_serial_number(i::Smi::FromInt(next_serial_number)); 1066 if (callback != 0) { 1067 if (data.IsEmpty()) { 1068 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1069 } 1070 Utils::ToLocal(obj)->SetCallHandler(callback, data); 1071 } 1072 obj->set_length(length); 1073 obj->set_undetectable(false); 1074 obj->set_needs_access_check(false); 1075 if (!signature.IsEmpty()) 1076 obj->set_signature(*Utils::OpenHandle(*signature)); 1077 return Utils::ToLocal(obj); 1078 } 1079 1080 Local<FunctionTemplate> FunctionTemplate::New( 1081 Isolate* isolate, 1082 FunctionCallback callback, 1083 v8::Handle<Value> data, 1084 v8::Handle<Signature> signature, 1085 int length) { 1086 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 1087 EnsureInitializedForIsolate(i_isolate, "v8::FunctionTemplate::New()"); 1088 LOG_API(i_isolate, "FunctionTemplate::New"); 1089 ENTER_V8(i_isolate); 1090 return FunctionTemplateNew( 1091 i_isolate, callback, data, signature, length, false); 1092 } 1093 1094 1095 Local<FunctionTemplate> FunctionTemplate::New( 1096 FunctionCallback callback, 1097 v8::Handle<Value> data, 1098 v8::Handle<Signature> signature, 1099 int length) { 1100 return New(Isolate::GetCurrent(), callback, data, signature, length); 1101 } 1102 1103 Local<Signature> Signature::New(Isolate* isolate, 1104 Handle<FunctionTemplate> receiver, int argc, 1105 Handle<FunctionTemplate> argv[]) { 1106 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 1107 EnsureInitializedForIsolate(i_isolate, "v8::Signature::New()"); 1108 LOG_API(i_isolate, "Signature::New"); 1109 ENTER_V8(i_isolate); 1110 i::Handle<i::Struct> struct_obj = 1111 i_isolate->factory()->NewStruct(i::SIGNATURE_INFO_TYPE); 1112 i::Handle<i::SignatureInfo> obj = 1113 i::Handle<i::SignatureInfo>::cast(struct_obj); 1114 if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver)); 1115 if (argc > 0) { 1116 i::Handle<i::FixedArray> args = i_isolate->factory()->NewFixedArray(argc); 1117 for (int i = 0; i < argc; i++) { 1118 if (!argv[i].IsEmpty()) 1119 args->set(i, *Utils::OpenHandle(*argv[i])); 1120 } 1121 obj->set_args(*args); 1122 } 1123 return Utils::ToLocal(obj); 1124 } 1125 1126 1127 Local<Signature> Signature::New(Handle<FunctionTemplate> receiver, 1128 int argc, Handle<FunctionTemplate> argv[]) { 1129 return New(Isolate::GetCurrent(), receiver, argc, argv); 1130 } 1131 1132 1133 Local<AccessorSignature> AccessorSignature::New( 1134 Isolate* isolate, 1135 Handle<FunctionTemplate> receiver) { 1136 return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver)); 1137 } 1138 1139 1140 // While this is just a cast, it's lame not to use an Isolate parameter. 1141 Local<AccessorSignature> AccessorSignature::New( 1142 Handle<FunctionTemplate> receiver) { 1143 return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver)); 1144 } 1145 1146 1147 template<typename Operation> 1148 static Local<Operation> NewDescriptor( 1149 Isolate* isolate, 1150 const i::DeclaredAccessorDescriptorData& data, 1151 Data* previous_descriptor) { 1152 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 1153 i::Handle<i::DeclaredAccessorDescriptor> previous = 1154 i::Handle<i::DeclaredAccessorDescriptor>(); 1155 if (previous_descriptor != NULL) { 1156 previous = Utils::OpenHandle( 1157 static_cast<DeclaredAccessorDescriptor*>(previous_descriptor)); 1158 } 1159 i::Handle<i::DeclaredAccessorDescriptor> descriptor = 1160 i::DeclaredAccessorDescriptor::Create(internal_isolate, data, previous); 1161 return Utils::Convert<i::DeclaredAccessorDescriptor, Operation>(descriptor); 1162 } 1163 1164 1165 Local<RawOperationDescriptor> 1166 ObjectOperationDescriptor::NewInternalFieldDereference( 1167 Isolate* isolate, 1168 int internal_field) { 1169 i::DeclaredAccessorDescriptorData data; 1170 data.type = i::kDescriptorObjectDereference; 1171 data.object_dereference_descriptor.internal_field = internal_field; 1172 return NewDescriptor<RawOperationDescriptor>(isolate, data, NULL); 1173 } 1174 1175 1176 Local<RawOperationDescriptor> RawOperationDescriptor::NewRawShift( 1177 Isolate* isolate, 1178 int16_t byte_offset) { 1179 i::DeclaredAccessorDescriptorData data; 1180 data.type = i::kDescriptorPointerShift; 1181 data.pointer_shift_descriptor.byte_offset = byte_offset; 1182 return NewDescriptor<RawOperationDescriptor>(isolate, data, this); 1183 } 1184 1185 1186 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewHandleDereference( 1187 Isolate* isolate) { 1188 i::DeclaredAccessorDescriptorData data; 1189 data.type = i::kDescriptorReturnObject; 1190 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this); 1191 } 1192 1193 1194 Local<RawOperationDescriptor> RawOperationDescriptor::NewRawDereference( 1195 Isolate* isolate) { 1196 i::DeclaredAccessorDescriptorData data; 1197 data.type = i::kDescriptorPointerDereference; 1198 return NewDescriptor<RawOperationDescriptor>(isolate, data, this); 1199 } 1200 1201 1202 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPointerCompare( 1203 Isolate* isolate, 1204 void* compare_value) { 1205 i::DeclaredAccessorDescriptorData data; 1206 data.type = i::kDescriptorPointerCompare; 1207 data.pointer_compare_descriptor.compare_value = compare_value; 1208 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this); 1209 } 1210 1211 1212 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPrimitiveValue( 1213 Isolate* isolate, 1214 DeclaredAccessorDescriptorDataType data_type, 1215 uint8_t bool_offset) { 1216 i::DeclaredAccessorDescriptorData data; 1217 data.type = i::kDescriptorPrimitiveValue; 1218 data.primitive_value_descriptor.data_type = data_type; 1219 data.primitive_value_descriptor.bool_offset = bool_offset; 1220 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this); 1221 } 1222 1223 1224 template<typename T> 1225 static Local<DeclaredAccessorDescriptor> NewBitmaskCompare( 1226 Isolate* isolate, 1227 T bitmask, 1228 T compare_value, 1229 RawOperationDescriptor* operation) { 1230 i::DeclaredAccessorDescriptorData data; 1231 data.type = i::kDescriptorBitmaskCompare; 1232 data.bitmask_compare_descriptor.bitmask = bitmask; 1233 data.bitmask_compare_descriptor.compare_value = compare_value; 1234 data.bitmask_compare_descriptor.size = sizeof(T); 1235 return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, operation); 1236 } 1237 1238 1239 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare8( 1240 Isolate* isolate, 1241 uint8_t bitmask, 1242 uint8_t compare_value) { 1243 return NewBitmaskCompare(isolate, bitmask, compare_value, this); 1244 } 1245 1246 1247 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare16( 1248 Isolate* isolate, 1249 uint16_t bitmask, 1250 uint16_t compare_value) { 1251 return NewBitmaskCompare(isolate, bitmask, compare_value, this); 1252 } 1253 1254 1255 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare32( 1256 Isolate* isolate, 1257 uint32_t bitmask, 1258 uint32_t compare_value) { 1259 return NewBitmaskCompare(isolate, bitmask, compare_value, this); 1260 } 1261 1262 1263 Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) { 1264 Handle<FunctionTemplate> types[1] = { type }; 1265 return TypeSwitch::New(1, types); 1266 } 1267 1268 1269 Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) { 1270 i::Isolate* isolate = i::Isolate::Current(); 1271 EnsureInitializedForIsolate(isolate, "v8::TypeSwitch::New()"); 1272 LOG_API(isolate, "TypeSwitch::New"); 1273 ENTER_V8(isolate); 1274 i::Handle<i::FixedArray> vector = isolate->factory()->NewFixedArray(argc); 1275 for (int i = 0; i < argc; i++) 1276 vector->set(i, *Utils::OpenHandle(*types[i])); 1277 i::Handle<i::Struct> struct_obj = 1278 isolate->factory()->NewStruct(i::TYPE_SWITCH_INFO_TYPE); 1279 i::Handle<i::TypeSwitchInfo> obj = 1280 i::Handle<i::TypeSwitchInfo>::cast(struct_obj); 1281 obj->set_types(*vector); 1282 return Utils::ToLocal(obj); 1283 } 1284 1285 1286 int TypeSwitch::match(v8::Handle<Value> value) { 1287 i::Isolate* isolate = i::Isolate::Current(); 1288 LOG_API(isolate, "TypeSwitch::match"); 1289 USE(isolate); 1290 i::Handle<i::Object> obj = Utils::OpenHandle(*value); 1291 i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this); 1292 i::FixedArray* types = i::FixedArray::cast(info->types()); 1293 for (int i = 0; i < types->length(); i++) { 1294 if (i::FunctionTemplateInfo::cast(types->get(i))->IsTemplateFor(*obj)) 1295 return i + 1; 1296 } 1297 return 0; 1298 } 1299 1300 1301 #define SET_FIELD_WRAPPED(obj, setter, cdata) do { \ 1302 i::Handle<i::Object> foreign = FromCData(obj->GetIsolate(), cdata); \ 1303 (obj)->setter(*foreign); \ 1304 } while (false) 1305 1306 1307 void FunctionTemplate::SetCallHandler(FunctionCallback callback, 1308 v8::Handle<Value> data) { 1309 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1310 ENTER_V8(isolate); 1311 i::HandleScope scope(isolate); 1312 i::Handle<i::Struct> struct_obj = 1313 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE); 1314 i::Handle<i::CallHandlerInfo> obj = 1315 i::Handle<i::CallHandlerInfo>::cast(struct_obj); 1316 SET_FIELD_WRAPPED(obj, set_callback, callback); 1317 if (data.IsEmpty()) { 1318 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1319 } 1320 obj->set_data(*Utils::OpenHandle(*data)); 1321 Utils::OpenHandle(this)->set_call_code(*obj); 1322 } 1323 1324 1325 static i::Handle<i::AccessorInfo> SetAccessorInfoProperties( 1326 i::Handle<i::AccessorInfo> obj, 1327 v8::Handle<String> name, 1328 v8::AccessControl settings, 1329 v8::PropertyAttribute attributes, 1330 v8::Handle<AccessorSignature> signature) { 1331 obj->set_name(*Utils::OpenHandle(*name)); 1332 if (settings & ALL_CAN_READ) obj->set_all_can_read(true); 1333 if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true); 1334 if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true); 1335 obj->set_property_attributes(static_cast<PropertyAttributes>(attributes)); 1336 if (!signature.IsEmpty()) { 1337 obj->set_expected_receiver_type(*Utils::OpenHandle(*signature)); 1338 } 1339 return obj; 1340 } 1341 1342 1343 template<typename Getter, typename Setter> 1344 static i::Handle<i::AccessorInfo> MakeAccessorInfo( 1345 v8::Handle<String> name, 1346 Getter getter, 1347 Setter setter, 1348 v8::Handle<Value> data, 1349 v8::AccessControl settings, 1350 v8::PropertyAttribute attributes, 1351 v8::Handle<AccessorSignature> signature) { 1352 i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate(); 1353 i::Handle<i::ExecutableAccessorInfo> obj = 1354 isolate->factory()->NewExecutableAccessorInfo(); 1355 SET_FIELD_WRAPPED(obj, set_getter, getter); 1356 SET_FIELD_WRAPPED(obj, set_setter, setter); 1357 if (data.IsEmpty()) { 1358 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1359 } 1360 obj->set_data(*Utils::OpenHandle(*data)); 1361 return SetAccessorInfoProperties(obj, name, settings, attributes, signature); 1362 } 1363 1364 1365 static i::Handle<i::AccessorInfo> MakeAccessorInfo( 1366 v8::Handle<String> name, 1367 v8::Handle<v8::DeclaredAccessorDescriptor> descriptor, 1368 void* setter_ignored, 1369 void* data_ignored, 1370 v8::AccessControl settings, 1371 v8::PropertyAttribute attributes, 1372 v8::Handle<AccessorSignature> signature) { 1373 i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate(); 1374 if (descriptor.IsEmpty()) return i::Handle<i::DeclaredAccessorInfo>(); 1375 i::Handle<i::DeclaredAccessorInfo> obj = 1376 isolate->factory()->NewDeclaredAccessorInfo(); 1377 obj->set_descriptor(*Utils::OpenHandle(*descriptor)); 1378 return SetAccessorInfoProperties(obj, name, settings, attributes, signature); 1379 } 1380 1381 1382 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() { 1383 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1384 if (EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this)) 1385 return Local<ObjectTemplate>(); 1386 ENTER_V8(isolate); 1387 i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this); 1388 if (handle->instance_template()->IsUndefined()) { 1389 Local<ObjectTemplate> templ = 1390 ObjectTemplate::New(isolate, ToApiHandle<FunctionTemplate>(handle)); 1391 handle->set_instance_template(*Utils::OpenHandle(*templ)); 1392 } 1393 i::Handle<i::ObjectTemplateInfo> result( 1394 i::ObjectTemplateInfo::cast(handle->instance_template())); 1395 return Utils::ToLocal(result); 1396 } 1397 1398 1399 void FunctionTemplate::SetLength(int length) { 1400 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1401 ENTER_V8(isolate); 1402 Utils::OpenHandle(this)->set_length(length); 1403 } 1404 1405 1406 void FunctionTemplate::SetClassName(Handle<String> name) { 1407 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1408 ENTER_V8(isolate); 1409 Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name)); 1410 } 1411 1412 1413 void FunctionTemplate::SetHiddenPrototype(bool value) { 1414 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1415 ENTER_V8(isolate); 1416 Utils::OpenHandle(this)->set_hidden_prototype(value); 1417 } 1418 1419 1420 void FunctionTemplate::ReadOnlyPrototype() { 1421 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1422 ENTER_V8(isolate); 1423 Utils::OpenHandle(this)->set_read_only_prototype(true); 1424 } 1425 1426 1427 void FunctionTemplate::RemovePrototype() { 1428 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1429 ENTER_V8(isolate); 1430 Utils::OpenHandle(this)->set_remove_prototype(true); 1431 } 1432 1433 1434 // --- O b j e c t T e m p l a t e --- 1435 1436 1437 Local<ObjectTemplate> ObjectTemplate::New(Isolate* isolate) { 1438 return New(reinterpret_cast<i::Isolate*>(isolate), Local<FunctionTemplate>()); 1439 } 1440 1441 1442 Local<ObjectTemplate> ObjectTemplate::New() { 1443 return New(i::Isolate::Current(), Local<FunctionTemplate>()); 1444 } 1445 1446 1447 Local<ObjectTemplate> ObjectTemplate::New( 1448 i::Isolate* isolate, 1449 v8::Handle<FunctionTemplate> constructor) { 1450 EnsureInitializedForIsolate(isolate, "v8::ObjectTemplate::New()"); 1451 LOG_API(isolate, "ObjectTemplate::New"); 1452 ENTER_V8(isolate); 1453 i::Handle<i::Struct> struct_obj = 1454 isolate->factory()->NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE); 1455 i::Handle<i::ObjectTemplateInfo> obj = 1456 i::Handle<i::ObjectTemplateInfo>::cast(struct_obj); 1457 InitializeTemplate(obj, Consts::OBJECT_TEMPLATE); 1458 if (!constructor.IsEmpty()) 1459 obj->set_constructor(*Utils::OpenHandle(*constructor)); 1460 obj->set_internal_field_count(i::Smi::FromInt(0)); 1461 return Utils::ToLocal(obj); 1462 } 1463 1464 1465 // Ensure that the object template has a constructor. If no 1466 // constructor is available we create one. 1467 static i::Handle<i::FunctionTemplateInfo> EnsureConstructor( 1468 ObjectTemplate* object_template) { 1469 i::Object* obj = Utils::OpenHandle(object_template)->constructor(); 1470 if (!obj ->IsUndefined()) { 1471 i::FunctionTemplateInfo* info = i::FunctionTemplateInfo::cast(obj); 1472 return i::Handle<i::FunctionTemplateInfo>(info, info->GetIsolate()); 1473 } 1474 Local<FunctionTemplate> templ = FunctionTemplate::New(); 1475 i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ); 1476 constructor->set_instance_template(*Utils::OpenHandle(object_template)); 1477 Utils::OpenHandle(object_template)->set_constructor(*constructor); 1478 return constructor; 1479 } 1480 1481 1482 static inline void AddPropertyToTemplate( 1483 i::Handle<i::TemplateInfo> info, 1484 i::Handle<i::AccessorInfo> obj) { 1485 i::Handle<i::Object> list(info->property_accessors(), info->GetIsolate()); 1486 if (list->IsUndefined()) { 1487 list = NeanderArray().value(); 1488 info->set_property_accessors(*list); 1489 } 1490 NeanderArray array(list); 1491 array.add(obj); 1492 } 1493 1494 1495 static inline i::Handle<i::TemplateInfo> GetTemplateInfo( 1496 Template* template_obj) { 1497 return Utils::OpenHandle(template_obj); 1498 } 1499 1500 1501 // TODO(dcarney): remove this with ObjectTemplate::SetAccessor 1502 static inline i::Handle<i::TemplateInfo> GetTemplateInfo( 1503 ObjectTemplate* object_template) { 1504 EnsureConstructor(object_template); 1505 return Utils::OpenHandle(object_template); 1506 } 1507 1508 1509 template<typename Setter, typename Getter, typename Data, typename Template> 1510 static bool TemplateSetAccessor( 1511 Template* template_obj, 1512 v8::Local<String> name, 1513 Getter getter, 1514 Setter setter, 1515 Data data, 1516 AccessControl settings, 1517 PropertyAttribute attribute, 1518 v8::Local<AccessorSignature> signature) { 1519 i::Isolate* isolate = Utils::OpenHandle(template_obj)->GetIsolate(); 1520 ENTER_V8(isolate); 1521 i::HandleScope scope(isolate); 1522 i::Handle<i::AccessorInfo> obj = MakeAccessorInfo( 1523 name, getter, setter, data, settings, attribute, signature); 1524 if (obj.is_null()) return false; 1525 i::Handle<i::TemplateInfo> info = GetTemplateInfo(template_obj); 1526 AddPropertyToTemplate(info, obj); 1527 return true; 1528 } 1529 1530 1531 bool Template::SetDeclaredAccessor( 1532 Local<String> name, 1533 Local<DeclaredAccessorDescriptor> descriptor, 1534 PropertyAttribute attribute, 1535 Local<AccessorSignature> signature, 1536 AccessControl settings) { 1537 void* null = NULL; 1538 return TemplateSetAccessor( 1539 this, name, descriptor, null, null, settings, attribute, signature); 1540 } 1541 1542 1543 void Template::SetNativeDataProperty(v8::Local<String> name, 1544 AccessorGetterCallback getter, 1545 AccessorSetterCallback setter, 1546 v8::Handle<Value> data, 1547 PropertyAttribute attribute, 1548 v8::Local<AccessorSignature> signature, 1549 AccessControl settings) { 1550 TemplateSetAccessor( 1551 this, name, getter, setter, data, settings, attribute, signature); 1552 } 1553 1554 1555 void ObjectTemplate::SetAccessor(v8::Handle<String> name, 1556 AccessorGetterCallback getter, 1557 AccessorSetterCallback setter, 1558 v8::Handle<Value> data, 1559 AccessControl settings, 1560 PropertyAttribute attribute, 1561 v8::Handle<AccessorSignature> signature) { 1562 TemplateSetAccessor( 1563 this, name, getter, setter, data, settings, attribute, signature); 1564 } 1565 1566 1567 void ObjectTemplate::SetNamedPropertyHandler( 1568 NamedPropertyGetterCallback getter, 1569 NamedPropertySetterCallback setter, 1570 NamedPropertyQueryCallback query, 1571 NamedPropertyDeleterCallback remover, 1572 NamedPropertyEnumeratorCallback enumerator, 1573 Handle<Value> data) { 1574 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1575 ENTER_V8(isolate); 1576 i::HandleScope scope(isolate); 1577 EnsureConstructor(this); 1578 i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast( 1579 Utils::OpenHandle(this)->constructor()); 1580 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1581 i::Handle<i::Struct> struct_obj = 1582 isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE); 1583 i::Handle<i::InterceptorInfo> obj = 1584 i::Handle<i::InterceptorInfo>::cast(struct_obj); 1585 1586 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter); 1587 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter); 1588 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query); 1589 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover); 1590 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); 1591 1592 if (data.IsEmpty()) { 1593 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1594 } 1595 obj->set_data(*Utils::OpenHandle(*data)); 1596 cons->set_named_property_handler(*obj); 1597 } 1598 1599 1600 void ObjectTemplate::MarkAsUndetectable() { 1601 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1602 ENTER_V8(isolate); 1603 i::HandleScope scope(isolate); 1604 EnsureConstructor(this); 1605 i::FunctionTemplateInfo* constructor = 1606 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor()); 1607 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1608 cons->set_undetectable(true); 1609 } 1610 1611 1612 void ObjectTemplate::SetAccessCheckCallbacks( 1613 NamedSecurityCallback named_callback, 1614 IndexedSecurityCallback indexed_callback, 1615 Handle<Value> data, 1616 bool turned_on_by_default) { 1617 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1618 ENTER_V8(isolate); 1619 i::HandleScope scope(isolate); 1620 EnsureConstructor(this); 1621 1622 i::Handle<i::Struct> struct_info = 1623 isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE); 1624 i::Handle<i::AccessCheckInfo> info = 1625 i::Handle<i::AccessCheckInfo>::cast(struct_info); 1626 1627 SET_FIELD_WRAPPED(info, set_named_callback, named_callback); 1628 SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback); 1629 1630 if (data.IsEmpty()) { 1631 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1632 } 1633 info->set_data(*Utils::OpenHandle(*data)); 1634 1635 i::FunctionTemplateInfo* constructor = 1636 i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor()); 1637 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1638 cons->set_access_check_info(*info); 1639 cons->set_needs_access_check(turned_on_by_default); 1640 } 1641 1642 1643 void ObjectTemplate::SetIndexedPropertyHandler( 1644 IndexedPropertyGetterCallback getter, 1645 IndexedPropertySetterCallback setter, 1646 IndexedPropertyQueryCallback query, 1647 IndexedPropertyDeleterCallback remover, 1648 IndexedPropertyEnumeratorCallback enumerator, 1649 Handle<Value> data) { 1650 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1651 ENTER_V8(isolate); 1652 i::HandleScope scope(isolate); 1653 EnsureConstructor(this); 1654 i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast( 1655 Utils::OpenHandle(this)->constructor()); 1656 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1657 i::Handle<i::Struct> struct_obj = 1658 isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE); 1659 i::Handle<i::InterceptorInfo> obj = 1660 i::Handle<i::InterceptorInfo>::cast(struct_obj); 1661 1662 if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter); 1663 if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter); 1664 if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query); 1665 if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover); 1666 if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); 1667 1668 if (data.IsEmpty()) { 1669 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1670 } 1671 obj->set_data(*Utils::OpenHandle(*data)); 1672 cons->set_indexed_property_handler(*obj); 1673 } 1674 1675 1676 void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback, 1677 Handle<Value> data) { 1678 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1679 ENTER_V8(isolate); 1680 i::HandleScope scope(isolate); 1681 EnsureConstructor(this); 1682 i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast( 1683 Utils::OpenHandle(this)->constructor()); 1684 i::Handle<i::FunctionTemplateInfo> cons(constructor); 1685 i::Handle<i::Struct> struct_obj = 1686 isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE); 1687 i::Handle<i::CallHandlerInfo> obj = 1688 i::Handle<i::CallHandlerInfo>::cast(struct_obj); 1689 SET_FIELD_WRAPPED(obj, set_callback, callback); 1690 if (data.IsEmpty()) { 1691 data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 1692 } 1693 obj->set_data(*Utils::OpenHandle(*data)); 1694 cons->set_instance_call_handler(*obj); 1695 } 1696 1697 1698 int ObjectTemplate::InternalFieldCount() { 1699 return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value(); 1700 } 1701 1702 1703 void ObjectTemplate::SetInternalFieldCount(int value) { 1704 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 1705 if (!ApiCheck(i::Smi::IsValid(value), 1706 "v8::ObjectTemplate::SetInternalFieldCount()", 1707 "Invalid internal field count")) { 1708 return; 1709 } 1710 ENTER_V8(isolate); 1711 if (value > 0) { 1712 // The internal field count is set by the constructor function's 1713 // construct code, so we ensure that there is a constructor 1714 // function to do the setting. 1715 EnsureConstructor(this); 1716 } 1717 Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value)); 1718 } 1719 1720 1721 // --- S c r i p t D a t a --- 1722 1723 1724 ScriptData* ScriptData::PreCompile(v8::Isolate* isolate, 1725 const char* input, 1726 int length) { 1727 i::Utf8ToUtf16CharacterStream stream( 1728 reinterpret_cast<const unsigned char*>(input), length); 1729 return i::PreParserApi::PreParse( 1730 reinterpret_cast<i::Isolate*>(isolate), &stream); 1731 } 1732 1733 1734 ScriptData* ScriptData::PreCompile(v8::Handle<String> source) { 1735 i::Handle<i::String> str = Utils::OpenHandle(*source); 1736 i::Isolate* isolate = str->GetIsolate(); 1737 if (str->IsExternalTwoByteString()) { 1738 i::ExternalTwoByteStringUtf16CharacterStream stream( 1739 i::Handle<i::ExternalTwoByteString>::cast(str), 0, str->length()); 1740 return i::PreParserApi::PreParse(isolate, &stream); 1741 } else { 1742 i::GenericStringUtf16CharacterStream stream(str, 0, str->length()); 1743 return i::PreParserApi::PreParse(isolate, &stream); 1744 } 1745 } 1746 1747 1748 ScriptData* ScriptData::New(const char* data, int length) { 1749 // Return an empty ScriptData if the length is obviously invalid. 1750 if (length % sizeof(unsigned) != 0) { 1751 return new i::ScriptDataImpl(); 1752 } 1753 1754 // Copy the data to ensure it is properly aligned. 1755 int deserialized_data_length = length / sizeof(unsigned); 1756 // If aligned, don't create a copy of the data. 1757 if (reinterpret_cast<intptr_t>(data) % sizeof(unsigned) == 0) { 1758 return new i::ScriptDataImpl(data, length); 1759 } 1760 // Copy the data to align it. 1761 unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length); 1762 i::CopyBytes(reinterpret_cast<char*>(deserialized_data), 1763 data, static_cast<size_t>(length)); 1764 1765 return new i::ScriptDataImpl( 1766 i::Vector<unsigned>(deserialized_data, deserialized_data_length)); 1767 } 1768 1769 1770 // --- S c r i p t --- 1771 1772 1773 Local<Script> Script::New(v8::Handle<String> source, 1774 v8::ScriptOrigin* origin, 1775 v8::ScriptData* pre_data, 1776 v8::Handle<String> script_data) { 1777 i::Handle<i::String> str = Utils::OpenHandle(*source); 1778 i::Isolate* isolate = str->GetIsolate(); 1779 ON_BAILOUT(isolate, "v8::Script::New()", return Local<Script>()); 1780 LOG_API(isolate, "Script::New"); 1781 ENTER_V8(isolate); 1782 i::SharedFunctionInfo* raw_result = NULL; 1783 { i::HandleScope scope(isolate); 1784 i::Handle<i::Object> name_obj; 1785 int line_offset = 0; 1786 int column_offset = 0; 1787 bool is_shared_cross_origin = false; 1788 if (origin != NULL) { 1789 if (!origin->ResourceName().IsEmpty()) { 1790 name_obj = Utils::OpenHandle(*origin->ResourceName()); 1791 } 1792 if (!origin->ResourceLineOffset().IsEmpty()) { 1793 line_offset = static_cast<int>(origin->ResourceLineOffset()->Value()); 1794 } 1795 if (!origin->ResourceColumnOffset().IsEmpty()) { 1796 column_offset = 1797 static_cast<int>(origin->ResourceColumnOffset()->Value()); 1798 } 1799 if (!origin->ResourceIsSharedCrossOrigin().IsEmpty()) { 1800 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); 1801 is_shared_cross_origin = 1802 origin->ResourceIsSharedCrossOrigin() == v8::True(v8_isolate); 1803 } 1804 } 1805 EXCEPTION_PREAMBLE(isolate); 1806 i::ScriptDataImpl* pre_data_impl = 1807 static_cast<i::ScriptDataImpl*>(pre_data); 1808 // We assert that the pre-data is sane, even though we can actually 1809 // handle it if it turns out not to be in release mode. 1810 ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck()); 1811 // If the pre-data isn't sane we simply ignore it 1812 if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) { 1813 pre_data_impl = NULL; 1814 } 1815 i::Handle<i::SharedFunctionInfo> result = 1816 i::Compiler::Compile(str, 1817 name_obj, 1818 line_offset, 1819 column_offset, 1820 is_shared_cross_origin, 1821 isolate->global_context(), 1822 NULL, 1823 pre_data_impl, 1824 Utils::OpenHandle(*script_data, true), 1825 i::NOT_NATIVES_CODE); 1826 has_pending_exception = result.is_null(); 1827 EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>()); 1828 raw_result = *result; 1829 } 1830 i::Handle<i::SharedFunctionInfo> result(raw_result, isolate); 1831 return ToApiHandle<Script>(result); 1832 } 1833 1834 1835 Local<Script> Script::New(v8::Handle<String> source, 1836 v8::Handle<Value> file_name) { 1837 ScriptOrigin origin(file_name); 1838 return New(source, &origin); 1839 } 1840 1841 1842 Local<Script> Script::Compile(v8::Handle<String> source, 1843 v8::ScriptOrigin* origin, 1844 v8::ScriptData* pre_data, 1845 v8::Handle<String> script_data) { 1846 i::Handle<i::String> str = Utils::OpenHandle(*source); 1847 i::Isolate* isolate = str->GetIsolate(); 1848 ON_BAILOUT(isolate, "v8::Script::Compile()", return Local<Script>()); 1849 LOG_API(isolate, "Script::Compile"); 1850 ENTER_V8(isolate); 1851 Local<Script> generic = New(source, origin, pre_data, script_data); 1852 if (generic.IsEmpty()) 1853 return generic; 1854 i::Handle<i::Object> obj = Utils::OpenHandle(*generic); 1855 i::Handle<i::SharedFunctionInfo> function = 1856 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj)); 1857 i::Handle<i::JSFunction> result = 1858 isolate->factory()->NewFunctionFromSharedFunctionInfo( 1859 function, 1860 isolate->global_context()); 1861 return ToApiHandle<Script>(result); 1862 } 1863 1864 1865 Local<Script> Script::Compile(v8::Handle<String> source, 1866 v8::Handle<Value> file_name, 1867 v8::Handle<String> script_data) { 1868 ScriptOrigin origin(file_name); 1869 return Compile(source, &origin, 0, script_data); 1870 } 1871 1872 1873 Local<Value> Script::Run() { 1874 // If execution is terminating, Compile(script)->Run() requires this check. 1875 if (this == NULL) return Local<Value>(); 1876 i::Handle<i::HeapObject> obj = 1877 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this)); 1878 i::Isolate* isolate = obj->GetIsolate(); 1879 ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>()); 1880 LOG_API(isolate, "Script::Run"); 1881 ENTER_V8(isolate); 1882 i::Logger::TimerEventScope timer_scope( 1883 isolate, i::Logger::TimerEventScope::v8_execute); 1884 i::Object* raw_result = NULL; 1885 { 1886 i::HandleScope scope(isolate); 1887 i::Handle<i::JSFunction> fun; 1888 if (obj->IsSharedFunctionInfo()) { 1889 i::Handle<i::SharedFunctionInfo> 1890 function_info(i::SharedFunctionInfo::cast(*obj), isolate); 1891 fun = isolate->factory()->NewFunctionFromSharedFunctionInfo( 1892 function_info, isolate->global_context()); 1893 } else { 1894 fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj), isolate); 1895 } 1896 EXCEPTION_PREAMBLE(isolate); 1897 i::Handle<i::Object> receiver( 1898 isolate->context()->global_proxy(), isolate); 1899 i::Handle<i::Object> result = i::Execution::Call( 1900 isolate, fun, receiver, 0, NULL, &has_pending_exception); 1901 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>()); 1902 raw_result = *result; 1903 } 1904 i::Handle<i::Object> result(raw_result, isolate); 1905 return Utils::ToLocal(result); 1906 } 1907 1908 1909 static i::Handle<i::SharedFunctionInfo> OpenScript(Script* script) { 1910 i::Handle<i::Object> obj = Utils::OpenHandle(script); 1911 i::Handle<i::SharedFunctionInfo> result; 1912 if (obj->IsSharedFunctionInfo()) { 1913 result = 1914 i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj)); 1915 } else { 1916 result = 1917 i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared()); 1918 } 1919 return result; 1920 } 1921 1922 1923 Local<Value> Script::Id() { 1924 i::Handle<i::HeapObject> obj = 1925 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this)); 1926 i::Isolate* isolate = obj->GetIsolate(); 1927 ON_BAILOUT(isolate, "v8::Script::Id()", return Local<Value>()); 1928 LOG_API(isolate, "Script::Id"); 1929 i::Object* raw_id = NULL; 1930 { 1931 i::HandleScope scope(isolate); 1932 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this); 1933 i::Handle<i::Script> script(i::Script::cast(function_info->script())); 1934 i::Handle<i::Object> id(script->id(), isolate); 1935 raw_id = *id; 1936 } 1937 i::Handle<i::Object> id(raw_id, isolate); 1938 return Utils::ToLocal(id); 1939 } 1940 1941 1942 int Script::GetId() { 1943 i::Handle<i::HeapObject> obj = 1944 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this)); 1945 i::Isolate* isolate = obj->GetIsolate(); 1946 ON_BAILOUT(isolate, "v8::Script::Id()", return -1); 1947 LOG_API(isolate, "Script::Id"); 1948 { 1949 i::HandleScope scope(isolate); 1950 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this); 1951 i::Handle<i::Script> script(i::Script::cast(function_info->script())); 1952 return script->id()->value(); 1953 } 1954 } 1955 1956 1957 int Script::GetLineNumber(int code_pos) { 1958 i::Handle<i::HeapObject> obj = 1959 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this)); 1960 i::Isolate* isolate = obj->GetIsolate(); 1961 ON_BAILOUT(isolate, "v8::Script::GetLineNumber()", return -1); 1962 LOG_API(isolate, "Script::GetLineNumber"); 1963 if (obj->IsScript()) { 1964 i::Handle<i::Script> script = i::Handle<i::Script>(i::Script::cast(*obj)); 1965 return i::GetScriptLineNumber(script, code_pos); 1966 } else { 1967 return -1; 1968 } 1969 } 1970 1971 1972 Handle<Value> Script::GetScriptName() { 1973 i::Handle<i::HeapObject> obj = 1974 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this)); 1975 i::Isolate* isolate = obj->GetIsolate(); 1976 ON_BAILOUT(isolate, "v8::Script::GetName()", return Handle<String>()); 1977 LOG_API(isolate, "Script::GetName"); 1978 if (obj->IsScript()) { 1979 i::Object* name = i::Script::cast(*obj)->name(); 1980 return Utils::ToLocal(i::Handle<i::Object>(name, isolate)); 1981 } else { 1982 return Handle<String>(); 1983 } 1984 } 1985 1986 1987 void Script::SetData(v8::Handle<String> data) { 1988 i::Handle<i::HeapObject> obj = 1989 i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this)); 1990 i::Isolate* isolate = obj->GetIsolate(); 1991 ON_BAILOUT(isolate, "v8::Script::SetData()", return); 1992 LOG_API(isolate, "Script::SetData"); 1993 { 1994 i::HandleScope scope(isolate); 1995 i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this); 1996 i::Handle<i::Object> raw_data = Utils::OpenHandle(*data); 1997 i::Handle<i::Script> script(i::Script::cast(function_info->script())); 1998 script->set_data(*raw_data); 1999 } 2000 } 2001 2002 2003 // --- E x c e p t i o n s --- 2004 2005 2006 v8::TryCatch::TryCatch() 2007 : isolate_(i::Isolate::Current()), 2008 next_(isolate_->try_catch_handler_address()), 2009 is_verbose_(false), 2010 can_continue_(true), 2011 capture_message_(true), 2012 rethrow_(false), 2013 has_terminated_(false) { 2014 Reset(); 2015 isolate_->RegisterTryCatchHandler(this); 2016 } 2017 2018 2019 v8::TryCatch::~TryCatch() { 2020 ASSERT(isolate_ == i::Isolate::Current()); 2021 if (rethrow_) { 2022 v8::Isolate* isolate = reinterpret_cast<Isolate*>(isolate_); 2023 v8::HandleScope scope(isolate); 2024 v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(isolate, Exception()); 2025 if (HasCaught() && capture_message_) { 2026 // If an exception was caught and rethrow_ is indicated, the saved 2027 // message, script, and location need to be restored to Isolate TLS 2028 // for reuse. capture_message_ needs to be disabled so that DoThrow() 2029 // does not create a new message. 2030 isolate_->thread_local_top()->rethrowing_message_ = true; 2031 isolate_->RestorePendingMessageFromTryCatch(this); 2032 } 2033 isolate_->UnregisterTryCatchHandler(this); 2034 reinterpret_cast<Isolate*>(isolate_)->ThrowException(exc); 2035 ASSERT(!isolate_->thread_local_top()->rethrowing_message_); 2036 } else { 2037 isolate_->UnregisterTryCatchHandler(this); 2038 } 2039 } 2040 2041 2042 bool v8::TryCatch::HasCaught() const { 2043 return !reinterpret_cast<i::Object*>(exception_)->IsTheHole(); 2044 } 2045 2046 2047 bool v8::TryCatch::CanContinue() const { 2048 return can_continue_; 2049 } 2050 2051 2052 bool v8::TryCatch::HasTerminated() const { 2053 return has_terminated_; 2054 } 2055 2056 2057 v8::Handle<v8::Value> v8::TryCatch::ReThrow() { 2058 if (!HasCaught()) return v8::Local<v8::Value>(); 2059 rethrow_ = true; 2060 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate_)); 2061 } 2062 2063 2064 v8::Local<Value> v8::TryCatch::Exception() const { 2065 ASSERT(isolate_ == i::Isolate::Current()); 2066 if (HasCaught()) { 2067 // Check for out of memory exception. 2068 i::Object* exception = reinterpret_cast<i::Object*>(exception_); 2069 return v8::Utils::ToLocal(i::Handle<i::Object>(exception, isolate_)); 2070 } else { 2071 return v8::Local<Value>(); 2072 } 2073 } 2074 2075 2076 v8::Local<Value> v8::TryCatch::StackTrace() const { 2077 ASSERT(isolate_ == i::Isolate::Current()); 2078 if (HasCaught()) { 2079 i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_); 2080 if (!raw_obj->IsJSObject()) return v8::Local<Value>(); 2081 i::HandleScope scope(isolate_); 2082 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_); 2083 i::Handle<i::String> name = isolate_->factory()->stack_string(); 2084 if (!i::JSReceiver::HasProperty(obj, name)) return v8::Local<Value>(); 2085 i::Handle<i::Object> value = i::GetProperty(isolate_, obj, name); 2086 if (value.is_null()) return v8::Local<Value>(); 2087 return v8::Utils::ToLocal(scope.CloseAndEscape(value)); 2088 } else { 2089 return v8::Local<Value>(); 2090 } 2091 } 2092 2093 2094 v8::Local<v8::Message> v8::TryCatch::Message() const { 2095 ASSERT(isolate_ == i::Isolate::Current()); 2096 i::Object* message = reinterpret_cast<i::Object*>(message_obj_); 2097 ASSERT(message->IsJSMessageObject() || message->IsTheHole()); 2098 if (HasCaught() && !message->IsTheHole()) { 2099 return v8::Utils::MessageToLocal(i::Handle<i::Object>(message, isolate_)); 2100 } else { 2101 return v8::Local<v8::Message>(); 2102 } 2103 } 2104 2105 2106 void v8::TryCatch::Reset() { 2107 ASSERT(isolate_ == i::Isolate::Current()); 2108 i::Object* the_hole = isolate_->heap()->the_hole_value(); 2109 exception_ = the_hole; 2110 message_obj_ = the_hole; 2111 message_script_ = the_hole; 2112 message_start_pos_ = 0; 2113 message_end_pos_ = 0; 2114 } 2115 2116 2117 void v8::TryCatch::SetVerbose(bool value) { 2118 is_verbose_ = value; 2119 } 2120 2121 2122 void v8::TryCatch::SetCaptureMessage(bool value) { 2123 capture_message_ = value; 2124 } 2125 2126 2127 // --- M e s s a g e --- 2128 2129 2130 Local<String> Message::Get() const { 2131 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2132 ON_BAILOUT(isolate, "v8::Message::Get()", return Local<String>()); 2133 ENTER_V8(isolate); 2134 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2135 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2136 i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(isolate, obj); 2137 Local<String> result = Utils::ToLocal(raw_result); 2138 return scope.Escape(result); 2139 } 2140 2141 2142 v8::Handle<Value> Message::GetScriptResourceName() const { 2143 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2144 ENTER_V8(isolate); 2145 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2146 i::Handle<i::JSMessageObject> message = 2147 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 2148 // Return this.script.name. 2149 i::Handle<i::JSValue> script = 2150 i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(), 2151 isolate)); 2152 i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name(), 2153 isolate); 2154 return scope.Escape(Utils::ToLocal(resource_name)); 2155 } 2156 2157 2158 v8::Handle<Value> Message::GetScriptData() const { 2159 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2160 ENTER_V8(isolate); 2161 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2162 i::Handle<i::JSMessageObject> message = 2163 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 2164 // Return this.script.data. 2165 i::Handle<i::JSValue> script = 2166 i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(), 2167 isolate)); 2168 i::Handle<i::Object> data(i::Script::cast(script->value())->data(), isolate); 2169 return scope.Escape(Utils::ToLocal(data)); 2170 } 2171 2172 2173 v8::Handle<v8::StackTrace> Message::GetStackTrace() const { 2174 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2175 ENTER_V8(isolate); 2176 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2177 i::Handle<i::JSMessageObject> message = 2178 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 2179 i::Handle<i::Object> stackFramesObj(message->stack_frames(), isolate); 2180 if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>(); 2181 i::Handle<i::JSArray> stackTrace = 2182 i::Handle<i::JSArray>::cast(stackFramesObj); 2183 return scope.Escape(Utils::StackTraceToLocal(stackTrace)); 2184 } 2185 2186 2187 static i::Handle<i::Object> CallV8HeapFunction(const char* name, 2188 i::Handle<i::Object> recv, 2189 int argc, 2190 i::Handle<i::Object> argv[], 2191 bool* has_pending_exception) { 2192 i::Isolate* isolate = i::Isolate::Current(); 2193 i::Handle<i::String> fmt_str = 2194 isolate->factory()->InternalizeUtf8String(name); 2195 i::Object* object_fun = 2196 isolate->js_builtins_object()->GetPropertyNoExceptionThrown(*fmt_str); 2197 i::Handle<i::JSFunction> fun = 2198 i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun)); 2199 i::Handle<i::Object> value = i::Execution::Call( 2200 isolate, fun, recv, argc, argv, has_pending_exception); 2201 return value; 2202 } 2203 2204 2205 static i::Handle<i::Object> CallV8HeapFunction(const char* name, 2206 i::Handle<i::Object> data, 2207 bool* has_pending_exception) { 2208 i::Handle<i::Object> argv[] = { data }; 2209 return CallV8HeapFunction(name, 2210 i::Isolate::Current()->js_builtins_object(), 2211 ARRAY_SIZE(argv), 2212 argv, 2213 has_pending_exception); 2214 } 2215 2216 2217 int Message::GetLineNumber() const { 2218 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2219 ON_BAILOUT(isolate, "v8::Message::GetLineNumber()", return kNoLineNumberInfo); 2220 ENTER_V8(isolate); 2221 i::HandleScope scope(isolate); 2222 2223 EXCEPTION_PREAMBLE(isolate); 2224 i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber", 2225 Utils::OpenHandle(this), 2226 &has_pending_exception); 2227 EXCEPTION_BAILOUT_CHECK(isolate, 0); 2228 return static_cast<int>(result->Number()); 2229 } 2230 2231 2232 int Message::GetStartPosition() const { 2233 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2234 ENTER_V8(isolate); 2235 i::HandleScope scope(isolate); 2236 i::Handle<i::JSMessageObject> message = 2237 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 2238 return message->start_position(); 2239 } 2240 2241 2242 int Message::GetEndPosition() const { 2243 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2244 ENTER_V8(isolate); 2245 i::HandleScope scope(isolate); 2246 i::Handle<i::JSMessageObject> message = 2247 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 2248 return message->end_position(); 2249 } 2250 2251 2252 int Message::GetStartColumn() const { 2253 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2254 ENTER_V8(isolate); 2255 i::HandleScope scope(isolate); 2256 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this); 2257 EXCEPTION_PREAMBLE(isolate); 2258 i::Handle<i::Object> start_col_obj = CallV8HeapFunction( 2259 "GetPositionInLine", 2260 data_obj, 2261 &has_pending_exception); 2262 EXCEPTION_BAILOUT_CHECK(isolate, 0); 2263 return static_cast<int>(start_col_obj->Number()); 2264 } 2265 2266 2267 int Message::GetEndColumn() const { 2268 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2269 ENTER_V8(isolate); 2270 i::HandleScope scope(isolate); 2271 i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this); 2272 EXCEPTION_PREAMBLE(isolate); 2273 i::Handle<i::Object> start_col_obj = CallV8HeapFunction( 2274 "GetPositionInLine", 2275 data_obj, 2276 &has_pending_exception); 2277 EXCEPTION_BAILOUT_CHECK(isolate, 0); 2278 i::Handle<i::JSMessageObject> message = 2279 i::Handle<i::JSMessageObject>::cast(data_obj); 2280 int start = message->start_position(); 2281 int end = message->end_position(); 2282 return static_cast<int>(start_col_obj->Number()) + (end - start); 2283 } 2284 2285 2286 bool Message::IsSharedCrossOrigin() const { 2287 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2288 ENTER_V8(isolate); 2289 i::HandleScope scope(isolate); 2290 i::Handle<i::JSMessageObject> message = 2291 i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this)); 2292 i::Handle<i::JSValue> script = 2293 i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(), 2294 isolate)); 2295 return i::Script::cast(script->value())->is_shared_cross_origin(); 2296 } 2297 2298 2299 Local<String> Message::GetSourceLine() const { 2300 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2301 ON_BAILOUT(isolate, "v8::Message::GetSourceLine()", return Local<String>()); 2302 ENTER_V8(isolate); 2303 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2304 EXCEPTION_PREAMBLE(isolate); 2305 i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine", 2306 Utils::OpenHandle(this), 2307 &has_pending_exception); 2308 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::String>()); 2309 if (result->IsString()) { 2310 return scope.Escape(Utils::ToLocal(i::Handle<i::String>::cast(result))); 2311 } else { 2312 return Local<String>(); 2313 } 2314 } 2315 2316 2317 void Message::PrintCurrentStackTrace(Isolate* isolate, FILE* out) { 2318 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 2319 ENTER_V8(i_isolate); 2320 i_isolate->PrintCurrentStackTrace(out); 2321 } 2322 2323 2324 void Message::PrintCurrentStackTrace(FILE* out) { 2325 PrintCurrentStackTrace(Isolate::GetCurrent(), out); 2326 } 2327 2328 2329 // --- S t a c k T r a c e --- 2330 2331 Local<StackFrame> StackTrace::GetFrame(uint32_t index) const { 2332 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2333 ENTER_V8(isolate); 2334 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2335 i::Handle<i::JSArray> self = Utils::OpenHandle(this); 2336 i::Object* raw_object = self->GetElementNoExceptionThrown(isolate, index); 2337 i::Handle<i::JSObject> obj(i::JSObject::cast(raw_object)); 2338 return scope.Escape(Utils::StackFrameToLocal(obj)); 2339 } 2340 2341 2342 int StackTrace::GetFrameCount() const { 2343 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2344 ENTER_V8(isolate); 2345 return i::Smi::cast(Utils::OpenHandle(this)->length())->value(); 2346 } 2347 2348 2349 Local<Array> StackTrace::AsArray() { 2350 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2351 ENTER_V8(isolate); 2352 return Utils::ToLocal(Utils::OpenHandle(this)); 2353 } 2354 2355 2356 Local<StackTrace> StackTrace::CurrentStackTrace( 2357 Isolate* isolate, 2358 int frame_limit, 2359 StackTraceOptions options) { 2360 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 2361 ENTER_V8(i_isolate); 2362 i::Handle<i::JSArray> stackTrace = 2363 i_isolate->CaptureCurrentStackTrace(frame_limit, options); 2364 return Utils::StackTraceToLocal(stackTrace); 2365 } 2366 2367 2368 Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit, 2369 StackTraceOptions options) { 2370 return CurrentStackTrace(Isolate::GetCurrent(), frame_limit, options); 2371 } 2372 2373 2374 // --- S t a c k F r a m e --- 2375 2376 int StackFrame::GetLineNumber() const { 2377 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2378 ENTER_V8(isolate); 2379 i::HandleScope scope(isolate); 2380 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2381 i::Handle<i::Object> line = GetProperty(self, "lineNumber"); 2382 if (!line->IsSmi()) { 2383 return Message::kNoLineNumberInfo; 2384 } 2385 return i::Smi::cast(*line)->value(); 2386 } 2387 2388 2389 int StackFrame::GetColumn() const { 2390 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2391 ENTER_V8(isolate); 2392 i::HandleScope scope(isolate); 2393 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2394 i::Handle<i::Object> column = GetProperty(self, "column"); 2395 if (!column->IsSmi()) { 2396 return Message::kNoColumnInfo; 2397 } 2398 return i::Smi::cast(*column)->value(); 2399 } 2400 2401 2402 int StackFrame::GetScriptId() const { 2403 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2404 ENTER_V8(isolate); 2405 i::HandleScope scope(isolate); 2406 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2407 i::Handle<i::Object> scriptId = GetProperty(self, "scriptId"); 2408 if (!scriptId->IsSmi()) { 2409 return Message::kNoScriptIdInfo; 2410 } 2411 return i::Smi::cast(*scriptId)->value(); 2412 } 2413 2414 2415 Local<String> StackFrame::GetScriptName() const { 2416 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2417 ENTER_V8(isolate); 2418 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2419 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2420 i::Handle<i::Object> name = GetProperty(self, "scriptName"); 2421 if (!name->IsString()) { 2422 return Local<String>(); 2423 } 2424 return scope.Escape(Local<String>::Cast(Utils::ToLocal(name))); 2425 } 2426 2427 2428 Local<String> StackFrame::GetScriptNameOrSourceURL() const { 2429 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2430 ENTER_V8(isolate); 2431 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2432 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2433 i::Handle<i::Object> name = GetProperty(self, "scriptNameOrSourceURL"); 2434 if (!name->IsString()) { 2435 return Local<String>(); 2436 } 2437 return scope.Escape(Local<String>::Cast(Utils::ToLocal(name))); 2438 } 2439 2440 2441 Local<String> StackFrame::GetFunctionName() const { 2442 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2443 ENTER_V8(isolate); 2444 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 2445 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2446 i::Handle<i::Object> name = GetProperty(self, "functionName"); 2447 if (!name->IsString()) { 2448 return Local<String>(); 2449 } 2450 return scope.Escape(Local<String>::Cast(Utils::ToLocal(name))); 2451 } 2452 2453 2454 bool StackFrame::IsEval() const { 2455 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2456 ENTER_V8(isolate); 2457 i::HandleScope scope(isolate); 2458 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2459 i::Handle<i::Object> is_eval = GetProperty(self, "isEval"); 2460 return is_eval->IsTrue(); 2461 } 2462 2463 2464 bool StackFrame::IsConstructor() const { 2465 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 2466 ENTER_V8(isolate); 2467 i::HandleScope scope(isolate); 2468 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 2469 i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor"); 2470 return is_constructor->IsTrue(); 2471 } 2472 2473 2474 // --- J S O N --- 2475 2476 Local<Value> JSON::Parse(Local<String> json_string) { 2477 i::Isolate* isolate = i::Isolate::Current(); 2478 EnsureInitializedForIsolate(isolate, "v8::JSON::Parse"); 2479 ENTER_V8(isolate); 2480 i::HandleScope scope(isolate); 2481 i::Handle<i::String> source = i::Handle<i::String>( 2482 FlattenGetString(Utils::OpenHandle(*json_string))); 2483 EXCEPTION_PREAMBLE(isolate); 2484 i::Handle<i::Object> result; 2485 if (source->IsSeqOneByteString()) { 2486 result = i::JsonParser<true>::Parse(source); 2487 } else { 2488 result = i::JsonParser<false>::Parse(source); 2489 } 2490 has_pending_exception = result.is_null(); 2491 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>()); 2492 return Utils::ToLocal( 2493 i::Handle<i::Object>::cast(scope.CloseAndEscape(result))); 2494 } 2495 2496 2497 // --- D a t a --- 2498 2499 bool Value::FullIsUndefined() const { 2500 bool result = Utils::OpenHandle(this)->IsUndefined(); 2501 ASSERT_EQ(result, QuickIsUndefined()); 2502 return result; 2503 } 2504 2505 2506 bool Value::FullIsNull() const { 2507 bool result = Utils::OpenHandle(this)->IsNull(); 2508 ASSERT_EQ(result, QuickIsNull()); 2509 return result; 2510 } 2511 2512 2513 bool Value::IsTrue() const { 2514 return Utils::OpenHandle(this)->IsTrue(); 2515 } 2516 2517 2518 bool Value::IsFalse() const { 2519 return Utils::OpenHandle(this)->IsFalse(); 2520 } 2521 2522 2523 bool Value::IsFunction() const { 2524 return Utils::OpenHandle(this)->IsJSFunction(); 2525 } 2526 2527 2528 bool Value::FullIsString() const { 2529 bool result = Utils::OpenHandle(this)->IsString(); 2530 ASSERT_EQ(result, QuickIsString()); 2531 return result; 2532 } 2533 2534 2535 bool Value::IsSymbol() const { 2536 return Utils::OpenHandle(this)->IsSymbol(); 2537 } 2538 2539 2540 bool Value::IsArray() const { 2541 return Utils::OpenHandle(this)->IsJSArray(); 2542 } 2543 2544 2545 bool Value::IsArrayBuffer() const { 2546 return Utils::OpenHandle(this)->IsJSArrayBuffer(); 2547 } 2548 2549 2550 bool Value::IsArrayBufferView() const { 2551 return Utils::OpenHandle(this)->IsJSArrayBufferView(); 2552 } 2553 2554 2555 bool Value::IsTypedArray() const { 2556 return Utils::OpenHandle(this)->IsJSTypedArray(); 2557 } 2558 2559 2560 #define TYPED_ARRAY_LIST(F) \ 2561 F(Uint8Array, kExternalUnsignedByteArray) \ 2562 F(Int8Array, kExternalByteArray) \ 2563 F(Uint16Array, kExternalUnsignedShortArray) \ 2564 F(Int16Array, kExternalShortArray) \ 2565 F(Uint32Array, kExternalUnsignedIntArray) \ 2566 F(Int32Array, kExternalIntArray) \ 2567 F(Float32Array, kExternalFloatArray) \ 2568 F(Float64Array, kExternalDoubleArray) \ 2569 F(Uint8ClampedArray, kExternalPixelArray) 2570 2571 2572 #define VALUE_IS_TYPED_ARRAY(TypedArray, type_const) \ 2573 bool Value::Is##TypedArray() const { \ 2574 i::Handle<i::Object> obj = Utils::OpenHandle(this); \ 2575 if (!obj->IsJSTypedArray()) return false; \ 2576 return i::JSTypedArray::cast(*obj)->type() == type_const; \ 2577 } 2578 2579 TYPED_ARRAY_LIST(VALUE_IS_TYPED_ARRAY) 2580 2581 #undef VALUE_IS_TYPED_ARRAY 2582 2583 2584 bool Value::IsDataView() const { 2585 return Utils::OpenHandle(this)->IsJSDataView(); 2586 } 2587 2588 2589 bool Value::IsObject() const { 2590 return Utils::OpenHandle(this)->IsJSObject(); 2591 } 2592 2593 2594 bool Value::IsNumber() const { 2595 return Utils::OpenHandle(this)->IsNumber(); 2596 } 2597 2598 2599 bool Value::IsBoolean() const { 2600 return Utils::OpenHandle(this)->IsBoolean(); 2601 } 2602 2603 2604 bool Value::IsExternal() const { 2605 return Utils::OpenHandle(this)->IsExternal(); 2606 } 2607 2608 2609 bool Value::IsInt32() const { 2610 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2611 if (obj->IsSmi()) return true; 2612 if (obj->IsNumber()) { 2613 double value = obj->Number(); 2614 static const i::DoubleRepresentation minus_zero(-0.0); 2615 i::DoubleRepresentation rep(value); 2616 if (rep.bits == minus_zero.bits) { 2617 return false; 2618 } 2619 return i::FastI2D(i::FastD2I(value)) == value; 2620 } 2621 return false; 2622 } 2623 2624 2625 bool Value::IsUint32() const { 2626 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2627 if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0; 2628 if (obj->IsNumber()) { 2629 double value = obj->Number(); 2630 static const i::DoubleRepresentation minus_zero(-0.0); 2631 i::DoubleRepresentation rep(value); 2632 if (rep.bits == minus_zero.bits) { 2633 return false; 2634 } 2635 return i::FastUI2D(i::FastD2UI(value)) == value; 2636 } 2637 return false; 2638 } 2639 2640 2641 bool Value::IsDate() const { 2642 i::Isolate* isolate = i::Isolate::Current(); 2643 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2644 return obj->HasSpecificClassOf(isolate->heap()->Date_string()); 2645 } 2646 2647 2648 bool Value::IsStringObject() const { 2649 i::Isolate* isolate = i::Isolate::Current(); 2650 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2651 return obj->HasSpecificClassOf(isolate->heap()->String_string()); 2652 } 2653 2654 2655 bool Value::IsSymbolObject() const { 2656 // TODO(svenpanne): these and other test functions should be written such 2657 // that they do not use Isolate::Current(). 2658 i::Isolate* isolate = i::Isolate::Current(); 2659 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2660 return obj->HasSpecificClassOf(isolate->heap()->Symbol_string()); 2661 } 2662 2663 2664 bool Value::IsNumberObject() const { 2665 i::Isolate* isolate = i::Isolate::Current(); 2666 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2667 return obj->HasSpecificClassOf(isolate->heap()->Number_string()); 2668 } 2669 2670 2671 static i::Object* LookupBuiltin(i::Isolate* isolate, 2672 const char* builtin_name) { 2673 i::Handle<i::String> string = 2674 isolate->factory()->InternalizeUtf8String(builtin_name); 2675 i::Handle<i::JSBuiltinsObject> builtins = isolate->js_builtins_object(); 2676 return builtins->GetPropertyNoExceptionThrown(*string); 2677 } 2678 2679 2680 static bool CheckConstructor(i::Isolate* isolate, 2681 i::Handle<i::JSObject> obj, 2682 const char* class_name) { 2683 i::Object* constr = obj->map()->constructor(); 2684 if (!constr->IsJSFunction()) return false; 2685 i::JSFunction* func = i::JSFunction::cast(constr); 2686 return func->shared()->native() && 2687 constr == LookupBuiltin(isolate, class_name); 2688 } 2689 2690 2691 bool Value::IsNativeError() const { 2692 i::Isolate* isolate = i::Isolate::Current(); 2693 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2694 if (obj->IsJSObject()) { 2695 i::Handle<i::JSObject> js_obj(i::JSObject::cast(*obj)); 2696 return CheckConstructor(isolate, js_obj, "$Error") || 2697 CheckConstructor(isolate, js_obj, "$EvalError") || 2698 CheckConstructor(isolate, js_obj, "$RangeError") || 2699 CheckConstructor(isolate, js_obj, "$ReferenceError") || 2700 CheckConstructor(isolate, js_obj, "$SyntaxError") || 2701 CheckConstructor(isolate, js_obj, "$TypeError") || 2702 CheckConstructor(isolate, js_obj, "$URIError"); 2703 } else { 2704 return false; 2705 } 2706 } 2707 2708 2709 bool Value::IsBooleanObject() const { 2710 i::Isolate* isolate = i::Isolate::Current(); 2711 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2712 return obj->HasSpecificClassOf(isolate->heap()->Boolean_string()); 2713 } 2714 2715 2716 bool Value::IsRegExp() const { 2717 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2718 return obj->IsJSRegExp(); 2719 } 2720 2721 2722 Local<String> Value::ToString() const { 2723 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2724 i::Handle<i::Object> str; 2725 if (obj->IsString()) { 2726 str = obj; 2727 } else { 2728 i::Isolate* isolate = i::Isolate::Current(); 2729 LOG_API(isolate, "ToString"); 2730 ENTER_V8(isolate); 2731 EXCEPTION_PREAMBLE(isolate); 2732 str = i::Execution::ToString(isolate, obj, &has_pending_exception); 2733 EXCEPTION_BAILOUT_CHECK(isolate, Local<String>()); 2734 } 2735 return ToApiHandle<String>(str); 2736 } 2737 2738 2739 Local<String> Value::ToDetailString() const { 2740 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2741 i::Handle<i::Object> str; 2742 if (obj->IsString()) { 2743 str = obj; 2744 } else { 2745 i::Isolate* isolate = i::Isolate::Current(); 2746 LOG_API(isolate, "ToDetailString"); 2747 ENTER_V8(isolate); 2748 EXCEPTION_PREAMBLE(isolate); 2749 str = i::Execution::ToDetailString(isolate, obj, &has_pending_exception); 2750 EXCEPTION_BAILOUT_CHECK(isolate, Local<String>()); 2751 } 2752 return ToApiHandle<String>(str); 2753 } 2754 2755 2756 Local<v8::Object> Value::ToObject() const { 2757 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2758 i::Handle<i::Object> val; 2759 if (obj->IsJSObject()) { 2760 val = obj; 2761 } else { 2762 i::Isolate* isolate = i::Isolate::Current(); 2763 LOG_API(isolate, "ToObject"); 2764 ENTER_V8(isolate); 2765 EXCEPTION_PREAMBLE(isolate); 2766 val = i::Execution::ToObject(isolate, obj, &has_pending_exception); 2767 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); 2768 } 2769 return ToApiHandle<Object>(val); 2770 } 2771 2772 2773 Local<Boolean> Value::ToBoolean() const { 2774 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2775 if (obj->IsBoolean()) { 2776 return ToApiHandle<Boolean>(obj); 2777 } else { 2778 i::Isolate* isolate = i::Isolate::Current(); 2779 LOG_API(isolate, "ToBoolean"); 2780 ENTER_V8(isolate); 2781 i::Handle<i::Object> val = 2782 isolate->factory()->ToBoolean(obj->BooleanValue()); 2783 return ToApiHandle<Boolean>(val); 2784 } 2785 } 2786 2787 2788 Local<Number> Value::ToNumber() const { 2789 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2790 i::Handle<i::Object> num; 2791 if (obj->IsNumber()) { 2792 num = obj; 2793 } else { 2794 i::Isolate* isolate = i::Isolate::Current(); 2795 LOG_API(isolate, "ToNumber"); 2796 ENTER_V8(isolate); 2797 EXCEPTION_PREAMBLE(isolate); 2798 num = i::Execution::ToNumber(isolate, obj, &has_pending_exception); 2799 EXCEPTION_BAILOUT_CHECK(isolate, Local<Number>()); 2800 } 2801 return ToApiHandle<Number>(num); 2802 } 2803 2804 2805 Local<Integer> Value::ToInteger() const { 2806 i::Handle<i::Object> obj = Utils::OpenHandle(this); 2807 i::Handle<i::Object> num; 2808 if (obj->IsSmi()) { 2809 num = obj; 2810 } else { 2811 i::Isolate* isolate = i::Isolate::Current(); 2812 LOG_API(isolate, "ToInteger"); 2813 ENTER_V8(isolate); 2814 EXCEPTION_PREAMBLE(isolate); 2815 num = i::Execution::ToInteger(isolate, obj, &has_pending_exception); 2816 EXCEPTION_BAILOUT_CHECK(isolate, Local<Integer>()); 2817 } 2818 return ToApiHandle<Integer>(num); 2819 } 2820 2821 2822 void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) { 2823 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate); 2824 ApiCheck(isolate != NULL && isolate->IsInitialized() && !isolate->IsDead(), 2825 "v8::internal::Internals::CheckInitialized()", 2826 "Isolate is not initialized or V8 has died"); 2827 } 2828 2829 2830 void External::CheckCast(v8::Value* that) { 2831 ApiCheck(Utils::OpenHandle(that)->IsExternal(), 2832 "v8::External::Cast()", 2833 "Could not convert to external"); 2834 } 2835 2836 2837 void v8::Object::CheckCast(Value* that) { 2838 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2839 ApiCheck(obj->IsJSObject(), 2840 "v8::Object::Cast()", 2841 "Could not convert to object"); 2842 } 2843 2844 2845 void v8::Function::CheckCast(Value* that) { 2846 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2847 ApiCheck(obj->IsJSFunction(), 2848 "v8::Function::Cast()", 2849 "Could not convert to function"); 2850 } 2851 2852 2853 void v8::String::CheckCast(v8::Value* that) { 2854 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2855 ApiCheck(obj->IsString(), 2856 "v8::String::Cast()", 2857 "Could not convert to string"); 2858 } 2859 2860 2861 void v8::Symbol::CheckCast(v8::Value* that) { 2862 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2863 ApiCheck(obj->IsSymbol(), 2864 "v8::Symbol::Cast()", 2865 "Could not convert to symbol"); 2866 } 2867 2868 2869 void v8::Number::CheckCast(v8::Value* that) { 2870 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2871 ApiCheck(obj->IsNumber(), 2872 "v8::Number::Cast()", 2873 "Could not convert to number"); 2874 } 2875 2876 2877 void v8::Integer::CheckCast(v8::Value* that) { 2878 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2879 ApiCheck(obj->IsNumber(), 2880 "v8::Integer::Cast()", 2881 "Could not convert to number"); 2882 } 2883 2884 2885 void v8::Array::CheckCast(Value* that) { 2886 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2887 ApiCheck(obj->IsJSArray(), 2888 "v8::Array::Cast()", 2889 "Could not convert to array"); 2890 } 2891 2892 2893 void v8::ArrayBuffer::CheckCast(Value* that) { 2894 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2895 ApiCheck(obj->IsJSArrayBuffer(), 2896 "v8::ArrayBuffer::Cast()", 2897 "Could not convert to ArrayBuffer"); 2898 } 2899 2900 2901 void v8::ArrayBufferView::CheckCast(Value* that) { 2902 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2903 ApiCheck(obj->IsJSArrayBufferView(), 2904 "v8::ArrayBufferView::Cast()", 2905 "Could not convert to ArrayBufferView"); 2906 } 2907 2908 2909 void v8::TypedArray::CheckCast(Value* that) { 2910 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2911 ApiCheck(obj->IsJSTypedArray(), 2912 "v8::TypedArray::Cast()", 2913 "Could not convert to TypedArray"); 2914 } 2915 2916 2917 #define CHECK_TYPED_ARRAY_CAST(ApiClass, typeConst) \ 2918 void v8::ApiClass::CheckCast(Value* that) { \ 2919 i::Handle<i::Object> obj = Utils::OpenHandle(that); \ 2920 ApiCheck(obj->IsJSTypedArray() && \ 2921 i::JSTypedArray::cast(*obj)->type() == typeConst, \ 2922 "v8::" #ApiClass "::Cast()", \ 2923 "Could not convert to " #ApiClass); \ 2924 } 2925 2926 2927 TYPED_ARRAY_LIST(CHECK_TYPED_ARRAY_CAST) 2928 2929 #undef CHECK_TYPED_ARRAY_CAST 2930 2931 2932 void v8::DataView::CheckCast(Value* that) { 2933 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2934 ApiCheck(obj->IsJSDataView(), 2935 "v8::DataView::Cast()", 2936 "Could not convert to DataView"); 2937 } 2938 2939 2940 void v8::Date::CheckCast(v8::Value* that) { 2941 i::Isolate* isolate = i::Isolate::Current(); 2942 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2943 ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Date_string()), 2944 "v8::Date::Cast()", 2945 "Could not convert to date"); 2946 } 2947 2948 2949 void v8::StringObject::CheckCast(v8::Value* that) { 2950 i::Isolate* isolate = i::Isolate::Current(); 2951 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2952 ApiCheck(obj->HasSpecificClassOf(isolate->heap()->String_string()), 2953 "v8::StringObject::Cast()", 2954 "Could not convert to StringObject"); 2955 } 2956 2957 2958 void v8::SymbolObject::CheckCast(v8::Value* that) { 2959 i::Isolate* isolate = i::Isolate::Current(); 2960 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2961 ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Symbol_string()), 2962 "v8::SymbolObject::Cast()", 2963 "Could not convert to SymbolObject"); 2964 } 2965 2966 2967 void v8::NumberObject::CheckCast(v8::Value* that) { 2968 i::Isolate* isolate = i::Isolate::Current(); 2969 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2970 ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Number_string()), 2971 "v8::NumberObject::Cast()", 2972 "Could not convert to NumberObject"); 2973 } 2974 2975 2976 void v8::BooleanObject::CheckCast(v8::Value* that) { 2977 i::Isolate* isolate = i::Isolate::Current(); 2978 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2979 ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Boolean_string()), 2980 "v8::BooleanObject::Cast()", 2981 "Could not convert to BooleanObject"); 2982 } 2983 2984 2985 void v8::RegExp::CheckCast(v8::Value* that) { 2986 i::Handle<i::Object> obj = Utils::OpenHandle(that); 2987 ApiCheck(obj->IsJSRegExp(), 2988 "v8::RegExp::Cast()", 2989 "Could not convert to regular expression"); 2990 } 2991 2992 2993 bool Value::BooleanValue() const { 2994 return Utils::OpenHandle(this)->BooleanValue(); 2995 } 2996 2997 2998 double Value::NumberValue() const { 2999 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3000 i::Handle<i::Object> num; 3001 if (obj->IsNumber()) { 3002 num = obj; 3003 } else { 3004 i::Isolate* isolate = i::Isolate::Current(); 3005 LOG_API(isolate, "NumberValue"); 3006 ENTER_V8(isolate); 3007 EXCEPTION_PREAMBLE(isolate); 3008 num = i::Execution::ToNumber(isolate, obj, &has_pending_exception); 3009 EXCEPTION_BAILOUT_CHECK(isolate, i::OS::nan_value()); 3010 } 3011 return num->Number(); 3012 } 3013 3014 3015 int64_t Value::IntegerValue() const { 3016 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3017 i::Handle<i::Object> num; 3018 if (obj->IsNumber()) { 3019 num = obj; 3020 } else { 3021 i::Isolate* isolate = i::Isolate::Current(); 3022 LOG_API(isolate, "IntegerValue"); 3023 ENTER_V8(isolate); 3024 EXCEPTION_PREAMBLE(isolate); 3025 num = i::Execution::ToInteger(isolate, obj, &has_pending_exception); 3026 EXCEPTION_BAILOUT_CHECK(isolate, 0); 3027 } 3028 if (num->IsSmi()) { 3029 return i::Smi::cast(*num)->value(); 3030 } else { 3031 return static_cast<int64_t>(num->Number()); 3032 } 3033 } 3034 3035 3036 Local<Int32> Value::ToInt32() const { 3037 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3038 i::Handle<i::Object> num; 3039 if (obj->IsSmi()) { 3040 num = obj; 3041 } else { 3042 i::Isolate* isolate = i::Isolate::Current(); 3043 LOG_API(isolate, "ToInt32"); 3044 ENTER_V8(isolate); 3045 EXCEPTION_PREAMBLE(isolate); 3046 num = i::Execution::ToInt32(isolate, obj, &has_pending_exception); 3047 EXCEPTION_BAILOUT_CHECK(isolate, Local<Int32>()); 3048 } 3049 return ToApiHandle<Int32>(num); 3050 } 3051 3052 3053 Local<Uint32> Value::ToUint32() const { 3054 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3055 i::Handle<i::Object> num; 3056 if (obj->IsSmi()) { 3057 num = obj; 3058 } else { 3059 i::Isolate* isolate = i::Isolate::Current(); 3060 LOG_API(isolate, "ToUInt32"); 3061 ENTER_V8(isolate); 3062 EXCEPTION_PREAMBLE(isolate); 3063 num = i::Execution::ToUint32(isolate, obj, &has_pending_exception); 3064 EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>()); 3065 } 3066 return ToApiHandle<Uint32>(num); 3067 } 3068 3069 3070 Local<Uint32> Value::ToArrayIndex() const { 3071 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3072 if (obj->IsSmi()) { 3073 if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj); 3074 return Local<Uint32>(); 3075 } 3076 i::Isolate* isolate = i::Isolate::Current(); 3077 LOG_API(isolate, "ToArrayIndex"); 3078 ENTER_V8(isolate); 3079 EXCEPTION_PREAMBLE(isolate); 3080 i::Handle<i::Object> string_obj = 3081 i::Execution::ToString(isolate, obj, &has_pending_exception); 3082 EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>()); 3083 i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj); 3084 uint32_t index; 3085 if (str->AsArrayIndex(&index)) { 3086 i::Handle<i::Object> value; 3087 if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) { 3088 value = i::Handle<i::Object>(i::Smi::FromInt(index), isolate); 3089 } else { 3090 value = isolate->factory()->NewNumber(index); 3091 } 3092 return Utils::Uint32ToLocal(value); 3093 } 3094 return Local<Uint32>(); 3095 } 3096 3097 3098 int32_t Value::Int32Value() const { 3099 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3100 if (obj->IsSmi()) { 3101 return i::Smi::cast(*obj)->value(); 3102 } else { 3103 i::Isolate* isolate = i::Isolate::Current(); 3104 LOG_API(isolate, "Int32Value (slow)"); 3105 ENTER_V8(isolate); 3106 EXCEPTION_PREAMBLE(isolate); 3107 i::Handle<i::Object> num = 3108 i::Execution::ToInt32(isolate, obj, &has_pending_exception); 3109 EXCEPTION_BAILOUT_CHECK(isolate, 0); 3110 if (num->IsSmi()) { 3111 return i::Smi::cast(*num)->value(); 3112 } else { 3113 return static_cast<int32_t>(num->Number()); 3114 } 3115 } 3116 } 3117 3118 3119 bool Value::Equals(Handle<Value> that) const { 3120 i::Isolate* isolate = i::Isolate::Current(); 3121 if (EmptyCheck("v8::Value::Equals()", this) || 3122 EmptyCheck("v8::Value::Equals()", that)) { 3123 return false; 3124 } 3125 LOG_API(isolate, "Equals"); 3126 ENTER_V8(isolate); 3127 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3128 i::Handle<i::Object> other = Utils::OpenHandle(*that); 3129 // If both obj and other are JSObjects, we'd better compare by identity 3130 // immediately when going into JS builtin. The reason is Invoke 3131 // would overwrite global object receiver with global proxy. 3132 if (obj->IsJSObject() && other->IsJSObject()) { 3133 return *obj == *other; 3134 } 3135 i::Handle<i::Object> args[] = { other }; 3136 EXCEPTION_PREAMBLE(isolate); 3137 i::Handle<i::Object> result = 3138 CallV8HeapFunction("EQUALS", obj, ARRAY_SIZE(args), args, 3139 &has_pending_exception); 3140 EXCEPTION_BAILOUT_CHECK(isolate, false); 3141 return *result == i::Smi::FromInt(i::EQUAL); 3142 } 3143 3144 3145 bool Value::StrictEquals(Handle<Value> that) const { 3146 i::Isolate* isolate = i::Isolate::Current(); 3147 if (EmptyCheck("v8::Value::StrictEquals()", this) || 3148 EmptyCheck("v8::Value::StrictEquals()", that)) { 3149 return false; 3150 } 3151 LOG_API(isolate, "StrictEquals"); 3152 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3153 i::Handle<i::Object> other = Utils::OpenHandle(*that); 3154 // Must check HeapNumber first, since NaN !== NaN. 3155 if (obj->IsHeapNumber()) { 3156 if (!other->IsNumber()) return false; 3157 double x = obj->Number(); 3158 double y = other->Number(); 3159 // Must check explicitly for NaN:s on Windows, but -0 works fine. 3160 return x == y && !std::isnan(x) && !std::isnan(y); 3161 } else if (*obj == *other) { // Also covers Booleans. 3162 return true; 3163 } else if (obj->IsSmi()) { 3164 return other->IsNumber() && obj->Number() == other->Number(); 3165 } else if (obj->IsString()) { 3166 return other->IsString() && 3167 i::String::cast(*obj)->Equals(i::String::cast(*other)); 3168 } else if (obj->IsUndefined() || obj->IsUndetectableObject()) { 3169 return other->IsUndefined() || other->IsUndetectableObject(); 3170 } else { 3171 return false; 3172 } 3173 } 3174 3175 3176 bool Value::SameValue(Handle<Value> that) const { 3177 i::Isolate* isolate = i::Isolate::Current(); 3178 if (EmptyCheck("v8::Value::SameValue()", this) || 3179 EmptyCheck("v8::Value::SameValue()", that)) { 3180 return false; 3181 } 3182 LOG_API(isolate, "SameValue"); 3183 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3184 i::Handle<i::Object> other = Utils::OpenHandle(*that); 3185 return obj->SameValue(*other); 3186 } 3187 3188 3189 uint32_t Value::Uint32Value() const { 3190 i::Handle<i::Object> obj = Utils::OpenHandle(this); 3191 if (obj->IsSmi()) { 3192 return i::Smi::cast(*obj)->value(); 3193 } else { 3194 i::Isolate* isolate = i::Isolate::Current(); 3195 LOG_API(isolate, "Uint32Value"); 3196 ENTER_V8(isolate); 3197 EXCEPTION_PREAMBLE(isolate); 3198 i::Handle<i::Object> num = 3199 i::Execution::ToUint32(isolate, obj, &has_pending_exception); 3200 EXCEPTION_BAILOUT_CHECK(isolate, 0); 3201 if (num->IsSmi()) { 3202 return i::Smi::cast(*num)->value(); 3203 } else { 3204 return static_cast<uint32_t>(num->Number()); 3205 } 3206 } 3207 } 3208 3209 3210 bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value, 3211 v8::PropertyAttribute attribs) { 3212 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3213 ON_BAILOUT(isolate, "v8::Object::Set()", return false); 3214 ENTER_V8(isolate); 3215 i::HandleScope scope(isolate); 3216 i::Handle<i::Object> self = Utils::OpenHandle(this); 3217 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 3218 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 3219 EXCEPTION_PREAMBLE(isolate); 3220 i::Handle<i::Object> obj = i::Runtime::SetObjectProperty( 3221 isolate, 3222 self, 3223 key_obj, 3224 value_obj, 3225 static_cast<PropertyAttributes>(attribs), 3226 i::kNonStrictMode); 3227 has_pending_exception = obj.is_null(); 3228 EXCEPTION_BAILOUT_CHECK(isolate, false); 3229 return true; 3230 } 3231 3232 3233 bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) { 3234 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3235 ON_BAILOUT(isolate, "v8::Object::Set()", return false); 3236 ENTER_V8(isolate); 3237 i::HandleScope scope(isolate); 3238 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3239 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 3240 EXCEPTION_PREAMBLE(isolate); 3241 i::Handle<i::Object> obj = i::JSObject::SetElement( 3242 self, 3243 index, 3244 value_obj, 3245 NONE, 3246 i::kNonStrictMode); 3247 has_pending_exception = obj.is_null(); 3248 EXCEPTION_BAILOUT_CHECK(isolate, false); 3249 return true; 3250 } 3251 3252 3253 bool v8::Object::ForceSet(v8::Handle<Value> key, 3254 v8::Handle<Value> value, 3255 v8::PropertyAttribute attribs) { 3256 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3257 ON_BAILOUT(isolate, "v8::Object::ForceSet()", return false); 3258 ENTER_V8(isolate); 3259 i::HandleScope scope(isolate); 3260 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3261 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 3262 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 3263 EXCEPTION_PREAMBLE(isolate); 3264 i::Handle<i::Object> obj = i::ForceSetProperty( 3265 self, 3266 key_obj, 3267 value_obj, 3268 static_cast<PropertyAttributes>(attribs)); 3269 has_pending_exception = obj.is_null(); 3270 EXCEPTION_BAILOUT_CHECK(isolate, false); 3271 return true; 3272 } 3273 3274 3275 bool v8::Object::SetPrivate(v8::Handle<Private> key, v8::Handle<Value> value) { 3276 return Set(v8::Handle<Value>(reinterpret_cast<Value*>(*key)), 3277 value, DontEnum); 3278 } 3279 3280 3281 bool v8::Object::ForceDelete(v8::Handle<Value> key) { 3282 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3283 ON_BAILOUT(isolate, "v8::Object::ForceDelete()", return false); 3284 ENTER_V8(isolate); 3285 i::HandleScope scope(isolate); 3286 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3287 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 3288 3289 // When deleting a property on the global object using ForceDelete 3290 // deoptimize all functions as optimized code does not check for the hole 3291 // value with DontDelete properties. We have to deoptimize all contexts 3292 // because of possible cross-context inlined functions. 3293 if (self->IsJSGlobalProxy() || self->IsGlobalObject()) { 3294 i::Deoptimizer::DeoptimizeAll(isolate); 3295 } 3296 3297 EXCEPTION_PREAMBLE(isolate); 3298 i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj); 3299 has_pending_exception = obj.is_null(); 3300 EXCEPTION_BAILOUT_CHECK(isolate, false); 3301 return obj->IsTrue(); 3302 } 3303 3304 3305 Local<Value> v8::Object::Get(v8::Handle<Value> key) { 3306 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3307 ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>()); 3308 ENTER_V8(isolate); 3309 i::Handle<i::Object> self = Utils::OpenHandle(this); 3310 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 3311 EXCEPTION_PREAMBLE(isolate); 3312 i::Handle<i::Object> result = i::GetProperty(isolate, self, key_obj); 3313 has_pending_exception = result.is_null(); 3314 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 3315 return Utils::ToLocal(result); 3316 } 3317 3318 3319 Local<Value> v8::Object::Get(uint32_t index) { 3320 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3321 ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>()); 3322 ENTER_V8(isolate); 3323 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3324 EXCEPTION_PREAMBLE(isolate); 3325 i::Handle<i::Object> result = i::Object::GetElement(isolate, self, index); 3326 has_pending_exception = result.is_null(); 3327 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 3328 return Utils::ToLocal(result); 3329 } 3330 3331 3332 Local<Value> v8::Object::GetPrivate(v8::Handle<Private> key) { 3333 return Get(v8::Handle<Value>(reinterpret_cast<Value*>(*key))); 3334 } 3335 3336 3337 PropertyAttribute v8::Object::GetPropertyAttributes(v8::Handle<Value> key) { 3338 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3339 ON_BAILOUT(isolate, "v8::Object::GetPropertyAttribute()", 3340 return static_cast<PropertyAttribute>(NONE)); 3341 ENTER_V8(isolate); 3342 i::HandleScope scope(isolate); 3343 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3344 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 3345 if (!key_obj->IsName()) { 3346 EXCEPTION_PREAMBLE(isolate); 3347 key_obj = i::Execution::ToString(isolate, key_obj, &has_pending_exception); 3348 EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE)); 3349 } 3350 i::Handle<i::Name> key_name = i::Handle<i::Name>::cast(key_obj); 3351 PropertyAttributes result = self->GetPropertyAttribute(*key_name); 3352 if (result == ABSENT) return static_cast<PropertyAttribute>(NONE); 3353 return static_cast<PropertyAttribute>(result); 3354 } 3355 3356 3357 Local<Value> v8::Object::GetPrototype() { 3358 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3359 ON_BAILOUT(isolate, "v8::Object::GetPrototype()", 3360 return Local<v8::Value>()); 3361 ENTER_V8(isolate); 3362 i::Handle<i::Object> self = Utils::OpenHandle(this); 3363 i::Handle<i::Object> result(self->GetPrototype(isolate), isolate); 3364 return Utils::ToLocal(result); 3365 } 3366 3367 3368 bool v8::Object::SetPrototype(Handle<Value> value) { 3369 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3370 ON_BAILOUT(isolate, "v8::Object::SetPrototype()", return false); 3371 ENTER_V8(isolate); 3372 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3373 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 3374 // We do not allow exceptions thrown while setting the prototype 3375 // to propagate outside. 3376 TryCatch try_catch; 3377 EXCEPTION_PREAMBLE(isolate); 3378 i::Handle<i::Object> result = i::JSObject::SetPrototype(self, value_obj); 3379 has_pending_exception = result.is_null(); 3380 EXCEPTION_BAILOUT_CHECK(isolate, false); 3381 return true; 3382 } 3383 3384 3385 Local<Object> v8::Object::FindInstanceInPrototypeChain( 3386 v8::Handle<FunctionTemplate> tmpl) { 3387 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3388 ON_BAILOUT(isolate, 3389 "v8::Object::FindInstanceInPrototypeChain()", 3390 return Local<v8::Object>()); 3391 ENTER_V8(isolate); 3392 i::JSObject* object = *Utils::OpenHandle(this); 3393 i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl); 3394 while (!tmpl_info->IsTemplateFor(object)) { 3395 i::Object* prototype = object->GetPrototype(); 3396 if (!prototype->IsJSObject()) return Local<Object>(); 3397 object = i::JSObject::cast(prototype); 3398 } 3399 return Utils::ToLocal(i::Handle<i::JSObject>(object)); 3400 } 3401 3402 3403 Local<Array> v8::Object::GetPropertyNames() { 3404 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3405 ON_BAILOUT(isolate, "v8::Object::GetPropertyNames()", 3406 return Local<v8::Array>()); 3407 ENTER_V8(isolate); 3408 i::HandleScope scope(isolate); 3409 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3410 bool threw = false; 3411 i::Handle<i::FixedArray> value = 3412 i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS, &threw); 3413 if (threw) return Local<v8::Array>(); 3414 // Because we use caching to speed up enumeration it is important 3415 // to never change the result of the basic enumeration function so 3416 // we clone the result. 3417 i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value); 3418 i::Handle<i::JSArray> result = 3419 isolate->factory()->NewJSArrayWithElements(elms); 3420 return Utils::ToLocal(scope.CloseAndEscape(result)); 3421 } 3422 3423 3424 Local<Array> v8::Object::GetOwnPropertyNames() { 3425 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3426 ON_BAILOUT(isolate, "v8::Object::GetOwnPropertyNames()", 3427 return Local<v8::Array>()); 3428 ENTER_V8(isolate); 3429 i::HandleScope scope(isolate); 3430 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3431 bool threw = false; 3432 i::Handle<i::FixedArray> value = 3433 i::GetKeysInFixedArrayFor(self, i::LOCAL_ONLY, &threw); 3434 if (threw) return Local<v8::Array>(); 3435 // Because we use caching to speed up enumeration it is important 3436 // to never change the result of the basic enumeration function so 3437 // we clone the result. 3438 i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value); 3439 i::Handle<i::JSArray> result = 3440 isolate->factory()->NewJSArrayWithElements(elms); 3441 return Utils::ToLocal(scope.CloseAndEscape(result)); 3442 } 3443 3444 3445 Local<String> v8::Object::ObjectProtoToString() { 3446 i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate(); 3447 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); 3448 ON_BAILOUT(i_isolate, "v8::Object::ObjectProtoToString()", 3449 return Local<v8::String>()); 3450 ENTER_V8(i_isolate); 3451 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3452 3453 i::Handle<i::Object> name(self->class_name(), i_isolate); 3454 3455 // Native implementation of Object.prototype.toString (v8natives.js): 3456 // var c = %_ClassOf(this); 3457 // if (c === 'Arguments') c = 'Object'; 3458 // return "[object " + c + "]"; 3459 3460 if (!name->IsString()) { 3461 return v8::String::NewFromUtf8(isolate, "[object ]"); 3462 } else { 3463 i::Handle<i::String> class_name = i::Handle<i::String>::cast(name); 3464 if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Arguments"))) { 3465 return v8::String::NewFromUtf8(isolate, "[object Object]"); 3466 } else { 3467 const char* prefix = "[object "; 3468 Local<String> str = Utils::ToLocal(class_name); 3469 const char* postfix = "]"; 3470 3471 int prefix_len = i::StrLength(prefix); 3472 int str_len = str->Utf8Length(); 3473 int postfix_len = i::StrLength(postfix); 3474 3475 int buf_len = prefix_len + str_len + postfix_len; 3476 i::ScopedVector<char> buf(buf_len); 3477 3478 // Write prefix. 3479 char* ptr = buf.start(); 3480 i::OS::MemCopy(ptr, prefix, prefix_len * v8::internal::kCharSize); 3481 ptr += prefix_len; 3482 3483 // Write real content. 3484 str->WriteUtf8(ptr, str_len); 3485 ptr += str_len; 3486 3487 // Write postfix. 3488 i::OS::MemCopy(ptr, postfix, postfix_len * v8::internal::kCharSize); 3489 3490 // Copy the buffer into a heap-allocated string and return it. 3491 Local<String> result = v8::String::NewFromUtf8( 3492 isolate, buf.start(), String::kNormalString, buf_len); 3493 return result; 3494 } 3495 } 3496 } 3497 3498 3499 Local<Value> v8::Object::GetConstructor() { 3500 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3501 ON_BAILOUT(isolate, "v8::Object::GetConstructor()", 3502 return Local<v8::Function>()); 3503 ENTER_V8(isolate); 3504 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3505 i::Handle<i::Object> constructor(self->GetConstructor(), isolate); 3506 return Utils::ToLocal(constructor); 3507 } 3508 3509 3510 Local<String> v8::Object::GetConstructorName() { 3511 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3512 ON_BAILOUT(isolate, "v8::Object::GetConstructorName()", 3513 return Local<v8::String>()); 3514 ENTER_V8(isolate); 3515 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3516 i::Handle<i::String> name(self->constructor_name()); 3517 return Utils::ToLocal(name); 3518 } 3519 3520 3521 bool v8::Object::Delete(v8::Handle<Value> key) { 3522 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3523 ON_BAILOUT(isolate, "v8::Object::Delete()", return false); 3524 ENTER_V8(isolate); 3525 i::HandleScope scope(isolate); 3526 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3527 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 3528 EXCEPTION_PREAMBLE(isolate); 3529 i::Handle<i::Object> obj = i::DeleteProperty(self, key_obj); 3530 has_pending_exception = obj.is_null(); 3531 EXCEPTION_BAILOUT_CHECK(isolate, false); 3532 return obj->IsTrue(); 3533 } 3534 3535 3536 bool v8::Object::DeletePrivate(v8::Handle<Private> key) { 3537 return Delete(v8::Handle<Value>(reinterpret_cast<Value*>(*key))); 3538 } 3539 3540 3541 bool v8::Object::Has(v8::Handle<Value> key) { 3542 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3543 ON_BAILOUT(isolate, "v8::Object::Has()", return false); 3544 ENTER_V8(isolate); 3545 i::Handle<i::JSReceiver> self = Utils::OpenHandle(this); 3546 i::Handle<i::Object> key_obj = Utils::OpenHandle(*key); 3547 EXCEPTION_PREAMBLE(isolate); 3548 i::Handle<i::Object> obj = i::HasProperty(self, key_obj); 3549 has_pending_exception = obj.is_null(); 3550 EXCEPTION_BAILOUT_CHECK(isolate, false); 3551 return obj->IsTrue(); 3552 } 3553 3554 3555 bool v8::Object::HasPrivate(v8::Handle<Private> key) { 3556 return Has(v8::Handle<Value>(reinterpret_cast<Value*>(*key))); 3557 } 3558 3559 3560 bool v8::Object::Delete(uint32_t index) { 3561 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3562 ON_BAILOUT(isolate, "v8::Object::DeleteProperty()", 3563 return false); 3564 ENTER_V8(isolate); 3565 HandleScope scope(reinterpret_cast<Isolate*>(isolate)); 3566 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3567 return i::JSReceiver::DeleteElement(self, index)->IsTrue(); 3568 } 3569 3570 3571 bool v8::Object::Has(uint32_t index) { 3572 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3573 ON_BAILOUT(isolate, "v8::Object::HasProperty()", return false); 3574 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3575 return i::JSReceiver::HasElement(self, index); 3576 } 3577 3578 3579 template<typename Setter, typename Getter, typename Data> 3580 static inline bool ObjectSetAccessor(Object* obj, 3581 Handle<String> name, 3582 Setter getter, 3583 Getter setter, 3584 Data data, 3585 AccessControl settings, 3586 PropertyAttribute attributes) { 3587 i::Isolate* isolate = Utils::OpenHandle(obj)->GetIsolate(); 3588 ON_BAILOUT(isolate, "v8::Object::SetAccessor()", return false); 3589 ENTER_V8(isolate); 3590 i::HandleScope scope(isolate); 3591 v8::Handle<AccessorSignature> signature; 3592 i::Handle<i::AccessorInfo> info = MakeAccessorInfo( 3593 name, getter, setter, data, settings, attributes, signature); 3594 if (info.is_null()) return false; 3595 bool fast = Utils::OpenHandle(obj)->HasFastProperties(); 3596 i::Handle<i::Object> result = 3597 i::JSObject::SetAccessor(Utils::OpenHandle(obj), info); 3598 if (result.is_null() || result->IsUndefined()) return false; 3599 if (fast) i::JSObject::TransformToFastProperties(Utils::OpenHandle(obj), 0); 3600 return true; 3601 } 3602 3603 3604 bool Object::SetAccessor(Handle<String> name, 3605 AccessorGetterCallback getter, 3606 AccessorSetterCallback setter, 3607 v8::Handle<Value> data, 3608 AccessControl settings, 3609 PropertyAttribute attributes) { 3610 return ObjectSetAccessor( 3611 this, name, getter, setter, data, settings, attributes); 3612 } 3613 3614 3615 bool Object::SetDeclaredAccessor(Local<String> name, 3616 Local<DeclaredAccessorDescriptor> descriptor, 3617 PropertyAttribute attributes, 3618 AccessControl settings) { 3619 void* null = NULL; 3620 return ObjectSetAccessor( 3621 this, name, descriptor, null, null, settings, attributes); 3622 } 3623 3624 3625 bool v8::Object::HasOwnProperty(Handle<String> key) { 3626 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3627 ON_BAILOUT(isolate, "v8::Object::HasOwnProperty()", 3628 return false); 3629 return i::JSReceiver::HasLocalProperty( 3630 Utils::OpenHandle(this), Utils::OpenHandle(*key)); 3631 } 3632 3633 3634 bool v8::Object::HasRealNamedProperty(Handle<String> key) { 3635 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3636 ON_BAILOUT(isolate, "v8::Object::HasRealNamedProperty()", 3637 return false); 3638 return i::JSObject::HasRealNamedProperty(Utils::OpenHandle(this), 3639 Utils::OpenHandle(*key)); 3640 } 3641 3642 3643 bool v8::Object::HasRealIndexedProperty(uint32_t index) { 3644 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3645 ON_BAILOUT(isolate, "v8::Object::HasRealIndexedProperty()", 3646 return false); 3647 return i::JSObject::HasRealElementProperty(Utils::OpenHandle(this), index); 3648 } 3649 3650 3651 bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) { 3652 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3653 ON_BAILOUT(isolate, 3654 "v8::Object::HasRealNamedCallbackProperty()", 3655 return false); 3656 ENTER_V8(isolate); 3657 return i::JSObject::HasRealNamedCallbackProperty(Utils::OpenHandle(this), 3658 Utils::OpenHandle(*key)); 3659 } 3660 3661 3662 bool v8::Object::HasNamedLookupInterceptor() { 3663 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3664 ON_BAILOUT(isolate, "v8::Object::HasNamedLookupInterceptor()", 3665 return false); 3666 return Utils::OpenHandle(this)->HasNamedInterceptor(); 3667 } 3668 3669 3670 bool v8::Object::HasIndexedLookupInterceptor() { 3671 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3672 ON_BAILOUT(isolate, "v8::Object::HasIndexedLookupInterceptor()", 3673 return false); 3674 return Utils::OpenHandle(this)->HasIndexedInterceptor(); 3675 } 3676 3677 3678 static Local<Value> GetPropertyByLookup(i::Isolate* isolate, 3679 i::Handle<i::JSObject> receiver, 3680 i::Handle<i::String> name, 3681 i::LookupResult* lookup) { 3682 if (!lookup->IsProperty()) { 3683 // No real property was found. 3684 return Local<Value>(); 3685 } 3686 3687 // If the property being looked up is a callback, it can throw 3688 // an exception. 3689 EXCEPTION_PREAMBLE(isolate); 3690 PropertyAttributes ignored; 3691 i::Handle<i::Object> result = 3692 i::Object::GetProperty(receiver, receiver, lookup, name, 3693 &ignored); 3694 has_pending_exception = result.is_null(); 3695 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 3696 3697 return Utils::ToLocal(result); 3698 } 3699 3700 3701 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain( 3702 Handle<String> key) { 3703 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3704 ON_BAILOUT(isolate, 3705 "v8::Object::GetRealNamedPropertyInPrototypeChain()", 3706 return Local<Value>()); 3707 ENTER_V8(isolate); 3708 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this); 3709 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 3710 i::LookupResult lookup(isolate); 3711 self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup); 3712 return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup); 3713 } 3714 3715 3716 Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) { 3717 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3718 ON_BAILOUT(isolate, "v8::Object::GetRealNamedProperty()", 3719 return Local<Value>()); 3720 ENTER_V8(isolate); 3721 i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this); 3722 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 3723 i::LookupResult lookup(isolate); 3724 self_obj->LookupRealNamedProperty(*key_obj, &lookup); 3725 return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup); 3726 } 3727 3728 3729 // Turns on access checks by copying the map and setting the check flag. 3730 // Because the object gets a new map, existing inline cache caching 3731 // the old map of this object will fail. 3732 void v8::Object::TurnOnAccessCheck() { 3733 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3734 ON_BAILOUT(isolate, "v8::Object::TurnOnAccessCheck()", return); 3735 ENTER_V8(isolate); 3736 i::HandleScope scope(isolate); 3737 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 3738 3739 // When turning on access checks for a global object deoptimize all functions 3740 // as optimized code does not always handle access checks. 3741 i::Deoptimizer::DeoptimizeGlobalObject(*obj); 3742 3743 i::Handle<i::Map> new_map = 3744 isolate->factory()->CopyMap(i::Handle<i::Map>(obj->map())); 3745 new_map->set_is_access_check_needed(true); 3746 obj->set_map(*new_map); 3747 } 3748 3749 3750 bool v8::Object::IsDirty() { 3751 return Utils::OpenHandle(this)->IsDirty(); 3752 } 3753 3754 3755 Local<v8::Object> v8::Object::Clone() { 3756 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3757 ON_BAILOUT(isolate, "v8::Object::Clone()", return Local<Object>()); 3758 ENTER_V8(isolate); 3759 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3760 EXCEPTION_PREAMBLE(isolate); 3761 i::Handle<i::JSObject> result = i::JSObject::Copy(self); 3762 has_pending_exception = result.is_null(); 3763 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>()); 3764 return Utils::ToLocal(result); 3765 } 3766 3767 3768 static i::Context* GetCreationContext(i::JSObject* object) { 3769 i::Object* constructor = object->map()->constructor(); 3770 i::JSFunction* function; 3771 if (!constructor->IsJSFunction()) { 3772 // Functions have null as a constructor, 3773 // but any JSFunction knows its context immediately. 3774 ASSERT(object->IsJSFunction()); 3775 function = i::JSFunction::cast(object); 3776 } else { 3777 function = i::JSFunction::cast(constructor); 3778 } 3779 return function->context()->native_context(); 3780 } 3781 3782 3783 Local<v8::Context> v8::Object::CreationContext() { 3784 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3785 ON_BAILOUT(isolate, 3786 "v8::Object::CreationContext()", return Local<v8::Context>()); 3787 ENTER_V8(isolate); 3788 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3789 i::Context* context = GetCreationContext(*self); 3790 return Utils::ToLocal(i::Handle<i::Context>(context)); 3791 } 3792 3793 3794 int v8::Object::GetIdentityHash() { 3795 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3796 ON_BAILOUT(isolate, "v8::Object::GetIdentityHash()", return 0); 3797 ENTER_V8(isolate); 3798 i::HandleScope scope(isolate); 3799 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3800 return i::Handle<i::Smi>::cast( 3801 i::JSReceiver::GetOrCreateIdentityHash(self))->value(); 3802 } 3803 3804 3805 bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key, 3806 v8::Handle<v8::Value> value) { 3807 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3808 ON_BAILOUT(isolate, "v8::Object::SetHiddenValue()", return false); 3809 if (value.IsEmpty()) return DeleteHiddenValue(key); 3810 ENTER_V8(isolate); 3811 i::HandleScope scope(isolate); 3812 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3813 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 3814 i::Handle<i::String> key_string = 3815 isolate->factory()->InternalizeString(key_obj); 3816 i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); 3817 i::Handle<i::Object> result = 3818 i::JSObject::SetHiddenProperty(self, key_string, value_obj); 3819 return *result == *self; 3820 } 3821 3822 3823 v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) { 3824 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3825 ON_BAILOUT(isolate, "v8::Object::GetHiddenValue()", 3826 return Local<v8::Value>()); 3827 ENTER_V8(isolate); 3828 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3829 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 3830 i::Handle<i::String> key_string = 3831 isolate->factory()->InternalizeString(key_obj); 3832 i::Handle<i::Object> result(self->GetHiddenProperty(*key_string), isolate); 3833 if (result->IsTheHole()) return v8::Local<v8::Value>(); 3834 return Utils::ToLocal(result); 3835 } 3836 3837 3838 bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) { 3839 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3840 ON_BAILOUT(isolate, "v8::DeleteHiddenValue()", return false); 3841 ENTER_V8(isolate); 3842 i::HandleScope scope(isolate); 3843 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3844 i::Handle<i::String> key_obj = Utils::OpenHandle(*key); 3845 i::Handle<i::String> key_string = 3846 isolate->factory()->InternalizeString(key_obj); 3847 i::JSObject::DeleteHiddenProperty(self, key_string); 3848 return true; 3849 } 3850 3851 3852 namespace { 3853 3854 static i::ElementsKind GetElementsKindFromExternalArrayType( 3855 ExternalArrayType array_type) { 3856 switch (array_type) { 3857 case kExternalByteArray: 3858 return i::EXTERNAL_BYTE_ELEMENTS; 3859 break; 3860 case kExternalUnsignedByteArray: 3861 return i::EXTERNAL_UNSIGNED_BYTE_ELEMENTS; 3862 break; 3863 case kExternalShortArray: 3864 return i::EXTERNAL_SHORT_ELEMENTS; 3865 break; 3866 case kExternalUnsignedShortArray: 3867 return i::EXTERNAL_UNSIGNED_SHORT_ELEMENTS; 3868 break; 3869 case kExternalIntArray: 3870 return i::EXTERNAL_INT_ELEMENTS; 3871 break; 3872 case kExternalUnsignedIntArray: 3873 return i::EXTERNAL_UNSIGNED_INT_ELEMENTS; 3874 break; 3875 case kExternalFloatArray: 3876 return i::EXTERNAL_FLOAT_ELEMENTS; 3877 break; 3878 case kExternalDoubleArray: 3879 return i::EXTERNAL_DOUBLE_ELEMENTS; 3880 break; 3881 case kExternalPixelArray: 3882 return i::EXTERNAL_PIXEL_ELEMENTS; 3883 break; 3884 } 3885 UNREACHABLE(); 3886 return i::DICTIONARY_ELEMENTS; 3887 } 3888 3889 3890 void PrepareExternalArrayElements(i::Handle<i::JSObject> object, 3891 void* data, 3892 ExternalArrayType array_type, 3893 int length) { 3894 i::Isolate* isolate = object->GetIsolate(); 3895 i::Handle<i::ExternalArray> array = 3896 isolate->factory()->NewExternalArray(length, array_type, data); 3897 3898 i::Handle<i::Map> external_array_map = 3899 isolate->factory()->GetElementsTransitionMap( 3900 object, 3901 GetElementsKindFromExternalArrayType(array_type)); 3902 3903 object->set_map(*external_array_map); 3904 object->set_elements(*array); 3905 } 3906 3907 } // namespace 3908 3909 3910 void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) { 3911 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3912 ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return); 3913 ENTER_V8(isolate); 3914 i::HandleScope scope(isolate); 3915 if (!ApiCheck(length >= 0 && length <= i::ExternalPixelArray::kMaxLength, 3916 "v8::Object::SetIndexedPropertiesToPixelData()", 3917 "length exceeds max acceptable value")) { 3918 return; 3919 } 3920 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3921 if (!ApiCheck(!self->IsJSArray(), 3922 "v8::Object::SetIndexedPropertiesToPixelData()", 3923 "JSArray is not supported")) { 3924 return; 3925 } 3926 PrepareExternalArrayElements(self, data, kExternalPixelArray, length); 3927 } 3928 3929 3930 bool v8::Object::HasIndexedPropertiesInPixelData() { 3931 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3932 ON_BAILOUT(self->GetIsolate(), "v8::HasIndexedPropertiesInPixelData()", 3933 return false); 3934 return self->HasExternalPixelElements(); 3935 } 3936 3937 3938 uint8_t* v8::Object::GetIndexedPropertiesPixelData() { 3939 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3940 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelData()", 3941 return NULL); 3942 if (self->HasExternalPixelElements()) { 3943 return i::ExternalPixelArray::cast(self->elements())-> 3944 external_pixel_pointer(); 3945 } else { 3946 return NULL; 3947 } 3948 } 3949 3950 3951 int v8::Object::GetIndexedPropertiesPixelDataLength() { 3952 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3953 ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelDataLength()", 3954 return -1); 3955 if (self->HasExternalPixelElements()) { 3956 return i::ExternalPixelArray::cast(self->elements())->length(); 3957 } else { 3958 return -1; 3959 } 3960 } 3961 3962 3963 void v8::Object::SetIndexedPropertiesToExternalArrayData( 3964 void* data, 3965 ExternalArrayType array_type, 3966 int length) { 3967 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 3968 ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return); 3969 ENTER_V8(isolate); 3970 i::HandleScope scope(isolate); 3971 if (!ApiCheck(length >= 0 && length <= i::ExternalArray::kMaxLength, 3972 "v8::Object::SetIndexedPropertiesToExternalArrayData()", 3973 "length exceeds max acceptable value")) { 3974 return; 3975 } 3976 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3977 if (!ApiCheck(!self->IsJSArray(), 3978 "v8::Object::SetIndexedPropertiesToExternalArrayData()", 3979 "JSArray is not supported")) { 3980 return; 3981 } 3982 PrepareExternalArrayElements(self, data, array_type, length); 3983 } 3984 3985 3986 bool v8::Object::HasIndexedPropertiesInExternalArrayData() { 3987 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3988 ON_BAILOUT(self->GetIsolate(), 3989 "v8::HasIndexedPropertiesInExternalArrayData()", 3990 return false); 3991 return self->HasExternalArrayElements(); 3992 } 3993 3994 3995 void* v8::Object::GetIndexedPropertiesExternalArrayData() { 3996 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 3997 ON_BAILOUT(self->GetIsolate(), 3998 "v8::GetIndexedPropertiesExternalArrayData()", 3999 return NULL); 4000 if (self->HasExternalArrayElements()) { 4001 return i::ExternalArray::cast(self->elements())->external_pointer(); 4002 } else { 4003 return NULL; 4004 } 4005 } 4006 4007 4008 ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() { 4009 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 4010 ON_BAILOUT(self->GetIsolate(), 4011 "v8::GetIndexedPropertiesExternalArrayDataType()", 4012 return static_cast<ExternalArrayType>(-1)); 4013 switch (self->elements()->map()->instance_type()) { 4014 case i::EXTERNAL_BYTE_ARRAY_TYPE: 4015 return kExternalByteArray; 4016 case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE: 4017 return kExternalUnsignedByteArray; 4018 case i::EXTERNAL_SHORT_ARRAY_TYPE: 4019 return kExternalShortArray; 4020 case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE: 4021 return kExternalUnsignedShortArray; 4022 case i::EXTERNAL_INT_ARRAY_TYPE: 4023 return kExternalIntArray; 4024 case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE: 4025 return kExternalUnsignedIntArray; 4026 case i::EXTERNAL_FLOAT_ARRAY_TYPE: 4027 return kExternalFloatArray; 4028 case i::EXTERNAL_DOUBLE_ARRAY_TYPE: 4029 return kExternalDoubleArray; 4030 case i::EXTERNAL_PIXEL_ARRAY_TYPE: 4031 return kExternalPixelArray; 4032 default: 4033 return static_cast<ExternalArrayType>(-1); 4034 } 4035 } 4036 4037 4038 int v8::Object::GetIndexedPropertiesExternalArrayDataLength() { 4039 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 4040 ON_BAILOUT(self->GetIsolate(), 4041 "v8::GetIndexedPropertiesExternalArrayDataLength()", 4042 return 0); 4043 if (self->HasExternalArrayElements()) { 4044 return i::ExternalArray::cast(self->elements())->length(); 4045 } else { 4046 return -1; 4047 } 4048 } 4049 4050 4051 bool v8::Object::IsCallable() { 4052 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4053 ON_BAILOUT(isolate, "v8::Object::IsCallable()", return false); 4054 ENTER_V8(isolate); 4055 i::HandleScope scope(isolate); 4056 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 4057 return obj->IsCallable(); 4058 } 4059 4060 4061 Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Value> recv, 4062 int argc, 4063 v8::Handle<v8::Value> argv[]) { 4064 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4065 ON_BAILOUT(isolate, "v8::Object::CallAsFunction()", 4066 return Local<v8::Value>()); 4067 LOG_API(isolate, "Object::CallAsFunction"); 4068 ENTER_V8(isolate); 4069 i::Logger::TimerEventScope timer_scope( 4070 isolate, i::Logger::TimerEventScope::v8_execute); 4071 i::HandleScope scope(isolate); 4072 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 4073 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv); 4074 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); 4075 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); 4076 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>(); 4077 if (obj->IsJSFunction()) { 4078 fun = i::Handle<i::JSFunction>::cast(obj); 4079 } else { 4080 EXCEPTION_PREAMBLE(isolate); 4081 i::Handle<i::Object> delegate = i::Execution::TryGetFunctionDelegate( 4082 isolate, obj, &has_pending_exception); 4083 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 4084 fun = i::Handle<i::JSFunction>::cast(delegate); 4085 recv_obj = obj; 4086 } 4087 EXCEPTION_PREAMBLE(isolate); 4088 i::Handle<i::Object> returned = i::Execution::Call( 4089 isolate, fun, recv_obj, argc, args, &has_pending_exception, true); 4090 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>()); 4091 return Utils::ToLocal(scope.CloseAndEscape(returned)); 4092 } 4093 4094 4095 Local<v8::Value> Object::CallAsConstructor(int argc, 4096 v8::Handle<v8::Value> argv[]) { 4097 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4098 ON_BAILOUT(isolate, "v8::Object::CallAsConstructor()", 4099 return Local<v8::Object>()); 4100 LOG_API(isolate, "Object::CallAsConstructor"); 4101 ENTER_V8(isolate); 4102 i::Logger::TimerEventScope timer_scope( 4103 isolate, i::Logger::TimerEventScope::v8_execute); 4104 i::HandleScope scope(isolate); 4105 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 4106 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); 4107 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); 4108 if (obj->IsJSFunction()) { 4109 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj); 4110 EXCEPTION_PREAMBLE(isolate); 4111 i::Handle<i::Object> returned = 4112 i::Execution::New(fun, argc, args, &has_pending_exception); 4113 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>()); 4114 return Utils::ToLocal(scope.CloseAndEscape( 4115 i::Handle<i::JSObject>::cast(returned))); 4116 } 4117 EXCEPTION_PREAMBLE(isolate); 4118 i::Handle<i::Object> delegate = i::Execution::TryGetConstructorDelegate( 4119 isolate, obj, &has_pending_exception); 4120 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); 4121 if (!delegate->IsUndefined()) { 4122 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(delegate); 4123 EXCEPTION_PREAMBLE(isolate); 4124 i::Handle<i::Object> returned = i::Execution::Call( 4125 isolate, fun, obj, argc, args, &has_pending_exception); 4126 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>()); 4127 ASSERT(!delegate->IsUndefined()); 4128 return Utils::ToLocal(scope.CloseAndEscape(returned)); 4129 } 4130 return Local<v8::Object>(); 4131 } 4132 4133 4134 Local<Function> Function::New(Isolate* v8_isolate, 4135 FunctionCallback callback, 4136 Local<Value> data, 4137 int length) { 4138 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); 4139 LOG_API(isolate, "Function::New"); 4140 ENTER_V8(isolate); 4141 return FunctionTemplateNew( 4142 isolate, callback, data, Local<Signature>(), length, true)-> 4143 GetFunction(); 4144 } 4145 4146 4147 Local<v8::Object> Function::NewInstance() const { 4148 return NewInstance(0, NULL); 4149 } 4150 4151 4152 Local<v8::Object> Function::NewInstance(int argc, 4153 v8::Handle<v8::Value> argv[]) const { 4154 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4155 ON_BAILOUT(isolate, "v8::Function::NewInstance()", 4156 return Local<v8::Object>()); 4157 LOG_API(isolate, "Function::NewInstance"); 4158 ENTER_V8(isolate); 4159 i::Logger::TimerEventScope timer_scope( 4160 isolate, i::Logger::TimerEventScope::v8_execute); 4161 EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 4162 i::Handle<i::JSFunction> function = Utils::OpenHandle(this); 4163 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); 4164 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); 4165 EXCEPTION_PREAMBLE(isolate); 4166 i::Handle<i::Object> returned = 4167 i::Execution::New(function, argc, args, &has_pending_exception); 4168 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>()); 4169 return scope.Escape(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned))); 4170 } 4171 4172 4173 Local<v8::Value> Function::Call(v8::Handle<v8::Value> recv, int argc, 4174 v8::Handle<v8::Value> argv[]) { 4175 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4176 ON_BAILOUT(isolate, "v8::Function::Call()", return Local<v8::Value>()); 4177 LOG_API(isolate, "Function::Call"); 4178 ENTER_V8(isolate); 4179 i::Logger::TimerEventScope timer_scope( 4180 isolate, i::Logger::TimerEventScope::v8_execute); 4181 i::Object* raw_result = NULL; 4182 { 4183 i::HandleScope scope(isolate); 4184 i::Handle<i::JSFunction> fun = Utils::OpenHandle(this); 4185 i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv); 4186 STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); 4187 i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv); 4188 EXCEPTION_PREAMBLE(isolate); 4189 i::Handle<i::Object> returned = i::Execution::Call( 4190 isolate, fun, recv_obj, argc, args, &has_pending_exception, true); 4191 EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Object>()); 4192 raw_result = *returned; 4193 } 4194 i::Handle<i::Object> result(raw_result, isolate); 4195 return Utils::ToLocal(result); 4196 } 4197 4198 4199 void Function::SetName(v8::Handle<v8::String> name) { 4200 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4201 ENTER_V8(isolate); 4202 USE(isolate); 4203 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4204 func->shared()->set_name(*Utils::OpenHandle(*name)); 4205 } 4206 4207 4208 Handle<Value> Function::GetName() const { 4209 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4210 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name(), 4211 func->GetIsolate())); 4212 } 4213 4214 4215 Handle<Value> Function::GetInferredName() const { 4216 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4217 return Utils::ToLocal(i::Handle<i::Object>(func->shared()->inferred_name(), 4218 func->GetIsolate())); 4219 } 4220 4221 4222 Handle<Value> Function::GetDisplayName() const { 4223 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4224 ON_BAILOUT(isolate, "v8::Function::GetDisplayName()", 4225 return ToApiHandle<Primitive>( 4226 isolate->factory()->undefined_value())); 4227 ENTER_V8(isolate); 4228 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4229 i::Handle<i::String> property_name = 4230 isolate->factory()->InternalizeOneByteString( 4231 STATIC_ASCII_VECTOR("displayName")); 4232 i::LookupResult lookup(isolate); 4233 func->LookupRealNamedProperty(*property_name, &lookup); 4234 if (lookup.IsFound()) { 4235 i::Object* value = lookup.GetLazyValue(); 4236 if (value && value->IsString()) { 4237 i::String* name = i::String::cast(value); 4238 if (name->length() > 0) return Utils::ToLocal(i::Handle<i::String>(name)); 4239 } 4240 } 4241 return ToApiHandle<Primitive>(isolate->factory()->undefined_value()); 4242 } 4243 4244 4245 ScriptOrigin Function::GetScriptOrigin() const { 4246 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4247 if (func->shared()->script()->IsScript()) { 4248 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 4249 i::Handle<i::Object> scriptName = GetScriptNameOrSourceURL(script); 4250 v8::ScriptOrigin origin( 4251 Utils::ToLocal(scriptName), 4252 v8::Integer::New(script->line_offset()->value()), 4253 v8::Integer::New(script->column_offset()->value())); 4254 return origin; 4255 } 4256 return v8::ScriptOrigin(Handle<Value>()); 4257 } 4258 4259 4260 const int Function::kLineOffsetNotFound = -1; 4261 4262 4263 int Function::GetScriptLineNumber() const { 4264 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4265 if (func->shared()->script()->IsScript()) { 4266 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 4267 return i::GetScriptLineNumber(script, func->shared()->start_position()); 4268 } 4269 return kLineOffsetNotFound; 4270 } 4271 4272 4273 int Function::GetScriptColumnNumber() const { 4274 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4275 if (func->shared()->script()->IsScript()) { 4276 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 4277 return i::GetScriptColumnNumber(script, func->shared()->start_position()); 4278 } 4279 return kLineOffsetNotFound; 4280 } 4281 4282 4283 bool Function::IsBuiltin() const { 4284 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4285 return func->IsBuiltin(); 4286 } 4287 4288 4289 Handle<Value> Function::GetScriptId() const { 4290 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4291 i::Isolate* isolate = func->GetIsolate(); 4292 if (!func->shared()->script()->IsScript()) { 4293 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 4294 } 4295 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 4296 return Utils::ToLocal(i::Handle<i::Object>(script->id(), isolate)); 4297 } 4298 4299 4300 int Function::ScriptId() const { 4301 i::Handle<i::JSFunction> func = Utils::OpenHandle(this); 4302 if (!func->shared()->script()->IsScript()) return v8::Script::kNoScriptId; 4303 i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); 4304 return script->id()->value(); 4305 } 4306 4307 4308 int String::Length() const { 4309 i::Handle<i::String> str = Utils::OpenHandle(this); 4310 return str->length(); 4311 } 4312 4313 4314 bool String::IsOneByte() const { 4315 i::Handle<i::String> str = Utils::OpenHandle(this); 4316 return str->HasOnlyOneByteChars(); 4317 } 4318 4319 4320 // Helpers for ContainsOnlyOneByteHelper 4321 template<size_t size> struct OneByteMask; 4322 template<> struct OneByteMask<4> { 4323 static const uint32_t value = 0xFF00FF00; 4324 }; 4325 template<> struct OneByteMask<8> { 4326 static const uint64_t value = V8_2PART_UINT64_C(0xFF00FF00, FF00FF00); 4327 }; 4328 static const uintptr_t kOneByteMask = OneByteMask<sizeof(uintptr_t)>::value; 4329 static const uintptr_t kAlignmentMask = sizeof(uintptr_t) - 1; 4330 static inline bool Unaligned(const uint16_t* chars) { 4331 return reinterpret_cast<const uintptr_t>(chars) & kAlignmentMask; 4332 } 4333 4334 4335 static inline const uint16_t* Align(const uint16_t* chars) { 4336 return reinterpret_cast<uint16_t*>( 4337 reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask); 4338 } 4339 4340 class ContainsOnlyOneByteHelper { 4341 public: 4342 ContainsOnlyOneByteHelper() : is_one_byte_(true) {} 4343 bool Check(i::String* string) { 4344 i::ConsString* cons_string = i::String::VisitFlat(this, string, 0); 4345 if (cons_string == NULL) return is_one_byte_; 4346 return CheckCons(cons_string); 4347 } 4348 void VisitOneByteString(const uint8_t* chars, int length) { 4349 // Nothing to do. 4350 } 4351 void VisitTwoByteString(const uint16_t* chars, int length) { 4352 // Accumulated bits. 4353 uintptr_t acc = 0; 4354 // Align to uintptr_t. 4355 const uint16_t* end = chars + length; 4356 while (Unaligned(chars) && chars != end) { 4357 acc |= *chars++; 4358 } 4359 // Read word aligned in blocks, 4360 // checking the return value at the end of each block. 4361 const uint16_t* aligned_end = Align(end); 4362 const int increment = sizeof(uintptr_t)/sizeof(uint16_t); 4363 const int inner_loops = 16; 4364 while (chars + inner_loops*increment < aligned_end) { 4365 for (int i = 0; i < inner_loops; i++) { 4366 acc |= *reinterpret_cast<const uintptr_t*>(chars); 4367 chars += increment; 4368 } 4369 // Check for early return. 4370 if ((acc & kOneByteMask) != 0) { 4371 is_one_byte_ = false; 4372 return; 4373 } 4374 } 4375 // Read the rest. 4376 while (chars != end) { 4377 acc |= *chars++; 4378 } 4379 // Check result. 4380 if ((acc & kOneByteMask) != 0) is_one_byte_ = false; 4381 } 4382 4383 private: 4384 bool CheckCons(i::ConsString* cons_string) { 4385 while (true) { 4386 // Check left side if flat. 4387 i::String* left = cons_string->first(); 4388 i::ConsString* left_as_cons = 4389 i::String::VisitFlat(this, left, 0); 4390 if (!is_one_byte_) return false; 4391 // Check right side if flat. 4392 i::String* right = cons_string->second(); 4393 i::ConsString* right_as_cons = 4394 i::String::VisitFlat(this, right, 0); 4395 if (!is_one_byte_) return false; 4396 // Standard recurse/iterate trick. 4397 if (left_as_cons != NULL && right_as_cons != NULL) { 4398 if (left->length() < right->length()) { 4399 CheckCons(left_as_cons); 4400 cons_string = right_as_cons; 4401 } else { 4402 CheckCons(right_as_cons); 4403 cons_string = left_as_cons; 4404 } 4405 // Check fast return. 4406 if (!is_one_byte_) return false; 4407 continue; 4408 } 4409 // Descend left in place. 4410 if (left_as_cons != NULL) { 4411 cons_string = left_as_cons; 4412 continue; 4413 } 4414 // Descend right in place. 4415 if (right_as_cons != NULL) { 4416 cons_string = right_as_cons; 4417 continue; 4418 } 4419 // Terminate. 4420 break; 4421 } 4422 return is_one_byte_; 4423 } 4424 bool is_one_byte_; 4425 DISALLOW_COPY_AND_ASSIGN(ContainsOnlyOneByteHelper); 4426 }; 4427 4428 4429 bool String::ContainsOnlyOneByte() const { 4430 i::Handle<i::String> str = Utils::OpenHandle(this); 4431 if (str->HasOnlyOneByteChars()) return true; 4432 ContainsOnlyOneByteHelper helper; 4433 return helper.Check(*str); 4434 } 4435 4436 4437 class Utf8LengthHelper : public i::AllStatic { 4438 public: 4439 enum State { 4440 kEndsWithLeadingSurrogate = 1 << 0, 4441 kStartsWithTrailingSurrogate = 1 << 1, 4442 kLeftmostEdgeIsCalculated = 1 << 2, 4443 kRightmostEdgeIsCalculated = 1 << 3, 4444 kLeftmostEdgeIsSurrogate = 1 << 4, 4445 kRightmostEdgeIsSurrogate = 1 << 5 4446 }; 4447 4448 static const uint8_t kInitialState = 0; 4449 4450 static inline bool EndsWithSurrogate(uint8_t state) { 4451 return state & kEndsWithLeadingSurrogate; 4452 } 4453 4454 static inline bool StartsWithSurrogate(uint8_t state) { 4455 return state & kStartsWithTrailingSurrogate; 4456 } 4457 4458 class Visitor { 4459 public: 4460 inline explicit Visitor() 4461 : utf8_length_(0), 4462 state_(kInitialState) {} 4463 4464 void VisitOneByteString(const uint8_t* chars, int length) { 4465 int utf8_length = 0; 4466 // Add in length 1 for each non-ASCII character. 4467 for (int i = 0; i < length; i++) { 4468 utf8_length += *chars++ >> 7; 4469 } 4470 // Add in length 1 for each character. 4471 utf8_length_ = utf8_length + length; 4472 state_ = kInitialState; 4473 } 4474 4475 void VisitTwoByteString(const uint16_t* chars, int length) { 4476 int utf8_length = 0; 4477 int last_character = unibrow::Utf16::kNoPreviousCharacter; 4478 for (int i = 0; i < length; i++) { 4479 uint16_t c = chars[i]; 4480 utf8_length += unibrow::Utf8::Length(c, last_character); 4481 last_character = c; 4482 } 4483 utf8_length_ = utf8_length; 4484 uint8_t state = 0; 4485 if (unibrow::Utf16::IsTrailSurrogate(chars[0])) { 4486 state |= kStartsWithTrailingSurrogate; 4487 } 4488 if (unibrow::Utf16::IsLeadSurrogate(chars[length-1])) { 4489 state |= kEndsWithLeadingSurrogate; 4490 } 4491 state_ = state; 4492 } 4493 4494 static i::ConsString* VisitFlat(i::String* string, 4495 int* length, 4496 uint8_t* state) { 4497 Visitor visitor; 4498 i::ConsString* cons_string = i::String::VisitFlat(&visitor, string); 4499 *length = visitor.utf8_length_; 4500 *state = visitor.state_; 4501 return cons_string; 4502 } 4503 4504 private: 4505 int utf8_length_; 4506 uint8_t state_; 4507 DISALLOW_COPY_AND_ASSIGN(Visitor); 4508 }; 4509 4510 static inline void MergeLeafLeft(int* length, 4511 uint8_t* state, 4512 uint8_t leaf_state) { 4513 bool edge_surrogate = StartsWithSurrogate(leaf_state); 4514 if (!(*state & kLeftmostEdgeIsCalculated)) { 4515 ASSERT(!(*state & kLeftmostEdgeIsSurrogate)); 4516 *state |= kLeftmostEdgeIsCalculated 4517 | (edge_surrogate ? kLeftmostEdgeIsSurrogate : 0); 4518 } else if (EndsWithSurrogate(*state) && edge_surrogate) { 4519 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates; 4520 } 4521 if (EndsWithSurrogate(leaf_state)) { 4522 *state |= kEndsWithLeadingSurrogate; 4523 } else { 4524 *state &= ~kEndsWithLeadingSurrogate; 4525 } 4526 } 4527 4528 static inline void MergeLeafRight(int* length, 4529 uint8_t* state, 4530 uint8_t leaf_state) { 4531 bool edge_surrogate = EndsWithSurrogate(leaf_state); 4532 if (!(*state & kRightmostEdgeIsCalculated)) { 4533 ASSERT(!(*state & kRightmostEdgeIsSurrogate)); 4534 *state |= (kRightmostEdgeIsCalculated 4535 | (edge_surrogate ? kRightmostEdgeIsSurrogate : 0)); 4536 } else if (edge_surrogate && StartsWithSurrogate(*state)) { 4537 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates; 4538 } 4539 if (StartsWithSurrogate(leaf_state)) { 4540 *state |= kStartsWithTrailingSurrogate; 4541 } else { 4542 *state &= ~kStartsWithTrailingSurrogate; 4543 } 4544 } 4545 4546 static inline void MergeTerminal(int* length, 4547 uint8_t state, 4548 uint8_t* state_out) { 4549 ASSERT((state & kLeftmostEdgeIsCalculated) && 4550 (state & kRightmostEdgeIsCalculated)); 4551 if (EndsWithSurrogate(state) && StartsWithSurrogate(state)) { 4552 *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates; 4553 } 4554 *state_out = kInitialState | 4555 (state & kLeftmostEdgeIsSurrogate ? kStartsWithTrailingSurrogate : 0) | 4556 (state & kRightmostEdgeIsSurrogate ? kEndsWithLeadingSurrogate : 0); 4557 } 4558 4559 static int Calculate(i::ConsString* current, uint8_t* state_out) { 4560 using namespace internal; 4561 int total_length = 0; 4562 uint8_t state = kInitialState; 4563 while (true) { 4564 i::String* left = current->first(); 4565 i::String* right = current->second(); 4566 uint8_t right_leaf_state; 4567 uint8_t left_leaf_state; 4568 int leaf_length; 4569 ConsString* left_as_cons = 4570 Visitor::VisitFlat(left, &leaf_length, &left_leaf_state); 4571 if (left_as_cons == NULL) { 4572 total_length += leaf_length; 4573 MergeLeafLeft(&total_length, &state, left_leaf_state); 4574 } 4575 ConsString* right_as_cons = 4576 Visitor::VisitFlat(right, &leaf_length, &right_leaf_state); 4577 if (right_as_cons == NULL) { 4578 total_length += leaf_length; 4579 MergeLeafRight(&total_length, &state, right_leaf_state); 4580 if (left_as_cons != NULL) { 4581 // 1 Leaf node. Descend in place. 4582 current = left_as_cons; 4583 continue; 4584 } else { 4585 // Terminal node. 4586 MergeTerminal(&total_length, state, state_out); 4587 return total_length; 4588 } 4589 } else if (left_as_cons == NULL) { 4590 // 1 Leaf node. Descend in place. 4591 current = right_as_cons; 4592 continue; 4593 } 4594 // Both strings are ConsStrings. 4595 // Recurse on smallest. 4596 if (left->length() < right->length()) { 4597 total_length += Calculate(left_as_cons, &left_leaf_state); 4598 MergeLeafLeft(&total_length, &state, left_leaf_state); 4599 current = right_as_cons; 4600 } else { 4601 total_length += Calculate(right_as_cons, &right_leaf_state); 4602 MergeLeafRight(&total_length, &state, right_leaf_state); 4603 current = left_as_cons; 4604 } 4605 } 4606 UNREACHABLE(); 4607 return 0; 4608 } 4609 4610 static inline int Calculate(i::ConsString* current) { 4611 uint8_t state = kInitialState; 4612 return Calculate(current, &state); 4613 } 4614 4615 private: 4616 DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8LengthHelper); 4617 }; 4618 4619 4620 static int Utf8Length(i::String* str, i::Isolate* isolate) { 4621 int length = str->length(); 4622 if (length == 0) return 0; 4623 uint8_t state; 4624 i::ConsString* cons_string = 4625 Utf8LengthHelper::Visitor::VisitFlat(str, &length, &state); 4626 if (cons_string == NULL) return length; 4627 return Utf8LengthHelper::Calculate(cons_string); 4628 } 4629 4630 4631 int String::Utf8Length() const { 4632 i::Handle<i::String> str = Utils::OpenHandle(this); 4633 i::Isolate* isolate = str->GetIsolate(); 4634 return v8::Utf8Length(*str, isolate); 4635 } 4636 4637 4638 class Utf8WriterVisitor { 4639 public: 4640 Utf8WriterVisitor( 4641 char* buffer, int capacity, bool skip_capacity_check) 4642 : early_termination_(false), 4643 last_character_(unibrow::Utf16::kNoPreviousCharacter), 4644 buffer_(buffer), 4645 start_(buffer), 4646 capacity_(capacity), 4647 skip_capacity_check_(capacity == -1 || skip_capacity_check), 4648 utf16_chars_read_(0) { 4649 } 4650 4651 static int WriteEndCharacter(uint16_t character, 4652 int last_character, 4653 int remaining, 4654 char* const buffer) { 4655 using namespace unibrow; 4656 ASSERT(remaining > 0); 4657 // We can't use a local buffer here because Encode needs to modify 4658 // previous characters in the stream. We know, however, that 4659 // exactly one character will be advanced. 4660 if (Utf16::IsTrailSurrogate(character) && 4661 Utf16::IsLeadSurrogate(last_character)) { 4662 int written = Utf8::Encode(buffer, character, last_character); 4663 ASSERT(written == 1); 4664 return written; 4665 } 4666 // Use a scratch buffer to check the required characters. 4667 char temp_buffer[Utf8::kMaxEncodedSize]; 4668 // Can't encode using last_character as gcc has array bounds issues. 4669 int written = Utf8::Encode(temp_buffer, 4670 character, 4671 Utf16::kNoPreviousCharacter); 4672 // Won't fit. 4673 if (written > remaining) return 0; 4674 // Copy over the character from temp_buffer. 4675 for (int j = 0; j < written; j++) { 4676 buffer[j] = temp_buffer[j]; 4677 } 4678 return written; 4679 } 4680 4681 template<typename Char> 4682 void Visit(const Char* chars, const int length) { 4683 using namespace unibrow; 4684 ASSERT(!early_termination_); 4685 if (length == 0) return; 4686 // Copy state to stack. 4687 char* buffer = buffer_; 4688 int last_character = 4689 sizeof(Char) == 1 ? Utf16::kNoPreviousCharacter : last_character_; 4690 int i = 0; 4691 // Do a fast loop where there is no exit capacity check. 4692 while (true) { 4693 int fast_length; 4694 if (skip_capacity_check_) { 4695 fast_length = length; 4696 } else { 4697 int remaining_capacity = capacity_ - static_cast<int>(buffer - start_); 4698 // Need enough space to write everything but one character. 4699 STATIC_ASSERT(Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit == 3); 4700 int max_size_per_char = sizeof(Char) == 1 ? 2 : 3; 4701 int writable_length = 4702 (remaining_capacity - max_size_per_char)/max_size_per_char; 4703 // Need to drop into slow loop. 4704 if (writable_length <= 0) break; 4705 fast_length = i + writable_length; 4706 if (fast_length > length) fast_length = length; 4707 } 4708 // Write the characters to the stream. 4709 if (sizeof(Char) == 1) { 4710 for (; i < fast_length; i++) { 4711 buffer += 4712 Utf8::EncodeOneByte(buffer, static_cast<uint8_t>(*chars++)); 4713 ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_); 4714 } 4715 } else { 4716 for (; i < fast_length; i++) { 4717 uint16_t character = *chars++; 4718 buffer += Utf8::Encode(buffer, character, last_character); 4719 last_character = character; 4720 ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_); 4721 } 4722 } 4723 // Array is fully written. Exit. 4724 if (fast_length == length) { 4725 // Write state back out to object. 4726 last_character_ = last_character; 4727 buffer_ = buffer; 4728 utf16_chars_read_ += length; 4729 return; 4730 } 4731 } 4732 ASSERT(!skip_capacity_check_); 4733 // Slow loop. Must check capacity on each iteration. 4734 int remaining_capacity = capacity_ - static_cast<int>(buffer - start_); 4735 ASSERT(remaining_capacity >= 0); 4736 for (; i < length && remaining_capacity > 0; i++) { 4737 uint16_t character = *chars++; 4738 int written = WriteEndCharacter(character, 4739 last_character, 4740 remaining_capacity, 4741 buffer); 4742 if (written == 0) { 4743 early_termination_ = true; 4744 break; 4745 } 4746 buffer += written; 4747 remaining_capacity -= written; 4748 last_character = character; 4749 } 4750 // Write state back out to object. 4751 last_character_ = last_character; 4752 buffer_ = buffer; 4753 utf16_chars_read_ += i; 4754 } 4755 4756 inline bool IsDone() { 4757 return early_termination_; 4758 } 4759 4760 inline void VisitOneByteString(const uint8_t* chars, int length) { 4761 Visit(chars, length); 4762 } 4763 4764 inline void VisitTwoByteString(const uint16_t* chars, int length) { 4765 Visit(chars, length); 4766 } 4767 4768 int CompleteWrite(bool write_null, int* utf16_chars_read_out) { 4769 // Write out number of utf16 characters written to the stream. 4770 if (utf16_chars_read_out != NULL) { 4771 *utf16_chars_read_out = utf16_chars_read_; 4772 } 4773 // Only null terminate if all of the string was written and there's space. 4774 if (write_null && 4775 !early_termination_ && 4776 (capacity_ == -1 || (buffer_ - start_) < capacity_)) { 4777 *buffer_++ = '\0'; 4778 } 4779 return static_cast<int>(buffer_ - start_); 4780 } 4781 4782 private: 4783 bool early_termination_; 4784 int last_character_; 4785 char* buffer_; 4786 char* const start_; 4787 int capacity_; 4788 bool const skip_capacity_check_; 4789 int utf16_chars_read_; 4790 DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8WriterVisitor); 4791 }; 4792 4793 4794 static bool RecursivelySerializeToUtf8(i::String* current, 4795 Utf8WriterVisitor* writer, 4796 int recursion_budget) { 4797 while (!writer->IsDone()) { 4798 i::ConsString* cons_string = i::String::VisitFlat(writer, current); 4799 if (cons_string == NULL) return true; // Leaf node. 4800 if (recursion_budget <= 0) return false; 4801 // Must write the left branch first. 4802 i::String* first = cons_string->first(); 4803 bool success = RecursivelySerializeToUtf8(first, 4804 writer, 4805 recursion_budget - 1); 4806 if (!success) return false; 4807 // Inline tail recurse for right branch. 4808 current = cons_string->second(); 4809 } 4810 return true; 4811 } 4812 4813 4814 int String::WriteUtf8(char* buffer, 4815 int capacity, 4816 int* nchars_ref, 4817 int options) const { 4818 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 4819 LOG_API(isolate, "String::WriteUtf8"); 4820 ENTER_V8(isolate); 4821 i::Handle<i::String> str = Utils::OpenHandle(this); 4822 if (options & HINT_MANY_WRITES_EXPECTED) { 4823 FlattenString(str); // Flatten the string for efficiency. 4824 } 4825 const int string_length = str->length(); 4826 bool write_null = !(options & NO_NULL_TERMINATION); 4827 // First check if we can just write the string without checking capacity. 4828 if (capacity == -1 || capacity / 3 >= string_length) { 4829 Utf8WriterVisitor writer(buffer, capacity, true); 4830 const int kMaxRecursion = 100; 4831 bool success = RecursivelySerializeToUtf8(*str, &writer, kMaxRecursion); 4832 if (success) return writer.CompleteWrite(write_null, nchars_ref); 4833 } else if (capacity >= string_length) { 4834 // First check that the buffer is large enough. 4835 int utf8_bytes = v8::Utf8Length(*str, str->GetIsolate()); 4836 if (utf8_bytes <= capacity) { 4837 // ASCII fast path. 4838 if (utf8_bytes == string_length) { 4839 WriteOneByte(reinterpret_cast<uint8_t*>(buffer), 0, capacity, options); 4840 if (nchars_ref != NULL) *nchars_ref = string_length; 4841 if (write_null && (utf8_bytes+1 <= capacity)) { 4842 return string_length + 1; 4843 } 4844 return string_length; 4845 } 4846 if (write_null && (utf8_bytes+1 > capacity)) { 4847 options |= NO_NULL_TERMINATION; 4848 } 4849 // Recurse once without a capacity limit. 4850 // This will get into the first branch above. 4851 // TODO(dcarney) Check max left rec. in Utf8Length and fall through. 4852 return WriteUtf8(buffer, -1, nchars_ref, options); 4853 } 4854 } 4855 // Recursive slow path can potentially be unreasonable slow. Flatten. 4856 str = FlattenGetString(str); 4857 Utf8WriterVisitor writer(buffer, capacity, false); 4858 i::String::VisitFlat(&writer, *str); 4859 return writer.CompleteWrite(write_null, nchars_ref); 4860 } 4861 4862 4863 template<typename CharType> 4864 static inline int WriteHelper(const String* string, 4865 CharType* buffer, 4866 int start, 4867 int length, 4868 int options) { 4869 i::Isolate* isolate = Utils::OpenHandle(string)->GetIsolate(); 4870 LOG_API(isolate, "String::Write"); 4871 ENTER_V8(isolate); 4872 ASSERT(start >= 0 && length >= -1); 4873 i::Handle<i::String> str = Utils::OpenHandle(string); 4874 isolate->string_tracker()->RecordWrite(str); 4875 if (options & String::HINT_MANY_WRITES_EXPECTED) { 4876 // Flatten the string for efficiency. This applies whether we are 4877 // using StringCharacterStream or Get(i) to access the characters. 4878 FlattenString(str); 4879 } 4880 int end = start + length; 4881 if ((length == -1) || (length > str->length() - start) ) 4882 end = str->length(); 4883 if (end < 0) return 0; 4884 i::String::WriteToFlat(*str, buffer, start, end); 4885 if (!(options & String::NO_NULL_TERMINATION) && 4886 (length == -1 || end - start < length)) { 4887 buffer[end - start] = '\0'; 4888 } 4889 return end - start; 4890 } 4891 4892 4893 int String::WriteOneByte(uint8_t* buffer, 4894 int start, 4895 int length, 4896 int options) const { 4897 return WriteHelper(this, buffer, start, length, options); 4898 } 4899 4900 4901 int String::Write(uint16_t* buffer, 4902 int start, 4903 int length, 4904 int options) const { 4905 return WriteHelper(this, buffer, start, length, options); 4906 } 4907 4908 4909 bool v8::String::IsExternal() const { 4910 i::Handle<i::String> str = Utils::OpenHandle(this); 4911 EnsureInitializedForIsolate(str->GetIsolate(), "v8::String::IsExternal()"); 4912 return i::StringShape(*str).IsExternalTwoByte(); 4913 } 4914 4915 4916 bool v8::String::IsExternalAscii() const { 4917 i::Handle<i::String> str = Utils::OpenHandle(this); 4918 return i::StringShape(*str).IsExternalAscii(); 4919 } 4920 4921 4922 void v8::String::VerifyExternalStringResource( 4923 v8::String::ExternalStringResource* value) const { 4924 i::Handle<i::String> str = Utils::OpenHandle(this); 4925 const v8::String::ExternalStringResource* expected; 4926 if (i::StringShape(*str).IsExternalTwoByte()) { 4927 const void* resource = 4928 i::Handle<i::ExternalTwoByteString>::cast(str)->resource(); 4929 expected = reinterpret_cast<const ExternalStringResource*>(resource); 4930 } else { 4931 expected = NULL; 4932 } 4933 CHECK_EQ(expected, value); 4934 } 4935 4936 void v8::String::VerifyExternalStringResourceBase( 4937 v8::String::ExternalStringResourceBase* value, Encoding encoding) const { 4938 i::Handle<i::String> str = Utils::OpenHandle(this); 4939 const v8::String::ExternalStringResourceBase* expected; 4940 Encoding expectedEncoding; 4941 if (i::StringShape(*str).IsExternalAscii()) { 4942 const void* resource = 4943 i::Handle<i::ExternalAsciiString>::cast(str)->resource(); 4944 expected = reinterpret_cast<const ExternalStringResourceBase*>(resource); 4945 expectedEncoding = ASCII_ENCODING; 4946 } else if (i::StringShape(*str).IsExternalTwoByte()) { 4947 const void* resource = 4948 i::Handle<i::ExternalTwoByteString>::cast(str)->resource(); 4949 expected = reinterpret_cast<const ExternalStringResourceBase*>(resource); 4950 expectedEncoding = TWO_BYTE_ENCODING; 4951 } else { 4952 expected = NULL; 4953 expectedEncoding = str->IsOneByteRepresentation() ? ASCII_ENCODING 4954 : TWO_BYTE_ENCODING; 4955 } 4956 CHECK_EQ(expected, value); 4957 CHECK_EQ(expectedEncoding, encoding); 4958 } 4959 4960 const v8::String::ExternalAsciiStringResource* 4961 v8::String::GetExternalAsciiStringResource() const { 4962 i::Handle<i::String> str = Utils::OpenHandle(this); 4963 if (i::StringShape(*str).IsExternalAscii()) { 4964 const void* resource = 4965 i::Handle<i::ExternalAsciiString>::cast(str)->resource(); 4966 return reinterpret_cast<const ExternalAsciiStringResource*>(resource); 4967 } else { 4968 return NULL; 4969 } 4970 } 4971 4972 4973 Local<Value> Symbol::Name() const { 4974 i::Handle<i::Symbol> sym = Utils::OpenHandle(this); 4975 i::Handle<i::Object> name(sym->name(), sym->GetIsolate()); 4976 return Utils::ToLocal(name); 4977 } 4978 4979 4980 Local<Value> Private::Name() const { 4981 return reinterpret_cast<const Symbol*>(this)->Name(); 4982 } 4983 4984 4985 double Number::Value() const { 4986 i::Handle<i::Object> obj = Utils::OpenHandle(this); 4987 return obj->Number(); 4988 } 4989 4990 4991 bool Boolean::Value() const { 4992 i::Handle<i::Object> obj = Utils::OpenHandle(this); 4993 return obj->IsTrue(); 4994 } 4995 4996 4997 int64_t Integer::Value() const { 4998 i::Handle<i::Object> obj = Utils::OpenHandle(this); 4999 if (obj->IsSmi()) { 5000 return i::Smi::cast(*obj)->value(); 5001 } else { 5002 return static_cast<int64_t>(obj->Number()); 5003 } 5004 } 5005 5006 5007 int32_t Int32::Value() const { 5008 i::Handle<i::Object> obj = Utils::OpenHandle(this); 5009 if (obj->IsSmi()) { 5010 return i::Smi::cast(*obj)->value(); 5011 } else { 5012 return static_cast<int32_t>(obj->Number()); 5013 } 5014 } 5015 5016 5017 uint32_t Uint32::Value() const { 5018 i::Handle<i::Object> obj = Utils::OpenHandle(this); 5019 if (obj->IsSmi()) { 5020 return i::Smi::cast(*obj)->value(); 5021 } else { 5022 return static_cast<uint32_t>(obj->Number()); 5023 } 5024 } 5025 5026 5027 int v8::Object::InternalFieldCount() { 5028 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 5029 return obj->GetInternalFieldCount(); 5030 } 5031 5032 5033 static bool InternalFieldOK(i::Handle<i::JSObject> obj, 5034 int index, 5035 const char* location) { 5036 return ApiCheck(index < obj->GetInternalFieldCount(), 5037 location, 5038 "Internal field out of bounds"); 5039 } 5040 5041 5042 Local<Value> v8::Object::SlowGetInternalField(int index) { 5043 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 5044 const char* location = "v8::Object::GetInternalField()"; 5045 if (!InternalFieldOK(obj, index, location)) return Local<Value>(); 5046 i::Handle<i::Object> value(obj->GetInternalField(index), obj->GetIsolate()); 5047 return Utils::ToLocal(value); 5048 } 5049 5050 5051 void v8::Object::SetInternalField(int index, v8::Handle<Value> value) { 5052 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 5053 const char* location = "v8::Object::SetInternalField()"; 5054 if (!InternalFieldOK(obj, index, location)) return; 5055 i::Handle<i::Object> val = Utils::OpenHandle(*value); 5056 obj->SetInternalField(index, *val); 5057 ASSERT_EQ(value, GetInternalField(index)); 5058 } 5059 5060 5061 void* v8::Object::SlowGetAlignedPointerFromInternalField(int index) { 5062 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 5063 const char* location = "v8::Object::GetAlignedPointerFromInternalField()"; 5064 if (!InternalFieldOK(obj, index, location)) return NULL; 5065 return DecodeSmiToAligned(obj->GetInternalField(index), location); 5066 } 5067 5068 5069 void v8::Object::SetAlignedPointerInInternalField(int index, void* value) { 5070 i::Handle<i::JSObject> obj = Utils::OpenHandle(this); 5071 const char* location = "v8::Object::SetAlignedPointerInInternalField()"; 5072 if (!InternalFieldOK(obj, index, location)) return; 5073 obj->SetInternalField(index, EncodeAlignedAsSmi(value, location)); 5074 ASSERT_EQ(value, GetAlignedPointerFromInternalField(index)); 5075 } 5076 5077 5078 static void* ExternalValue(i::Object* obj) { 5079 // Obscure semantics for undefined, but somehow checked in our unit tests... 5080 if (obj->IsUndefined()) return NULL; 5081 i::Object* foreign = i::JSObject::cast(obj)->GetInternalField(0); 5082 return i::Foreign::cast(foreign)->foreign_address(); 5083 } 5084 5085 5086 // --- E n v i r o n m e n t --- 5087 5088 5089 void v8::V8::InitializePlatform(Platform* platform) { 5090 #ifdef V8_USE_DEFAULT_PLATFORM 5091 FATAL("Can't override v8::Platform when using default implementation"); 5092 #else 5093 i::V8::InitializePlatform(platform); 5094 #endif 5095 } 5096 5097 5098 void v8::V8::ShutdownPlatform() { 5099 #ifdef V8_USE_DEFAULT_PLATFORM 5100 FATAL("Can't override v8::Platform when using default implementation"); 5101 #else 5102 i::V8::ShutdownPlatform(); 5103 #endif 5104 } 5105 5106 5107 bool v8::V8::Initialize() { 5108 i::Isolate* isolate = i::Isolate::UncheckedCurrent(); 5109 if (isolate != NULL && isolate->IsInitialized()) { 5110 return true; 5111 } 5112 return InitializeHelper(isolate); 5113 } 5114 5115 5116 void v8::V8::SetEntropySource(EntropySource entropy_source) { 5117 i::RandomNumberGenerator::SetEntropySource(entropy_source); 5118 } 5119 5120 5121 void v8::V8::SetReturnAddressLocationResolver( 5122 ReturnAddressLocationResolver return_address_resolver) { 5123 i::V8::SetReturnAddressLocationResolver(return_address_resolver); 5124 } 5125 5126 5127 bool v8::V8::SetFunctionEntryHook(Isolate* ext_isolate, 5128 FunctionEntryHook entry_hook) { 5129 ASSERT(ext_isolate != NULL); 5130 ASSERT(entry_hook != NULL); 5131 5132 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(ext_isolate); 5133 5134 // The entry hook can only be set before the Isolate is initialized, as 5135 // otherwise the Isolate's code stubs generated at initialization won't 5136 // contain entry hooks. 5137 if (isolate->IsInitialized()) 5138 return false; 5139 5140 // Setting an entry hook is a one-way operation, once set, it cannot be 5141 // changed or unset. 5142 if (isolate->function_entry_hook() != NULL) 5143 return false; 5144 5145 isolate->set_function_entry_hook(entry_hook); 5146 return true; 5147 } 5148 5149 5150 void v8::V8::SetJitCodeEventHandler( 5151 JitCodeEventOptions options, JitCodeEventHandler event_handler) { 5152 i::Isolate* isolate = i::Isolate::Current(); 5153 // Ensure that logging is initialized for our isolate. 5154 isolate->InitializeLoggingAndCounters(); 5155 isolate->logger()->SetCodeEventHandler(options, event_handler); 5156 } 5157 5158 void v8::V8::SetArrayBufferAllocator( 5159 ArrayBuffer::Allocator* allocator) { 5160 if (!ApiCheck(i::V8::ArrayBufferAllocator() == NULL, 5161 "v8::V8::SetArrayBufferAllocator", 5162 "ArrayBufferAllocator might only be set once")) 5163 return; 5164 i::V8::SetArrayBufferAllocator(allocator); 5165 } 5166 5167 5168 bool v8::V8::Dispose() { 5169 i::Isolate* isolate = i::Isolate::Current(); 5170 if (!ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(), 5171 "v8::V8::Dispose()", 5172 "Use v8::Isolate::Dispose() for a non-default isolate.")) { 5173 return false; 5174 } 5175 i::V8::TearDown(); 5176 return true; 5177 } 5178 5179 5180 HeapStatistics::HeapStatistics(): total_heap_size_(0), 5181 total_heap_size_executable_(0), 5182 total_physical_size_(0), 5183 used_heap_size_(0), 5184 heap_size_limit_(0) { } 5185 5186 5187 void v8::V8::VisitExternalResources(ExternalResourceVisitor* visitor) { 5188 i::Isolate* isolate = i::Isolate::Current(); 5189 isolate->heap()->VisitExternalResources(visitor); 5190 } 5191 5192 5193 class VisitorAdapter : public i::ObjectVisitor { 5194 public: 5195 explicit VisitorAdapter(PersistentHandleVisitor* visitor) 5196 : visitor_(visitor) {} 5197 virtual void VisitPointers(i::Object** start, i::Object** end) { 5198 UNREACHABLE(); 5199 } 5200 virtual void VisitEmbedderReference(i::Object** p, uint16_t class_id) { 5201 Value* value = ToApi<Value>(i::Handle<i::Object>(p)); 5202 visitor_->VisitPersistentHandle( 5203 reinterpret_cast<Persistent<Value>*>(&value), class_id); 5204 } 5205 private: 5206 PersistentHandleVisitor* visitor_; 5207 }; 5208 5209 5210 void v8::V8::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) { 5211 i::Isolate* isolate = i::Isolate::Current(); 5212 i::DisallowHeapAllocation no_allocation; 5213 5214 VisitorAdapter visitor_adapter(visitor); 5215 isolate->global_handles()->IterateAllRootsWithClassIds(&visitor_adapter); 5216 } 5217 5218 5219 void v8::V8::VisitHandlesForPartialDependence( 5220 Isolate* exported_isolate, PersistentHandleVisitor* visitor) { 5221 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(exported_isolate); 5222 ASSERT(isolate == i::Isolate::Current()); 5223 i::DisallowHeapAllocation no_allocation; 5224 5225 VisitorAdapter visitor_adapter(visitor); 5226 isolate->global_handles()->IterateAllRootsInNewSpaceWithClassIds( 5227 &visitor_adapter); 5228 } 5229 5230 5231 bool v8::V8::IdleNotification(int hint) { 5232 // Returning true tells the caller that it need not 5233 // continue to call IdleNotification. 5234 i::Isolate* isolate = i::Isolate::Current(); 5235 if (isolate == NULL || !isolate->IsInitialized()) return true; 5236 if (!i::FLAG_use_idle_notification) return true; 5237 return isolate->heap()->IdleNotification(hint); 5238 } 5239 5240 5241 void v8::V8::LowMemoryNotification() { 5242 i::Isolate* isolate = i::Isolate::Current(); 5243 if (isolate == NULL || !isolate->IsInitialized()) return; 5244 isolate->heap()->CollectAllAvailableGarbage("low memory notification"); 5245 } 5246 5247 5248 int v8::V8::ContextDisposedNotification() { 5249 i::Isolate* isolate = i::Isolate::Current(); 5250 if (!isolate->IsInitialized()) return 0; 5251 return isolate->heap()->NotifyContextDisposed(); 5252 } 5253 5254 5255 bool v8::V8::InitializeICU() { 5256 return i::InitializeICU(); 5257 } 5258 5259 5260 const char* v8::V8::GetVersion() { 5261 return i::Version::GetVersion(); 5262 } 5263 5264 5265 static i::Handle<i::Context> CreateEnvironment( 5266 i::Isolate* isolate, 5267 v8::ExtensionConfiguration* extensions, 5268 v8::Handle<ObjectTemplate> global_template, 5269 v8::Handle<Value> global_object) { 5270 i::Handle<i::Context> env; 5271 5272 // Enter V8 via an ENTER_V8 scope. 5273 { 5274 ENTER_V8(isolate); 5275 v8::Handle<ObjectTemplate> proxy_template = global_template; 5276 i::Handle<i::FunctionTemplateInfo> proxy_constructor; 5277 i::Handle<i::FunctionTemplateInfo> global_constructor; 5278 5279 if (!global_template.IsEmpty()) { 5280 // Make sure that the global_template has a constructor. 5281 global_constructor = EnsureConstructor(*global_template); 5282 5283 // Create a fresh template for the global proxy object. 5284 proxy_template = ObjectTemplate::New(); 5285 proxy_constructor = EnsureConstructor(*proxy_template); 5286 5287 // Set the global template to be the prototype template of 5288 // global proxy template. 5289 proxy_constructor->set_prototype_template( 5290 *Utils::OpenHandle(*global_template)); 5291 5292 // Migrate security handlers from global_template to 5293 // proxy_template. Temporarily removing access check 5294 // information from the global template. 5295 if (!global_constructor->access_check_info()->IsUndefined()) { 5296 proxy_constructor->set_access_check_info( 5297 global_constructor->access_check_info()); 5298 proxy_constructor->set_needs_access_check( 5299 global_constructor->needs_access_check()); 5300 global_constructor->set_needs_access_check(false); 5301 global_constructor->set_access_check_info( 5302 isolate->heap()->undefined_value()); 5303 } 5304 } 5305 5306 // Create the environment. 5307 env = isolate->bootstrapper()->CreateEnvironment( 5308 Utils::OpenHandle(*global_object, true), 5309 proxy_template, 5310 extensions); 5311 5312 // Restore the access check info on the global template. 5313 if (!global_template.IsEmpty()) { 5314 ASSERT(!global_constructor.is_null()); 5315 ASSERT(!proxy_constructor.is_null()); 5316 global_constructor->set_access_check_info( 5317 proxy_constructor->access_check_info()); 5318 global_constructor->set_needs_access_check( 5319 proxy_constructor->needs_access_check()); 5320 } 5321 isolate->runtime_profiler()->Reset(); 5322 } 5323 // Leave V8. 5324 5325 return env; 5326 } 5327 5328 Local<Context> v8::Context::New( 5329 v8::Isolate* external_isolate, 5330 v8::ExtensionConfiguration* extensions, 5331 v8::Handle<ObjectTemplate> global_template, 5332 v8::Handle<Value> global_object) { 5333 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate); 5334 EnsureInitializedForIsolate(isolate, "v8::Context::New()"); 5335 LOG_API(isolate, "Context::New"); 5336 ON_BAILOUT(isolate, "v8::Context::New()", return Local<Context>()); 5337 i::HandleScope scope(isolate); 5338 i::Handle<i::Context> env = 5339 CreateEnvironment(isolate, extensions, global_template, global_object); 5340 if (env.is_null()) return Local<Context>(); 5341 return Utils::ToLocal(scope.CloseAndEscape(env)); 5342 } 5343 5344 5345 void v8::Context::SetSecurityToken(Handle<Value> token) { 5346 i::Isolate* isolate = i::Isolate::Current(); 5347 ENTER_V8(isolate); 5348 i::Handle<i::Context> env = Utils::OpenHandle(this); 5349 i::Handle<i::Object> token_handle = Utils::OpenHandle(*token); 5350 env->set_security_token(*token_handle); 5351 } 5352 5353 5354 void v8::Context::UseDefaultSecurityToken() { 5355 i::Isolate* isolate = i::Isolate::Current(); 5356 ENTER_V8(isolate); 5357 i::Handle<i::Context> env = Utils::OpenHandle(this); 5358 env->set_security_token(env->global_object()); 5359 } 5360 5361 5362 Handle<Value> v8::Context::GetSecurityToken() { 5363 i::Isolate* isolate = i::Isolate::Current(); 5364 i::Handle<i::Context> env = Utils::OpenHandle(this); 5365 i::Object* security_token = env->security_token(); 5366 i::Handle<i::Object> token_handle(security_token, isolate); 5367 return Utils::ToLocal(token_handle); 5368 } 5369 5370 5371 bool Context::HasOutOfMemoryException() { 5372 i::Handle<i::Context> env = Utils::OpenHandle(this); 5373 return env->has_out_of_memory(); 5374 } 5375 5376 5377 bool Context::InContext() { 5378 return i::Isolate::Current()->context() != NULL; 5379 } 5380 5381 5382 v8::Isolate* Context::GetIsolate() { 5383 i::Handle<i::Context> env = Utils::OpenHandle(this); 5384 return reinterpret_cast<Isolate*>(env->GetIsolate()); 5385 } 5386 5387 5388 v8::Local<v8::Context> Context::GetEntered() { 5389 i::Isolate* isolate = i::Isolate::Current(); 5390 if (!EnsureInitializedForIsolate(isolate, "v8::Context::GetEntered()")) { 5391 return Local<Context>(); 5392 } 5393 return reinterpret_cast<Isolate*>(isolate)->GetEnteredContext(); 5394 } 5395 5396 5397 v8::Local<v8::Context> Context::GetCurrent() { 5398 i::Isolate* isolate = i::Isolate::Current(); 5399 return reinterpret_cast<Isolate*>(isolate)->GetCurrentContext(); 5400 } 5401 5402 5403 v8::Local<v8::Context> Context::GetCalling() { 5404 i::Isolate* isolate = i::Isolate::Current(); 5405 return reinterpret_cast<Isolate*>(isolate)->GetCallingContext(); 5406 } 5407 5408 5409 v8::Local<v8::Object> Context::Global() { 5410 i::Handle<i::Context> context = Utils::OpenHandle(this); 5411 i::Isolate* isolate = context->GetIsolate(); 5412 i::Handle<i::Object> global(context->global_proxy(), isolate); 5413 // TODO(dcarney): This should always return the global proxy 5414 // but can't presently as calls to GetProtoype will return the wrong result. 5415 if (i::Handle<i::JSGlobalProxy>::cast( 5416 global)->IsDetachedFrom(context->global_object())) { 5417 global = i::Handle<i::Object>(context->global_object(), isolate); 5418 } 5419 return Utils::ToLocal(i::Handle<i::JSObject>::cast(global)); 5420 } 5421 5422 5423 void Context::DetachGlobal() { 5424 i::Handle<i::Context> context = Utils::OpenHandle(this); 5425 i::Isolate* isolate = context->GetIsolate(); 5426 ENTER_V8(isolate); 5427 isolate->bootstrapper()->DetachGlobal(context); 5428 } 5429 5430 5431 void Context::AllowCodeGenerationFromStrings(bool allow) { 5432 i::Handle<i::Context> context = Utils::OpenHandle(this); 5433 i::Isolate* isolate = context->GetIsolate(); 5434 ENTER_V8(isolate); 5435 context->set_allow_code_gen_from_strings( 5436 allow ? isolate->heap()->true_value() : isolate->heap()->false_value()); 5437 } 5438 5439 5440 bool Context::IsCodeGenerationFromStringsAllowed() { 5441 i::Handle<i::Context> context = Utils::OpenHandle(this); 5442 return !context->allow_code_gen_from_strings()->IsFalse(); 5443 } 5444 5445 5446 void Context::SetErrorMessageForCodeGenerationFromStrings( 5447 Handle<String> error) { 5448 i::Handle<i::Context> context = Utils::OpenHandle(this); 5449 i::Handle<i::String> error_handle = Utils::OpenHandle(*error); 5450 context->set_error_message_for_code_gen_from_strings(*error_handle); 5451 } 5452 5453 5454 Local<v8::Object> ObjectTemplate::NewInstance() { 5455 i::Isolate* isolate = i::Isolate::Current(); 5456 ON_BAILOUT(isolate, "v8::ObjectTemplate::NewInstance()", 5457 return Local<v8::Object>()); 5458 LOG_API(isolate, "ObjectTemplate::NewInstance"); 5459 ENTER_V8(isolate); 5460 EXCEPTION_PREAMBLE(isolate); 5461 i::Handle<i::Object> obj = 5462 i::Execution::InstantiateObject(Utils::OpenHandle(this), 5463 &has_pending_exception); 5464 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); 5465 return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj)); 5466 } 5467 5468 5469 Local<v8::Function> FunctionTemplate::GetFunction() { 5470 i::Isolate* isolate = i::Isolate::Current(); 5471 ON_BAILOUT(isolate, "v8::FunctionTemplate::GetFunction()", 5472 return Local<v8::Function>()); 5473 LOG_API(isolate, "FunctionTemplate::GetFunction"); 5474 ENTER_V8(isolate); 5475 EXCEPTION_PREAMBLE(isolate); 5476 i::Handle<i::Object> obj = 5477 i::Execution::InstantiateFunction(Utils::OpenHandle(this), 5478 &has_pending_exception); 5479 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Function>()); 5480 return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj)); 5481 } 5482 5483 5484 bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) { 5485 ON_BAILOUT(i::Isolate::Current(), "v8::FunctionTemplate::HasInstanceOf()", 5486 return false); 5487 i::Object* obj = *Utils::OpenHandle(*value); 5488 return Utils::OpenHandle(this)->IsTemplateFor(obj); 5489 } 5490 5491 5492 Local<External> v8::External::New(Isolate* isolate, void* value) { 5493 STATIC_ASSERT(sizeof(value) == sizeof(i::Address)); 5494 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 5495 EnsureInitializedForIsolate(i_isolate, "v8::External::New()"); 5496 LOG_API(i_isolate, "External::New"); 5497 ENTER_V8(i_isolate); 5498 i::Handle<i::JSObject> external = i_isolate->factory()->NewExternal(value); 5499 return Utils::ExternalToLocal(external); 5500 } 5501 5502 5503 Local<External> v8::External::New(void* value) { 5504 return v8::External::New(Isolate::GetCurrent(), value); 5505 } 5506 5507 5508 void* External::Value() const { 5509 return ExternalValue(*Utils::OpenHandle(this)); 5510 } 5511 5512 5513 Local<String> v8::String::Empty() { 5514 i::Isolate* isolate = i::Isolate::Current(); 5515 if (!EnsureInitializedForIsolate(isolate, "v8::String::Empty()")) { 5516 return v8::Local<String>(); 5517 } 5518 LOG_API(isolate, "String::Empty()"); 5519 return Utils::ToLocal(isolate->factory()->empty_string()); 5520 } 5521 5522 5523 // anonymous namespace for string creation helper functions 5524 namespace { 5525 5526 inline int StringLength(const char* string) { 5527 return i::StrLength(string); 5528 } 5529 5530 5531 inline int StringLength(const uint8_t* string) { 5532 return i::StrLength(reinterpret_cast<const char*>(string)); 5533 } 5534 5535 5536 inline int StringLength(const uint16_t* string) { 5537 int length = 0; 5538 while (string[length] != '\0') 5539 length++; 5540 return length; 5541 } 5542 5543 5544 inline i::Handle<i::String> NewString(i::Factory* factory, 5545 String::NewStringType type, 5546 i::Vector<const char> string) { 5547 if (type ==String::kInternalizedString) { 5548 return factory->InternalizeUtf8String(string); 5549 } 5550 return factory->NewStringFromUtf8(string); 5551 } 5552 5553 5554 inline i::Handle<i::String> NewString(i::Factory* factory, 5555 String::NewStringType type, 5556 i::Vector<const uint8_t> string) { 5557 if (type == String::kInternalizedString) { 5558 return factory->InternalizeOneByteString(string); 5559 } 5560 return factory->NewStringFromOneByte(string); 5561 } 5562 5563 5564 inline i::Handle<i::String> NewString(i::Factory* factory, 5565 String::NewStringType type, 5566 i::Vector<const uint16_t> string) { 5567 if (type == String::kInternalizedString) { 5568 return factory->InternalizeTwoByteString(string); 5569 } 5570 return factory->NewStringFromTwoByte(string); 5571 } 5572 5573 5574 template<typename Char> 5575 inline Local<String> NewString(Isolate* v8_isolate, 5576 const char* location, 5577 const char* env, 5578 const Char* data, 5579 String::NewStringType type, 5580 int length) { 5581 i::Isolate* isolate = reinterpret_cast<internal::Isolate*>(v8_isolate); 5582 EnsureInitializedForIsolate(isolate, location); 5583 LOG_API(isolate, env); 5584 if (length == 0 && type != String::kUndetectableString) { 5585 return String::Empty(); 5586 } 5587 ENTER_V8(isolate); 5588 if (length == -1) length = StringLength(data); 5589 i::Handle<i::String> result = NewString( 5590 isolate->factory(), type, i::Vector<const Char>(data, length)); 5591 if (type == String::kUndetectableString) { 5592 result->MarkAsUndetectable(); 5593 } 5594 return Utils::ToLocal(result); 5595 } 5596 5597 } // anonymous namespace 5598 5599 5600 Local<String> String::NewFromUtf8(Isolate* isolate, 5601 const char* data, 5602 NewStringType type, 5603 int length) { 5604 return NewString(isolate, 5605 "v8::String::NewFromUtf8()", 5606 "String::NewFromUtf8", 5607 data, 5608 type, 5609 length); 5610 } 5611 5612 5613 Local<String> String::NewFromOneByte(Isolate* isolate, 5614 const uint8_t* data, 5615 NewStringType type, 5616 int length) { 5617 return NewString(isolate, 5618 "v8::String::NewFromOneByte()", 5619 "String::NewFromOneByte", 5620 data, 5621 type, 5622 length); 5623 } 5624 5625 5626 Local<String> String::NewFromTwoByte(Isolate* isolate, 5627 const uint16_t* data, 5628 NewStringType type, 5629 int length) { 5630 return NewString(isolate, 5631 "v8::String::NewFromTwoByte()", 5632 "String::NewFromTwoByte", 5633 data, 5634 type, 5635 length); 5636 } 5637 5638 5639 Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) { 5640 i::Handle<i::String> left_string = Utils::OpenHandle(*left); 5641 i::Isolate* isolate = left_string->GetIsolate(); 5642 EnsureInitializedForIsolate(isolate, "v8::String::New()"); 5643 LOG_API(isolate, "String::New(char)"); 5644 ENTER_V8(isolate); 5645 i::Handle<i::String> right_string = Utils::OpenHandle(*right); 5646 i::Handle<i::String> result = isolate->factory()->NewConsString(left_string, 5647 right_string); 5648 return Utils::ToLocal(result); 5649 } 5650 5651 5652 i::Handle<i::String> NewExternalStringHandle(i::Isolate* isolate, 5653 v8::String::ExternalStringResource* resource) { 5654 i::Handle<i::String> result = 5655 isolate->factory()->NewExternalStringFromTwoByte(resource); 5656 return result; 5657 } 5658 5659 5660 i::Handle<i::String> NewExternalAsciiStringHandle(i::Isolate* isolate, 5661 v8::String::ExternalAsciiStringResource* resource) { 5662 i::Handle<i::String> result = 5663 isolate->factory()->NewExternalStringFromAscii(resource); 5664 return result; 5665 } 5666 5667 5668 bool RedirectToExternalString(i::Isolate* isolate, 5669 i::Handle<i::String> parent, 5670 i::Handle<i::String> external) { 5671 if (parent->IsConsString()) { 5672 i::Handle<i::ConsString> cons = i::Handle<i::ConsString>::cast(parent); 5673 cons->set_first(*external); 5674 cons->set_second(isolate->heap()->empty_string()); 5675 } else { 5676 ASSERT(parent->IsSlicedString()); 5677 i::Handle<i::SlicedString> slice = i::Handle<i::SlicedString>::cast(parent); 5678 slice->set_parent(*external); 5679 slice->set_offset(0); 5680 } 5681 return true; 5682 } 5683 5684 5685 Local<String> v8::String::NewExternal( 5686 Isolate* isolate, 5687 v8::String::ExternalStringResource* resource) { 5688 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 5689 EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()"); 5690 LOG_API(i_isolate, "String::NewExternal"); 5691 ENTER_V8(i_isolate); 5692 CHECK(resource && resource->data()); 5693 i::Handle<i::String> result = NewExternalStringHandle(i_isolate, resource); 5694 i_isolate->heap()->external_string_table()->AddString(*result); 5695 return Utils::ToLocal(result); 5696 } 5697 5698 5699 Local<String> v8::String::NewExternal( 5700 v8::String::ExternalStringResource* resource) { 5701 return NewExternal(Isolate::GetCurrent(), resource); 5702 } 5703 5704 5705 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { 5706 i::Handle<i::String> obj = Utils::OpenHandle(this); 5707 i::Isolate* isolate = obj->GetIsolate(); 5708 if (i::StringShape(*obj).IsExternalTwoByte()) { 5709 return false; // Already an external string. 5710 } 5711 ENTER_V8(isolate); 5712 if (isolate->string_tracker()->IsFreshUnusedString(obj)) { 5713 return false; 5714 } 5715 if (isolate->heap()->IsInGCPostProcessing()) { 5716 return false; 5717 } 5718 CHECK(resource && resource->data()); 5719 5720 bool result; 5721 i::Handle<i::String> external; 5722 if (isolate->heap()->old_pointer_space()->Contains(*obj)) { 5723 // We do not allow external strings in the old pointer space. Instead of 5724 // converting the string in-place, we keep the cons/sliced string and 5725 // point it to a newly-allocated external string. 5726 external = NewExternalStringHandle(isolate, resource); 5727 result = RedirectToExternalString(isolate, obj, external); 5728 } else { 5729 result = obj->MakeExternal(resource); 5730 external = obj; 5731 } 5732 5733 ASSERT(external->IsExternalString()); 5734 if (result && !external->IsInternalizedString()) { 5735 isolate->heap()->external_string_table()->AddString(*external); 5736 } 5737 return result; 5738 } 5739 5740 5741 Local<String> v8::String::NewExternal( 5742 Isolate* isolate, 5743 v8::String::ExternalAsciiStringResource* resource) { 5744 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 5745 EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()"); 5746 LOG_API(i_isolate, "String::NewExternal"); 5747 ENTER_V8(i_isolate); 5748 CHECK(resource && resource->data()); 5749 i::Handle<i::String> result = 5750 NewExternalAsciiStringHandle(i_isolate, resource); 5751 i_isolate->heap()->external_string_table()->AddString(*result); 5752 return Utils::ToLocal(result); 5753 } 5754 5755 5756 Local<String> v8::String::NewExternal( 5757 v8::String::ExternalAsciiStringResource* resource) { 5758 return NewExternal(Isolate::GetCurrent(), resource); 5759 } 5760 5761 5762 bool v8::String::MakeExternal( 5763 v8::String::ExternalAsciiStringResource* resource) { 5764 i::Handle<i::String> obj = Utils::OpenHandle(this); 5765 i::Isolate* isolate = obj->GetIsolate(); 5766 if (i::StringShape(*obj).IsExternalTwoByte()) { 5767 return false; // Already an external string. 5768 } 5769 ENTER_V8(isolate); 5770 if (isolate->string_tracker()->IsFreshUnusedString(obj)) { 5771 return false; 5772 } 5773 if (isolate->heap()->IsInGCPostProcessing()) { 5774 return false; 5775 } 5776 CHECK(resource && resource->data()); 5777 5778 bool result; 5779 i::Handle<i::String> external; 5780 if (isolate->heap()->old_pointer_space()->Contains(*obj)) { 5781 // We do not allow external strings in the old pointer space. Instead of 5782 // converting the string in-place, we keep the cons/sliced string and 5783 // point it to a newly-allocated external string. 5784 external = NewExternalAsciiStringHandle(isolate, resource); 5785 result = RedirectToExternalString(isolate, obj, external); 5786 } else { 5787 result = obj->MakeExternal(resource); 5788 external = obj; 5789 } 5790 5791 ASSERT(external->IsExternalString()); 5792 if (result && !external->IsInternalizedString()) { 5793 isolate->heap()->external_string_table()->AddString(*external); 5794 } 5795 return result; 5796 } 5797 5798 5799 bool v8::String::CanMakeExternal() { 5800 if (!internal::FLAG_clever_optimizations) return false; 5801 i::Handle<i::String> obj = Utils::OpenHandle(this); 5802 i::Isolate* isolate = obj->GetIsolate(); 5803 5804 // TODO(yangguo): Externalizing sliced/cons strings allocates. 5805 // This rule can be removed when all code that can 5806 // trigger an access check is handlified and therefore GC safe. 5807 if (isolate->heap()->old_pointer_space()->Contains(*obj)) return false; 5808 5809 if (isolate->string_tracker()->IsFreshUnusedString(obj)) return false; 5810 int size = obj->Size(); // Byte size of the original string. 5811 if (size < i::ExternalString::kShortSize) return false; 5812 i::StringShape shape(*obj); 5813 return !shape.IsExternal(); 5814 } 5815 5816 5817 Local<v8::Object> v8::Object::New(Isolate* isolate) { 5818 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 5819 EnsureInitializedForIsolate(i_isolate, "v8::Object::New()"); 5820 LOG_API(i_isolate, "Object::New"); 5821 ENTER_V8(i_isolate); 5822 i::Handle<i::JSObject> obj = 5823 i_isolate->factory()->NewJSObject(i_isolate->object_function()); 5824 return Utils::ToLocal(obj); 5825 } 5826 5827 5828 Local<v8::Object> v8::Object::New() { 5829 return New(Isolate::GetCurrent()); 5830 } 5831 5832 5833 Local<v8::Value> v8::NumberObject::New(Isolate* isolate, double value) { 5834 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 5835 EnsureInitializedForIsolate(i_isolate, "v8::NumberObject::New()"); 5836 LOG_API(i_isolate, "NumberObject::New"); 5837 ENTER_V8(i_isolate); 5838 i::Handle<i::Object> number = i_isolate->factory()->NewNumber(value); 5839 i::Handle<i::Object> obj = i_isolate->factory()->ToObject(number); 5840 return Utils::ToLocal(obj); 5841 } 5842 5843 5844 Local<v8::Value> v8::NumberObject::New(double value) { 5845 return New(Isolate::GetCurrent(), value); 5846 } 5847 5848 5849 double v8::NumberObject::ValueOf() const { 5850 i::Isolate* isolate = i::Isolate::Current(); 5851 LOG_API(isolate, "NumberObject::NumberValue"); 5852 i::Handle<i::Object> obj = Utils::OpenHandle(this); 5853 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj); 5854 return jsvalue->value()->Number(); 5855 } 5856 5857 5858 Local<v8::Value> v8::BooleanObject::New(bool value) { 5859 i::Isolate* isolate = i::Isolate::Current(); 5860 EnsureInitializedForIsolate(isolate, "v8::BooleanObject::New()"); 5861 LOG_API(isolate, "BooleanObject::New"); 5862 ENTER_V8(isolate); 5863 i::Handle<i::Object> boolean(value 5864 ? isolate->heap()->true_value() 5865 : isolate->heap()->false_value(), 5866 isolate); 5867 i::Handle<i::Object> obj = isolate->factory()->ToObject(boolean); 5868 return Utils::ToLocal(obj); 5869 } 5870 5871 5872 bool v8::BooleanObject::ValueOf() const { 5873 i::Isolate* isolate = i::Isolate::Current(); 5874 LOG_API(isolate, "BooleanObject::BooleanValue"); 5875 i::Handle<i::Object> obj = Utils::OpenHandle(this); 5876 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj); 5877 return jsvalue->value()->IsTrue(); 5878 } 5879 5880 5881 Local<v8::Value> v8::StringObject::New(Handle<String> value) { 5882 i::Isolate* isolate = i::Isolate::Current(); 5883 EnsureInitializedForIsolate(isolate, "v8::StringObject::New()"); 5884 LOG_API(isolate, "StringObject::New"); 5885 ENTER_V8(isolate); 5886 i::Handle<i::Object> obj = 5887 isolate->factory()->ToObject(Utils::OpenHandle(*value)); 5888 return Utils::ToLocal(obj); 5889 } 5890 5891 5892 Local<v8::String> v8::StringObject::ValueOf() const { 5893 i::Isolate* isolate = i::Isolate::Current(); 5894 LOG_API(isolate, "StringObject::StringValue"); 5895 i::Handle<i::Object> obj = Utils::OpenHandle(this); 5896 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj); 5897 return Utils::ToLocal( 5898 i::Handle<i::String>(i::String::cast(jsvalue->value()))); 5899 } 5900 5901 5902 Local<v8::Value> v8::SymbolObject::New(Isolate* isolate, Handle<Symbol> value) { 5903 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 5904 EnsureInitializedForIsolate(i_isolate, "v8::SymbolObject::New()"); 5905 LOG_API(i_isolate, "SymbolObject::New"); 5906 ENTER_V8(i_isolate); 5907 i::Handle<i::Object> obj = 5908 i_isolate->factory()->ToObject(Utils::OpenHandle(*value)); 5909 return Utils::ToLocal(obj); 5910 } 5911 5912 5913 Local<v8::Symbol> v8::SymbolObject::ValueOf() const { 5914 i::Isolate* isolate = i::Isolate::Current(); 5915 LOG_API(isolate, "SymbolObject::SymbolValue"); 5916 i::Handle<i::Object> obj = Utils::OpenHandle(this); 5917 i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj); 5918 return Utils::ToLocal( 5919 i::Handle<i::Symbol>(i::Symbol::cast(jsvalue->value()))); 5920 } 5921 5922 5923 Local<v8::Value> v8::Date::New(Isolate* isolate, double time) { 5924 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 5925 EnsureInitializedForIsolate(i_isolate, "v8::Date::New()"); 5926 LOG_API(i_isolate, "Date::New"); 5927 if (std::isnan(time)) { 5928 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs. 5929 time = i::OS::nan_value(); 5930 } 5931 ENTER_V8(i_isolate); 5932 EXCEPTION_PREAMBLE(i_isolate); 5933 i::Handle<i::Object> obj = 5934 i::Execution::NewDate(i_isolate, time, &has_pending_exception); 5935 EXCEPTION_BAILOUT_CHECK(i_isolate, Local<v8::Value>()); 5936 return Utils::ToLocal(obj); 5937 } 5938 5939 5940 Local<v8::Value> v8::Date::New(double time) { 5941 return New(Isolate::GetCurrent(), time); 5942 } 5943 5944 5945 double v8::Date::ValueOf() const { 5946 i::Isolate* isolate = i::Isolate::Current(); 5947 LOG_API(isolate, "Date::NumberValue"); 5948 i::Handle<i::Object> obj = Utils::OpenHandle(this); 5949 i::Handle<i::JSDate> jsdate = i::Handle<i::JSDate>::cast(obj); 5950 return jsdate->value()->Number(); 5951 } 5952 5953 5954 void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) { 5955 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 5956 ON_BAILOUT(i_isolate, "v8::Date::DateTimeConfigurationChangeNotification()", 5957 return); 5958 LOG_API(i_isolate, "Date::DateTimeConfigurationChangeNotification"); 5959 ENTER_V8(i_isolate); 5960 5961 i_isolate->date_cache()->ResetDateCache(); 5962 5963 i::HandleScope scope(i_isolate); 5964 // Get the function ResetDateCache (defined in date.js). 5965 i::Handle<i::String> func_name_str = 5966 i_isolate->factory()->InternalizeOneByteString( 5967 STATIC_ASCII_VECTOR("ResetDateCache")); 5968 i::MaybeObject* result = 5969 i_isolate->js_builtins_object()->GetProperty(*func_name_str); 5970 i::Object* object_func; 5971 if (!result->ToObject(&object_func)) { 5972 return; 5973 } 5974 5975 if (object_func->IsJSFunction()) { 5976 i::Handle<i::JSFunction> func = 5977 i::Handle<i::JSFunction>(i::JSFunction::cast(object_func)); 5978 5979 // Call ResetDateCache(0 but expect no exceptions: 5980 bool caught_exception = false; 5981 i::Execution::TryCall(func, 5982 i_isolate->js_builtins_object(), 5983 0, 5984 NULL, 5985 &caught_exception); 5986 } 5987 } 5988 5989 5990 void v8::Date::DateTimeConfigurationChangeNotification() { 5991 DateTimeConfigurationChangeNotification(Isolate::GetCurrent()); 5992 } 5993 5994 5995 static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) { 5996 i::Isolate* isolate = i::Isolate::Current(); 5997 uint8_t flags_buf[3]; 5998 int num_flags = 0; 5999 if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g'; 6000 if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm'; 6001 if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i'; 6002 ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf))); 6003 return isolate->factory()->InternalizeOneByteString( 6004 i::Vector<const uint8_t>(flags_buf, num_flags)); 6005 } 6006 6007 6008 Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern, 6009 Flags flags) { 6010 i::Isolate* isolate = Utils::OpenHandle(*pattern)->GetIsolate(); 6011 EnsureInitializedForIsolate(isolate, "v8::RegExp::New()"); 6012 LOG_API(isolate, "RegExp::New"); 6013 ENTER_V8(isolate); 6014 EXCEPTION_PREAMBLE(isolate); 6015 i::Handle<i::JSRegExp> obj = i::Execution::NewJSRegExp( 6016 Utils::OpenHandle(*pattern), 6017 RegExpFlagsToString(flags), 6018 &has_pending_exception); 6019 EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::RegExp>()); 6020 return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj)); 6021 } 6022 6023 6024 Local<v8::String> v8::RegExp::GetSource() const { 6025 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this); 6026 return Utils::ToLocal(i::Handle<i::String>(obj->Pattern())); 6027 } 6028 6029 6030 // Assert that the static flags cast in GetFlags is valid. 6031 #define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag) \ 6032 STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) == \ 6033 static_cast<int>(i::JSRegExp::internal_flag)) 6034 REGEXP_FLAG_ASSERT_EQ(kNone, NONE); 6035 REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL); 6036 REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE); 6037 REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE); 6038 #undef REGEXP_FLAG_ASSERT_EQ 6039 6040 v8::RegExp::Flags v8::RegExp::GetFlags() const { 6041 i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this); 6042 return static_cast<RegExp::Flags>(obj->GetFlags().value()); 6043 } 6044 6045 6046 Local<v8::Array> v8::Array::New(Isolate* isolate, int length) { 6047 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 6048 EnsureInitializedForIsolate(i_isolate, "v8::Array::New()"); 6049 LOG_API(i_isolate, "Array::New"); 6050 ENTER_V8(i_isolate); 6051 int real_length = length > 0 ? length : 0; 6052 i::Handle<i::JSArray> obj = i_isolate->factory()->NewJSArray(real_length); 6053 i::Handle<i::Object> length_obj = 6054 i_isolate->factory()->NewNumberFromInt(real_length); 6055 obj->set_length(*length_obj); 6056 return Utils::ToLocal(obj); 6057 } 6058 6059 6060 Local<v8::Array> v8::Array::New(int length) { 6061 return New(Isolate::GetCurrent(), length); 6062 } 6063 6064 6065 uint32_t v8::Array::Length() const { 6066 i::Handle<i::JSArray> obj = Utils::OpenHandle(this); 6067 i::Object* length = obj->length(); 6068 if (length->IsSmi()) { 6069 return i::Smi::cast(length)->value(); 6070 } else { 6071 return static_cast<uint32_t>(length->Number()); 6072 } 6073 } 6074 6075 6076 Local<Object> Array::CloneElementAt(uint32_t index) { 6077 i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); 6078 ON_BAILOUT(isolate, "v8::Array::CloneElementAt()", return Local<Object>()); 6079 i::Handle<i::JSObject> self = Utils::OpenHandle(this); 6080 if (!self->HasFastObjectElements()) { 6081 return Local<Object>(); 6082 } 6083 i::FixedArray* elms = i::FixedArray::cast(self->elements()); 6084 i::Object* paragon = elms->get(index); 6085 if (!paragon->IsJSObject()) { 6086 return Local<Object>(); 6087 } 6088 i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon)); 6089 EXCEPTION_PREAMBLE(isolate); 6090 ENTER_V8(isolate); 6091 i::Handle<i::JSObject> result = i::JSObject::Copy(paragon_handle); 6092 has_pending_exception = result.is_null(); 6093 EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>()); 6094 return Utils::ToLocal(result); 6095 } 6096 6097 6098 bool v8::ArrayBuffer::IsExternal() const { 6099 return Utils::OpenHandle(this)->is_external(); 6100 } 6101 6102 6103 v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() { 6104 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this); 6105 ApiCheck(!obj->is_external(), 6106 "v8::ArrayBuffer::Externalize", 6107 "ArrayBuffer already externalized"); 6108 obj->set_is_external(true); 6109 size_t byte_length = static_cast<size_t>(obj->byte_length()->Number()); 6110 Contents contents; 6111 contents.data_ = obj->backing_store(); 6112 contents.byte_length_ = byte_length; 6113 return contents; 6114 } 6115 6116 6117 void v8::ArrayBuffer::Neuter() { 6118 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this); 6119 i::Isolate* isolate = obj->GetIsolate(); 6120 ApiCheck(obj->is_external(), 6121 "v8::ArrayBuffer::Neuter", 6122 "Only externalized ArrayBuffers can be neutered"); 6123 LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()"); 6124 ENTER_V8(isolate); 6125 6126 for (i::Handle<i::Object> view_obj(obj->weak_first_view(), isolate); 6127 !view_obj->IsUndefined();) { 6128 i::Handle<i::JSArrayBufferView> view(i::JSArrayBufferView::cast(*view_obj)); 6129 if (view->IsJSTypedArray()) { 6130 i::JSTypedArray::cast(*view)->Neuter(); 6131 } else if (view->IsJSDataView()) { 6132 i::JSDataView::cast(*view)->Neuter(); 6133 } else { 6134 UNREACHABLE(); 6135 } 6136 view_obj = i::handle(view->weak_next(), isolate); 6137 } 6138 obj->Neuter(); 6139 } 6140 6141 6142 size_t v8::ArrayBuffer::ByteLength() const { 6143 i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this); 6144 return static_cast<size_t>(obj->byte_length()->Number()); 6145 } 6146 6147 6148 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) { 6149 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 6150 EnsureInitializedForIsolate(i_isolate, "v8::ArrayBuffer::New(size_t)"); 6151 LOG_API(i_isolate, "v8::ArrayBuffer::New(size_t)"); 6152 ENTER_V8(i_isolate); 6153 i::Handle<i::JSArrayBuffer> obj = 6154 i_isolate->factory()->NewJSArrayBuffer(); 6155 i::Runtime::SetupArrayBufferAllocatingData(i_isolate, obj, byte_length); 6156 return Utils::ToLocal(obj); 6157 } 6158 6159 6160 Local<ArrayBuffer> v8::ArrayBuffer::New(size_t byte_length) { 6161 return New(Isolate::GetCurrent(), byte_length); 6162 } 6163 6164 6165 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, void* data, 6166 size_t byte_length) { 6167 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 6168 EnsureInitializedForIsolate(i_isolate, "v8::ArrayBuffer::New(void*, size_t)"); 6169 LOG_API(i_isolate, "v8::ArrayBuffer::New(void*, size_t)"); 6170 ENTER_V8(i_isolate); 6171 i::Handle<i::JSArrayBuffer> obj = 6172 i_isolate->factory()->NewJSArrayBuffer(); 6173 i::Runtime::SetupArrayBuffer(i_isolate, obj, true, data, byte_length); 6174 return Utils::ToLocal(obj); 6175 } 6176 6177 6178 Local<ArrayBuffer> v8::ArrayBuffer::New(void* data, size_t byte_length) { 6179 return New(Isolate::GetCurrent(), data, byte_length); 6180 } 6181 6182 6183 Local<ArrayBuffer> v8::ArrayBufferView::Buffer() { 6184 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this); 6185 ASSERT(obj->buffer()->IsJSArrayBuffer()); 6186 i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(obj->buffer())); 6187 return Utils::ToLocal(buffer); 6188 } 6189 6190 6191 size_t v8::ArrayBufferView::ByteOffset() { 6192 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this); 6193 return static_cast<size_t>(obj->byte_offset()->Number()); 6194 } 6195 6196 6197 size_t v8::ArrayBufferView::ByteLength() { 6198 i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this); 6199 return static_cast<size_t>(obj->byte_length()->Number()); 6200 } 6201 6202 6203 size_t v8::TypedArray::Length() { 6204 i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this); 6205 return static_cast<size_t>(obj->length()->Number()); 6206 } 6207 6208 6209 static inline void SetupArrayBufferView( 6210 i::Isolate* isolate, 6211 i::Handle<i::JSArrayBufferView> obj, 6212 i::Handle<i::JSArrayBuffer> buffer, 6213 size_t byte_offset, 6214 size_t byte_length) { 6215 ASSERT(byte_offset + byte_length <= 6216 static_cast<size_t>(buffer->byte_length()->Number())); 6217 6218 obj->set_buffer(*buffer); 6219 6220 obj->set_weak_next(buffer->weak_first_view()); 6221 buffer->set_weak_first_view(*obj); 6222 6223 i::Handle<i::Object> byte_offset_object = 6224 isolate->factory()->NewNumberFromSize(byte_offset); 6225 obj->set_byte_offset(*byte_offset_object); 6226 6227 i::Handle<i::Object> byte_length_object = 6228 isolate->factory()->NewNumberFromSize(byte_length); 6229 obj->set_byte_length(*byte_length_object); 6230 } 6231 6232 template<typename ElementType, 6233 ExternalArrayType array_type, 6234 i::ElementsKind elements_kind> 6235 i::Handle<i::JSTypedArray> NewTypedArray( 6236 i::Isolate* isolate, 6237 Handle<ArrayBuffer> array_buffer, size_t byte_offset, size_t length) { 6238 i::Handle<i::JSTypedArray> obj = 6239 isolate->factory()->NewJSTypedArray(array_type); 6240 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer); 6241 6242 ASSERT(byte_offset % sizeof(ElementType) == 0); 6243 6244 CHECK(length <= (std::numeric_limits<size_t>::max() / sizeof(ElementType))); 6245 size_t byte_length = length * sizeof(ElementType); 6246 SetupArrayBufferView( 6247 isolate, obj, buffer, byte_offset, byte_length); 6248 6249 i::Handle<i::Object> length_object = 6250 isolate->factory()->NewNumberFromSize(length); 6251 obj->set_length(*length_object); 6252 6253 i::Handle<i::ExternalArray> elements = 6254 isolate->factory()->NewExternalArray( 6255 static_cast<int>(length), array_type, 6256 static_cast<uint8_t*>(buffer->backing_store()) + byte_offset); 6257 obj->set_elements(*elements); 6258 return obj; 6259 } 6260 6261 6262 #define TYPED_ARRAY_NEW(TypedArray, element_type, array_type, elements_kind) \ 6263 Local<TypedArray> TypedArray::New(Handle<ArrayBuffer> array_buffer, \ 6264 size_t byte_offset, size_t length) { \ 6265 i::Isolate* isolate = i::Isolate::Current(); \ 6266 EnsureInitializedForIsolate(isolate, \ 6267 "v8::" #TypedArray "::New(Handle<ArrayBuffer>, size_t, size_t)"); \ 6268 LOG_API(isolate, \ 6269 "v8::" #TypedArray "::New(Handle<ArrayBuffer>, size_t, size_t)"); \ 6270 ENTER_V8(isolate); \ 6271 i::Handle<i::JSTypedArray> obj = \ 6272 NewTypedArray<element_type, array_type, elements_kind>( \ 6273 isolate, array_buffer, byte_offset, length); \ 6274 return Utils::ToLocal##TypedArray(obj); \ 6275 } 6276 6277 6278 TYPED_ARRAY_NEW(Uint8Array, uint8_t, kExternalUnsignedByteArray, 6279 i::EXTERNAL_UNSIGNED_BYTE_ELEMENTS) 6280 TYPED_ARRAY_NEW(Uint8ClampedArray, uint8_t, kExternalPixelArray, 6281 i::EXTERNAL_PIXEL_ELEMENTS) 6282 TYPED_ARRAY_NEW(Int8Array, int8_t, kExternalByteArray, 6283 i::EXTERNAL_BYTE_ELEMENTS) 6284 TYPED_ARRAY_NEW(Uint16Array, uint16_t, kExternalUnsignedShortArray, 6285 i::EXTERNAL_UNSIGNED_SHORT_ELEMENTS) 6286 TYPED_ARRAY_NEW(Int16Array, int16_t, kExternalShortArray, 6287 i::EXTERNAL_SHORT_ELEMENTS) 6288 TYPED_ARRAY_NEW(Uint32Array, uint32_t, kExternalUnsignedIntArray, 6289 i::EXTERNAL_UNSIGNED_INT_ELEMENTS) 6290 TYPED_ARRAY_NEW(Int32Array, int32_t, kExternalIntArray, 6291 i::EXTERNAL_INT_ELEMENTS) 6292 TYPED_ARRAY_NEW(Float32Array, float, kExternalFloatArray, 6293 i::EXTERNAL_FLOAT_ELEMENTS) 6294 TYPED_ARRAY_NEW(Float64Array, double, kExternalDoubleArray, 6295 i::EXTERNAL_DOUBLE_ELEMENTS) 6296 6297 #undef TYPED_ARRAY_NEW 6298 6299 Local<DataView> DataView::New(Handle<ArrayBuffer> array_buffer, 6300 size_t byte_offset, size_t byte_length) { 6301 i::Isolate* isolate = i::Isolate::Current(); 6302 EnsureInitializedForIsolate( 6303 isolate, "v8::DataView::New(void*, size_t, size_t)"); 6304 LOG_API(isolate, "v8::DataView::New(void*, size_t, size_t)"); 6305 ENTER_V8(isolate); 6306 i::Handle<i::JSDataView> obj = isolate->factory()->NewJSDataView(); 6307 i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer); 6308 SetupArrayBufferView( 6309 isolate, obj, buffer, byte_offset, byte_length); 6310 return Utils::ToLocal(obj); 6311 } 6312 6313 6314 Local<Symbol> v8::Symbol::New(Isolate* isolate, const char* data, int length) { 6315 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 6316 EnsureInitializedForIsolate(i_isolate, "v8::Symbol::New()"); 6317 LOG_API(i_isolate, "Symbol::New()"); 6318 ENTER_V8(i_isolate); 6319 i::Handle<i::Symbol> result = i_isolate->factory()->NewSymbol(); 6320 if (data != NULL) { 6321 if (length == -1) length = i::StrLength(data); 6322 i::Handle<i::String> name = i_isolate->factory()->NewStringFromUtf8( 6323 i::Vector<const char>(data, length)); 6324 result->set_name(*name); 6325 } 6326 return Utils::ToLocal(result); 6327 } 6328 6329 6330 Local<Private> v8::Private::New( 6331 Isolate* isolate, const char* data, int length) { 6332 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 6333 EnsureInitializedForIsolate(i_isolate, "v8::Private::New()"); 6334 LOG_API(i_isolate, "Private::New()"); 6335 ENTER_V8(i_isolate); 6336 i::Handle<i::Symbol> symbol = i_isolate->factory()->NewPrivateSymbol(); 6337 if (data != NULL) { 6338 if (length == -1) length = i::StrLength(data); 6339 i::Handle<i::String> name = i_isolate->factory()->NewStringFromUtf8( 6340 i::Vector<const char>(data, length)); 6341 symbol->set_name(*name); 6342 } 6343 Local<Symbol> result = Utils::ToLocal(symbol); 6344 return v8::Handle<Private>(reinterpret_cast<Private*>(*result)); 6345 } 6346 6347 6348 Local<Number> v8::Number::New(double value) { 6349 i::Isolate* isolate = i::Isolate::Current(); 6350 EnsureInitializedForIsolate(isolate, "v8::Number::New()"); 6351 return Number::New(reinterpret_cast<Isolate*>(isolate), value); 6352 } 6353 6354 6355 Local<Number> v8::Number::New(Isolate* isolate, double value) { 6356 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 6357 ASSERT(internal_isolate->IsInitialized()); 6358 if (std::isnan(value)) { 6359 // Introduce only canonical NaN value into the VM, to avoid signaling NaNs. 6360 value = i::OS::nan_value(); 6361 } 6362 ENTER_V8(internal_isolate); 6363 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value); 6364 return Utils::NumberToLocal(result); 6365 } 6366 6367 6368 Local<Integer> v8::Integer::New(int32_t value) { 6369 i::Isolate* isolate = i::Isolate::UncheckedCurrent(); 6370 EnsureInitializedForIsolate(isolate, "v8::Integer::New()"); 6371 return v8::Integer::New(reinterpret_cast<Isolate*>(isolate), value); 6372 } 6373 6374 6375 Local<Integer> Integer::NewFromUnsigned(uint32_t value) { 6376 i::Isolate* isolate = i::Isolate::Current(); 6377 EnsureInitializedForIsolate(isolate, "v8::Integer::NewFromUnsigned()"); 6378 return Integer::NewFromUnsigned(reinterpret_cast<Isolate*>(isolate), value); 6379 } 6380 6381 6382 Local<Integer> v8::Integer::New(int32_t value, Isolate* isolate) { 6383 return Integer::New(isolate, value); 6384 } 6385 6386 6387 Local<Integer> v8::Integer::NewFromUnsigned(uint32_t value, Isolate* isolate) { 6388 return Integer::NewFromUnsigned(isolate, value); 6389 } 6390 6391 6392 Local<Integer> v8::Integer::New(Isolate* isolate, int32_t value) { 6393 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 6394 ASSERT(internal_isolate->IsInitialized()); 6395 if (i::Smi::IsValid(value)) { 6396 return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value), 6397 internal_isolate)); 6398 } 6399 ENTER_V8(internal_isolate); 6400 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value); 6401 return Utils::IntegerToLocal(result); 6402 } 6403 6404 6405 Local<Integer> v8::Integer::NewFromUnsigned(Isolate* isolate, uint32_t value) { 6406 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 6407 ASSERT(internal_isolate->IsInitialized()); 6408 bool fits_into_int32_t = (value & (1 << 31)) == 0; 6409 if (fits_into_int32_t) { 6410 return Integer::New(static_cast<int32_t>(value), isolate); 6411 } 6412 ENTER_V8(internal_isolate); 6413 i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value); 6414 return Utils::IntegerToLocal(result); 6415 } 6416 6417 6418 #ifdef DEBUG 6419 v8::AssertNoGCScope::AssertNoGCScope(v8::Isolate* isolate) { 6420 disallow_heap_allocation_ = new i::DisallowHeapAllocation(); 6421 } 6422 6423 6424 v8::AssertNoGCScope::~AssertNoGCScope() { 6425 delete static_cast<i::DisallowHeapAllocation*>(disallow_heap_allocation_); 6426 } 6427 #endif 6428 6429 6430 void V8::IgnoreOutOfMemoryException() { 6431 EnterIsolateIfNeeded()->set_ignore_out_of_memory(true); 6432 } 6433 6434 6435 bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) { 6436 i::Isolate* isolate = i::Isolate::Current(); 6437 EnsureInitializedForIsolate(isolate, "v8::V8::AddMessageListener()"); 6438 ON_BAILOUT(isolate, "v8::V8::AddMessageListener()", return false); 6439 ENTER_V8(isolate); 6440 i::HandleScope scope(isolate); 6441 NeanderArray listeners(isolate->factory()->message_listeners()); 6442 NeanderObject obj(2); 6443 obj.set(0, *isolate->factory()->NewForeign(FUNCTION_ADDR(that))); 6444 obj.set(1, data.IsEmpty() ? isolate->heap()->undefined_value() 6445 : *Utils::OpenHandle(*data)); 6446 listeners.add(obj.value()); 6447 return true; 6448 } 6449 6450 6451 void V8::RemoveMessageListeners(MessageCallback that) { 6452 i::Isolate* isolate = i::Isolate::Current(); 6453 EnsureInitializedForIsolate(isolate, "v8::V8::RemoveMessageListener()"); 6454 ON_BAILOUT(isolate, "v8::V8::RemoveMessageListeners()", return); 6455 ENTER_V8(isolate); 6456 i::HandleScope scope(isolate); 6457 NeanderArray listeners(isolate->factory()->message_listeners()); 6458 for (int i = 0; i < listeners.length(); i++) { 6459 if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones 6460 6461 NeanderObject listener(i::JSObject::cast(listeners.get(i))); 6462 i::Handle<i::Foreign> callback_obj(i::Foreign::cast(listener.get(0))); 6463 if (callback_obj->foreign_address() == FUNCTION_ADDR(that)) { 6464 listeners.set(i, isolate->heap()->undefined_value()); 6465 } 6466 } 6467 } 6468 6469 6470 void V8::SetCaptureStackTraceForUncaughtExceptions( 6471 bool capture, 6472 int frame_limit, 6473 StackTrace::StackTraceOptions options) { 6474 i::Isolate::Current()->SetCaptureStackTraceForUncaughtExceptions( 6475 capture, 6476 frame_limit, 6477 options); 6478 } 6479 6480 6481 void V8::SetCounterFunction(CounterLookupCallback callback) { 6482 i::Isolate* isolate = EnterIsolateIfNeeded(); 6483 isolate->stats_table()->SetCounterFunction(callback); 6484 } 6485 6486 6487 void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) { 6488 i::Isolate* isolate = EnterIsolateIfNeeded(); 6489 isolate->stats_table()->SetCreateHistogramFunction(callback); 6490 isolate->InitializeLoggingAndCounters(); 6491 isolate->counters()->ResetHistograms(); 6492 } 6493 6494 6495 void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) { 6496 i::Isolate* isolate = EnterIsolateIfNeeded(); 6497 isolate->stats_table()-> 6498 SetAddHistogramSampleFunction(callback); 6499 } 6500 6501 void V8::SetFailedAccessCheckCallbackFunction( 6502 FailedAccessCheckCallback callback) { 6503 i::Isolate* isolate = i::Isolate::Current(); 6504 isolate->SetFailedAccessCheckCallback(callback); 6505 } 6506 6507 6508 int64_t Isolate::AdjustAmountOfExternalAllocatedMemory( 6509 int64_t change_in_bytes) { 6510 i::Heap* heap = reinterpret_cast<i::Isolate*>(this)->heap(); 6511 return heap->AdjustAmountOfExternalAllocatedMemory(change_in_bytes); 6512 } 6513 6514 6515 int64_t V8::AdjustAmountOfExternalAllocatedMemory(int64_t change_in_bytes) { 6516 i::Isolate* isolate = i::Isolate::UncheckedCurrent(); 6517 if (isolate == NULL || !isolate->IsInitialized()) { 6518 return 0; 6519 } 6520 Isolate* isolate_ext = reinterpret_cast<Isolate*>(isolate); 6521 return isolate_ext->AdjustAmountOfExternalAllocatedMemory(change_in_bytes); 6522 } 6523 6524 6525 HeapProfiler* Isolate::GetHeapProfiler() { 6526 i::HeapProfiler* heap_profiler = 6527 reinterpret_cast<i::Isolate*>(this)->heap_profiler(); 6528 return reinterpret_cast<HeapProfiler*>(heap_profiler); 6529 } 6530 6531 6532 CpuProfiler* Isolate::GetCpuProfiler() { 6533 i::CpuProfiler* cpu_profiler = 6534 reinterpret_cast<i::Isolate*>(this)->cpu_profiler(); 6535 return reinterpret_cast<CpuProfiler*>(cpu_profiler); 6536 } 6537 6538 6539 bool Isolate::InContext() { 6540 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 6541 return isolate->context() != NULL; 6542 } 6543 6544 6545 v8::Local<v8::Context> Isolate::GetCurrentContext() { 6546 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 6547 i::Context* context = isolate->context(); 6548 if (context == NULL) return Local<Context>(); 6549 i::Context* native_context = context->global_object()->native_context(); 6550 if (native_context == NULL) return Local<Context>(); 6551 return Utils::ToLocal(i::Handle<i::Context>(native_context)); 6552 } 6553 6554 6555 v8::Local<v8::Context> Isolate::GetCallingContext() { 6556 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 6557 i::Handle<i::Object> calling = isolate->GetCallingNativeContext(); 6558 if (calling.is_null()) return Local<Context>(); 6559 return Utils::ToLocal(i::Handle<i::Context>::cast(calling)); 6560 } 6561 6562 6563 v8::Local<v8::Context> Isolate::GetEnteredContext() { 6564 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 6565 i::Handle<i::Object> last = 6566 isolate->handle_scope_implementer()->LastEnteredContext(); 6567 if (last.is_null()) return Local<Context>(); 6568 return Utils::ToLocal(i::Handle<i::Context>::cast(last)); 6569 } 6570 6571 6572 v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) { 6573 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 6574 ENTER_V8(isolate); 6575 // If we're passed an empty handle, we throw an undefined exception 6576 // to deal more gracefully with out of memory situations. 6577 if (value.IsEmpty()) { 6578 isolate->ScheduleThrow(isolate->heap()->undefined_value()); 6579 } else { 6580 isolate->ScheduleThrow(*Utils::OpenHandle(*value)); 6581 } 6582 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 6583 } 6584 6585 6586 void Isolate::SetObjectGroupId(internal::Object** object, UniqueId id) { 6587 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this); 6588 internal_isolate->global_handles()->SetObjectGroupId( 6589 v8::internal::Handle<v8::internal::Object>(object).location(), 6590 id); 6591 } 6592 6593 6594 void Isolate::SetReferenceFromGroup(UniqueId id, internal::Object** object) { 6595 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this); 6596 internal_isolate->global_handles()->SetReferenceFromGroup( 6597 id, 6598 v8::internal::Handle<v8::internal::Object>(object).location()); 6599 } 6600 6601 6602 void Isolate::SetReference(internal::Object** parent, 6603 internal::Object** child) { 6604 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this); 6605 i::Object** parent_location = 6606 v8::internal::Handle<v8::internal::Object>(parent).location(); 6607 internal_isolate->global_handles()->SetReference( 6608 reinterpret_cast<i::HeapObject**>(parent_location), 6609 v8::internal::Handle<v8::internal::Object>(child).location()); 6610 } 6611 6612 6613 void Isolate::AddGCPrologueCallback(GCPrologueCallback callback, 6614 GCType gc_type) { 6615 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 6616 isolate->heap()->AddGCPrologueCallback(callback, gc_type); 6617 } 6618 6619 6620 void Isolate::RemoveGCPrologueCallback(GCPrologueCallback callback) { 6621 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 6622 isolate->heap()->RemoveGCPrologueCallback(callback); 6623 } 6624 6625 6626 void Isolate::AddGCEpilogueCallback(GCEpilogueCallback callback, 6627 GCType gc_type) { 6628 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 6629 isolate->heap()->AddGCEpilogueCallback(callback, gc_type); 6630 } 6631 6632 6633 void Isolate::RemoveGCEpilogueCallback(GCEpilogueCallback callback) { 6634 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 6635 isolate->heap()->RemoveGCEpilogueCallback(callback); 6636 } 6637 6638 6639 void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) { 6640 i::Isolate* isolate = i::Isolate::Current(); 6641 isolate->heap()->AddGCPrologueCallback( 6642 reinterpret_cast<v8::Isolate::GCPrologueCallback>(callback), 6643 gc_type, 6644 false); 6645 } 6646 6647 6648 void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) { 6649 i::Isolate* isolate = i::Isolate::Current(); 6650 isolate->heap()->RemoveGCPrologueCallback( 6651 reinterpret_cast<v8::Isolate::GCPrologueCallback>(callback)); 6652 } 6653 6654 6655 void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) { 6656 i::Isolate* isolate = i::Isolate::Current(); 6657 isolate->heap()->AddGCEpilogueCallback( 6658 reinterpret_cast<v8::Isolate::GCEpilogueCallback>(callback), 6659 gc_type, 6660 false); 6661 } 6662 6663 6664 void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) { 6665 i::Isolate* isolate = i::Isolate::Current(); 6666 isolate->heap()->RemoveGCEpilogueCallback( 6667 reinterpret_cast<v8::Isolate::GCEpilogueCallback>(callback)); 6668 } 6669 6670 6671 void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback, 6672 ObjectSpace space, 6673 AllocationAction action) { 6674 i::Isolate* isolate = i::Isolate::Current(); 6675 isolate->memory_allocator()->AddMemoryAllocationCallback( 6676 callback, space, action); 6677 } 6678 6679 6680 void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) { 6681 i::Isolate* isolate = i::Isolate::Current(); 6682 isolate->memory_allocator()->RemoveMemoryAllocationCallback( 6683 callback); 6684 } 6685 6686 6687 void V8::AddCallCompletedCallback(CallCompletedCallback callback) { 6688 if (callback == NULL) return; 6689 i::V8::AddCallCompletedCallback(callback); 6690 } 6691 6692 6693 void V8::RemoveCallCompletedCallback(CallCompletedCallback callback) { 6694 i::V8::RemoveCallCompletedCallback(callback); 6695 } 6696 6697 6698 void V8::TerminateExecution(Isolate* isolate) { 6699 // If no isolate is supplied, use the default isolate. 6700 if (isolate != NULL) { 6701 reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->TerminateExecution(); 6702 } else { 6703 i::Isolate::GetDefaultIsolateStackGuard()->TerminateExecution(); 6704 } 6705 } 6706 6707 6708 bool V8::IsExecutionTerminating(Isolate* isolate) { 6709 i::Isolate* i_isolate = isolate != NULL ? 6710 reinterpret_cast<i::Isolate*>(isolate) : i::Isolate::Current(); 6711 return IsExecutionTerminatingCheck(i_isolate); 6712 } 6713 6714 6715 void V8::CancelTerminateExecution(Isolate* isolate) { 6716 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); 6717 i_isolate->stack_guard()->CancelTerminateExecution(); 6718 } 6719 6720 6721 Isolate* Isolate::GetCurrent() { 6722 i::Isolate* isolate = i::Isolate::UncheckedCurrent(); 6723 return reinterpret_cast<Isolate*>(isolate); 6724 } 6725 6726 6727 Isolate* Isolate::New() { 6728 i::Isolate* isolate = new i::Isolate(); 6729 return reinterpret_cast<Isolate*>(isolate); 6730 } 6731 6732 6733 void Isolate::Dispose() { 6734 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 6735 if (!ApiCheck(!isolate->IsInUse(), 6736 "v8::Isolate::Dispose()", 6737 "Disposing the isolate that is entered by a thread.")) { 6738 return; 6739 } 6740 isolate->TearDown(); 6741 } 6742 6743 6744 void Isolate::Enter() { 6745 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 6746 isolate->Enter(); 6747 } 6748 6749 6750 void Isolate::Exit() { 6751 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 6752 isolate->Exit(); 6753 } 6754 6755 6756 void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) { 6757 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); 6758 if (!isolate->IsInitialized()) { 6759 heap_statistics->total_heap_size_ = 0; 6760 heap_statistics->total_heap_size_executable_ = 0; 6761 heap_statistics->total_physical_size_ = 0; 6762 heap_statistics->used_heap_size_ = 0; 6763 heap_statistics->heap_size_limit_ = 0; 6764 return; 6765 } 6766 i::Heap* heap = isolate->heap(); 6767 heap_statistics->total_heap_size_ = heap->CommittedMemory(); 6768 heap_statistics->total_heap_size_executable_ = 6769 heap->CommittedMemoryExecutable(); 6770 heap_statistics->total_physical_size_ = heap->CommittedPhysicalMemory(); 6771 heap_statistics->used_heap_size_ = heap->SizeOfObjects(); 6772 heap_statistics->heap_size_limit_ = heap->MaxReserved(); 6773 } 6774 6775 6776 String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) 6777 : str_(NULL), length_(0) { 6778 i::Isolate* isolate = i::Isolate::Current(); 6779 if (obj.IsEmpty()) return; 6780 ENTER_V8(isolate); 6781 i::HandleScope scope(isolate); 6782 TryCatch try_catch; 6783 Handle<String> str = obj->ToString(); 6784 if (str.IsEmpty()) return; 6785 i::Handle<i::String> i_str = Utils::OpenHandle(*str); 6786 length_ = v8::Utf8Length(*i_str, isolate); 6787 str_ = i::NewArray<char>(length_ + 1); 6788 str->WriteUtf8(str_); 6789 } 6790 6791 6792 String::Utf8Value::~Utf8Value() { 6793 i::DeleteArray(str_); 6794 } 6795 6796 6797 String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj) 6798 : str_(NULL), length_(0) { 6799 i::Isolate* isolate = i::Isolate::Current(); 6800 if (obj.IsEmpty()) return; 6801 ENTER_V8(isolate); 6802 i::HandleScope scope(isolate); 6803 TryCatch try_catch; 6804 Handle<String> str = obj->ToString(); 6805 if (str.IsEmpty()) return; 6806 length_ = str->Utf8Length(); 6807 str_ = i::NewArray<char>(length_ + 1); 6808 str->WriteUtf8(str_); 6809 ASSERT(i::String::NonAsciiStart(str_, length_) >= length_); 6810 } 6811 6812 6813 String::AsciiValue::~AsciiValue() { 6814 i::DeleteArray(str_); 6815 } 6816 6817 6818 String::Value::Value(v8::Handle<v8::Value> obj) 6819 : str_(NULL), length_(0) { 6820 i::Isolate* isolate = i::Isolate::Current(); 6821 if (obj.IsEmpty()) return; 6822 ENTER_V8(isolate); 6823 i::HandleScope scope(isolate); 6824 TryCatch try_catch; 6825 Handle<String> str = obj->ToString(); 6826 if (str.IsEmpty()) return; 6827 length_ = str->Length(); 6828 str_ = i::NewArray<uint16_t>(length_ + 1); 6829 str->Write(str_); 6830 } 6831 6832 6833 String::Value::~Value() { 6834 i::DeleteArray(str_); 6835 } 6836 6837 6838 Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) { 6839 i::Isolate* isolate = i::Isolate::Current(); 6840 LOG_API(isolate, "RangeError"); 6841 ON_BAILOUT(isolate, "v8::Exception::RangeError()", return Local<Value>()); 6842 ENTER_V8(isolate); 6843 i::Object* error; 6844 { 6845 i::HandleScope scope(isolate); 6846 i::Handle<i::String> message = Utils::OpenHandle(*raw_message); 6847 i::Handle<i::Object> result = isolate->factory()->NewRangeError(message); 6848 error = *result; 6849 } 6850 i::Handle<i::Object> result(error, isolate); 6851 return Utils::ToLocal(result); 6852 } 6853 6854 6855 Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) { 6856 i::Isolate* isolate = i::Isolate::Current(); 6857 LOG_API(isolate, "ReferenceError"); 6858 ON_BAILOUT(isolate, "v8::Exception::ReferenceError()", return Local<Value>()); 6859 ENTER_V8(isolate); 6860 i::Object* error; 6861 { 6862 i::HandleScope scope(isolate); 6863 i::Handle<i::String> message = Utils::OpenHandle(*raw_message); 6864 i::Handle<i::Object> result = 6865 isolate->factory()->NewReferenceError(message); 6866 error = *result; 6867 } 6868 i::Handle<i::Object> result(error, isolate); 6869 return Utils::ToLocal(result); 6870 } 6871 6872 6873 Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) { 6874 i::Isolate* isolate = i::Isolate::Current(); 6875 LOG_API(isolate, "SyntaxError"); 6876 ON_BAILOUT(isolate, "v8::Exception::SyntaxError()", return Local<Value>()); 6877 ENTER_V8(isolate); 6878 i::Object* error; 6879 { 6880 i::HandleScope scope(isolate); 6881 i::Handle<i::String> message = Utils::OpenHandle(*raw_message); 6882 i::Handle<i::Object> result = isolate->factory()->NewSyntaxError(message); 6883 error = *result; 6884 } 6885 i::Handle<i::Object> result(error, isolate); 6886 return Utils::ToLocal(result); 6887 } 6888 6889 6890 Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) { 6891 i::Isolate* isolate = i::Isolate::Current(); 6892 LOG_API(isolate, "TypeError"); 6893 ON_BAILOUT(isolate, "v8::Exception::TypeError()", return Local<Value>()); 6894 ENTER_V8(isolate); 6895 i::Object* error; 6896 { 6897 i::HandleScope scope(isolate); 6898 i::Handle<i::String> message = Utils::OpenHandle(*raw_message); 6899 i::Handle<i::Object> result = isolate->factory()->NewTypeError(message); 6900 error = *result; 6901 } 6902 i::Handle<i::Object> result(error, isolate); 6903 return Utils::ToLocal(result); 6904 } 6905 6906 6907 Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) { 6908 i::Isolate* isolate = i::Isolate::Current(); 6909 LOG_API(isolate, "Error"); 6910 ON_BAILOUT(isolate, "v8::Exception::Error()", return Local<Value>()); 6911 ENTER_V8(isolate); 6912 i::Object* error; 6913 { 6914 i::HandleScope scope(isolate); 6915 i::Handle<i::String> message = Utils::OpenHandle(*raw_message); 6916 i::Handle<i::Object> result = isolate->factory()->NewError(message); 6917 error = *result; 6918 } 6919 i::Handle<i::Object> result(error, isolate); 6920 return Utils::ToLocal(result); 6921 } 6922 6923 6924 // --- D e b u g S u p p o r t --- 6925 6926 #ifdef ENABLE_DEBUGGER_SUPPORT 6927 6928 bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) { 6929 i::Isolate* isolate = i::Isolate::Current(); 6930 EnsureInitializedForIsolate(isolate, "v8::Debug::SetDebugEventListener2()"); 6931 ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener2()", return false); 6932 ENTER_V8(isolate); 6933 i::HandleScope scope(isolate); 6934 i::Handle<i::Object> foreign = isolate->factory()->undefined_value(); 6935 if (that != NULL) { 6936 foreign = isolate->factory()->NewForeign(FUNCTION_ADDR(that)); 6937 } 6938 isolate->debugger()->SetEventListener(foreign, 6939 Utils::OpenHandle(*data, true)); 6940 return true; 6941 } 6942 6943 6944 bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that, 6945 Handle<Value> data) { 6946 i::Isolate* isolate = i::Isolate::Current(); 6947 ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false); 6948 ENTER_V8(isolate); 6949 isolate->debugger()->SetEventListener(Utils::OpenHandle(*that), 6950 Utils::OpenHandle(*data, true)); 6951 return true; 6952 } 6953 6954 6955 void Debug::DebugBreak(Isolate* isolate) { 6956 // If no isolate is supplied, use the default isolate. 6957 if (isolate != NULL) { 6958 reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->DebugBreak(); 6959 } else { 6960 i::Isolate::GetDefaultIsolateStackGuard()->DebugBreak(); 6961 } 6962 } 6963 6964 6965 void Debug::CancelDebugBreak(Isolate* isolate) { 6966 // If no isolate is supplied, use the default isolate. 6967 if (isolate != NULL) { 6968 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 6969 internal_isolate->stack_guard()->Continue(i::DEBUGBREAK); 6970 } else { 6971 i::Isolate::GetDefaultIsolateStackGuard()->Continue(i::DEBUGBREAK); 6972 } 6973 } 6974 6975 6976 void Debug::DebugBreakForCommand(ClientData* data, Isolate* isolate) { 6977 // If no isolate is supplied, use the default isolate. 6978 if (isolate != NULL) { 6979 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 6980 internal_isolate->debugger()->EnqueueDebugCommand(data); 6981 } else { 6982 i::Isolate::GetDefaultIsolateDebugger()->EnqueueDebugCommand(data); 6983 } 6984 } 6985 6986 6987 void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) { 6988 i::Isolate* isolate = i::Isolate::Current(); 6989 EnsureInitializedForIsolate(isolate, "v8::Debug::SetMessageHandler"); 6990 ENTER_V8(isolate); 6991 isolate->debugger()->SetMessageHandler(handler); 6992 } 6993 6994 6995 void Debug::SendCommand(Isolate* isolate, 6996 const uint16_t* command, 6997 int length, 6998 ClientData* client_data) { 6999 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 7000 internal_isolate->debugger()->ProcessCommand( 7001 i::Vector<const uint16_t>(command, length), client_data); 7002 } 7003 7004 7005 void Debug::SendCommand(const uint16_t* command, int length, 7006 ClientData* client_data, 7007 Isolate* isolate) { 7008 // If no isolate is supplied, use the default isolate. 7009 if (isolate != NULL) { 7010 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 7011 internal_isolate->debugger()->ProcessCommand( 7012 i::Vector<const uint16_t>(command, length), client_data); 7013 } else { 7014 i::Isolate::GetDefaultIsolateDebugger()->ProcessCommand( 7015 i::Vector<const uint16_t>(command, length), client_data); 7016 } 7017 } 7018 7019 7020 void Debug::SetHostDispatchHandler(HostDispatchHandler handler, 7021 int period) { 7022 i::Isolate* isolate = i::Isolate::Current(); 7023 EnsureInitializedForIsolate(isolate, "v8::Debug::SetHostDispatchHandler"); 7024 ENTER_V8(isolate); 7025 isolate->debugger()->SetHostDispatchHandler( 7026 handler, i::TimeDelta::FromMilliseconds(period)); 7027 } 7028 7029 7030 void Debug::SetDebugMessageDispatchHandler( 7031 DebugMessageDispatchHandler handler, bool provide_locker) { 7032 i::Isolate* isolate = i::Isolate::Current(); 7033 EnsureInitializedForIsolate(isolate, 7034 "v8::Debug::SetDebugMessageDispatchHandler"); 7035 ENTER_V8(isolate); 7036 isolate->debugger()->SetDebugMessageDispatchHandler( 7037 handler, provide_locker); 7038 } 7039 7040 7041 Local<Value> Debug::Call(v8::Handle<v8::Function> fun, 7042 v8::Handle<v8::Value> data) { 7043 i::Isolate* isolate = i::Isolate::Current(); 7044 if (!isolate->IsInitialized()) return Local<Value>(); 7045 ON_BAILOUT(isolate, "v8::Debug::Call()", return Local<Value>()); 7046 ENTER_V8(isolate); 7047 i::Handle<i::Object> result; 7048 EXCEPTION_PREAMBLE(isolate); 7049 if (data.IsEmpty()) { 7050 result = isolate->debugger()->Call(Utils::OpenHandle(*fun), 7051 isolate->factory()->undefined_value(), 7052 &has_pending_exception); 7053 } else { 7054 result = isolate->debugger()->Call(Utils::OpenHandle(*fun), 7055 Utils::OpenHandle(*data), 7056 &has_pending_exception); 7057 } 7058 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 7059 return Utils::ToLocal(result); 7060 } 7061 7062 7063 Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) { 7064 i::Isolate* isolate = i::Isolate::Current(); 7065 if (!isolate->IsInitialized()) return Local<Value>(); 7066 ON_BAILOUT(isolate, "v8::Debug::GetMirror()", return Local<Value>()); 7067 ENTER_V8(isolate); 7068 v8::EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate)); 7069 i::Debug* isolate_debug = isolate->debug(); 7070 isolate_debug->Load(); 7071 i::Handle<i::JSObject> debug(isolate_debug->debug_context()->global_object()); 7072 i::Handle<i::String> name = isolate->factory()->InternalizeOneByteString( 7073 STATIC_ASCII_VECTOR("MakeMirror")); 7074 i::Handle<i::Object> fun_obj = i::GetProperty(isolate, debug, name); 7075 i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj); 7076 v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun); 7077 const int kArgc = 1; 7078 v8::Handle<v8::Value> argv[kArgc] = { obj }; 7079 EXCEPTION_PREAMBLE(isolate); 7080 v8::Local<v8::Value> result = 7081 v8_fun->Call(Utils::ToLocal(debug), kArgc, argv); 7082 EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); 7083 return scope.Escape(result); 7084 } 7085 7086 7087 bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) { 7088 return i::Isolate::Current()->debugger()->StartAgent(name, port, 7089 wait_for_connection); 7090 } 7091 7092 7093 void Debug::DisableAgent() { 7094 return i::Isolate::Current()->debugger()->StopAgent(); 7095 } 7096 7097 7098 void Debug::ProcessDebugMessages() { 7099 i::Execution::ProcessDebugMessages(i::Isolate::Current(), true); 7100 } 7101 7102 7103 Local<Context> Debug::GetDebugContext() { 7104 i::Isolate* isolate = i::Isolate::Current(); 7105 EnsureInitializedForIsolate(isolate, "v8::Debug::GetDebugContext()"); 7106 ENTER_V8(isolate); 7107 return Utils::ToLocal(i::Isolate::Current()->debugger()->GetDebugContext()); 7108 } 7109 7110 7111 void Debug::SetLiveEditEnabled(bool enable, Isolate* isolate) { 7112 // If no isolate is supplied, use the default isolate. 7113 i::Debugger* debugger; 7114 if (isolate != NULL) { 7115 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 7116 debugger = internal_isolate->debugger(); 7117 } else { 7118 debugger = i::Isolate::GetDefaultIsolateDebugger(); 7119 } 7120 debugger->set_live_edit_enabled(enable); 7121 } 7122 7123 7124 #endif // ENABLE_DEBUGGER_SUPPORT 7125 7126 7127 Handle<String> CpuProfileNode::GetFunctionName() const { 7128 i::Isolate* isolate = i::Isolate::Current(); 7129 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this); 7130 const i::CodeEntry* entry = node->entry(); 7131 if (!entry->has_name_prefix()) { 7132 return ToApiHandle<String>( 7133 isolate->factory()->InternalizeUtf8String(entry->name())); 7134 } else { 7135 return ToApiHandle<String>(isolate->factory()->NewConsString( 7136 isolate->factory()->InternalizeUtf8String(entry->name_prefix()), 7137 isolate->factory()->InternalizeUtf8String(entry->name()))); 7138 } 7139 } 7140 7141 7142 int CpuProfileNode::GetScriptId() const { 7143 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this); 7144 const i::CodeEntry* entry = node->entry(); 7145 return entry->script_id(); 7146 } 7147 7148 7149 Handle<String> CpuProfileNode::GetScriptResourceName() const { 7150 i::Isolate* isolate = i::Isolate::Current(); 7151 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this); 7152 return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String( 7153 node->entry()->resource_name())); 7154 } 7155 7156 7157 int CpuProfileNode::GetLineNumber() const { 7158 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number(); 7159 } 7160 7161 7162 int CpuProfileNode::GetColumnNumber() const { 7163 return reinterpret_cast<const i::ProfileNode*>(this)-> 7164 entry()->column_number(); 7165 } 7166 7167 7168 const char* CpuProfileNode::GetBailoutReason() const { 7169 const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this); 7170 return node->entry()->bailout_reason(); 7171 } 7172 7173 7174 unsigned CpuProfileNode::GetHitCount() const { 7175 return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks(); 7176 } 7177 7178 7179 unsigned CpuProfileNode::GetCallUid() const { 7180 return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid(); 7181 } 7182 7183 7184 unsigned CpuProfileNode::GetNodeId() const { 7185 return reinterpret_cast<const i::ProfileNode*>(this)->id(); 7186 } 7187 7188 7189 int CpuProfileNode::GetChildrenCount() const { 7190 return reinterpret_cast<const i::ProfileNode*>(this)->children()->length(); 7191 } 7192 7193 7194 const CpuProfileNode* CpuProfileNode::GetChild(int index) const { 7195 const i::ProfileNode* child = 7196 reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index); 7197 return reinterpret_cast<const CpuProfileNode*>(child); 7198 } 7199 7200 7201 void CpuProfile::Delete() { 7202 i::Isolate* isolate = i::Isolate::Current(); 7203 i::CpuProfiler* profiler = isolate->cpu_profiler(); 7204 ASSERT(profiler != NULL); 7205 profiler->DeleteProfile(reinterpret_cast<i::CpuProfile*>(this)); 7206 if (profiler->GetProfilesCount() == 0) { 7207 // If this was the last profile, clean up all accessory data as well. 7208 profiler->DeleteAllProfiles(); 7209 } 7210 } 7211 7212 7213 unsigned CpuProfile::GetUid() const { 7214 return reinterpret_cast<const i::CpuProfile*>(this)->uid(); 7215 } 7216 7217 7218 Handle<String> CpuProfile::GetTitle() const { 7219 i::Isolate* isolate = i::Isolate::Current(); 7220 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this); 7221 return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String( 7222 profile->title())); 7223 } 7224 7225 7226 const CpuProfileNode* CpuProfile::GetTopDownRoot() const { 7227 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this); 7228 return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root()); 7229 } 7230 7231 7232 const CpuProfileNode* CpuProfile::GetSample(int index) const { 7233 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this); 7234 return reinterpret_cast<const CpuProfileNode*>(profile->sample(index)); 7235 } 7236 7237 7238 int64_t CpuProfile::GetStartTime() const { 7239 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this); 7240 return (profile->start_time() - i::Time::UnixEpoch()).InMicroseconds(); 7241 } 7242 7243 7244 int64_t CpuProfile::GetEndTime() const { 7245 const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this); 7246 return (profile->end_time() - i::Time::UnixEpoch()).InMicroseconds(); 7247 } 7248 7249 7250 int CpuProfile::GetSamplesCount() const { 7251 return reinterpret_cast<const i::CpuProfile*>(this)->samples_count(); 7252 } 7253 7254 7255 int CpuProfiler::GetProfileCount() { 7256 return reinterpret_cast<i::CpuProfiler*>(this)->GetProfilesCount(); 7257 } 7258 7259 7260 void CpuProfiler::SetSamplingInterval(int us) { 7261 ASSERT(us >= 0); 7262 return reinterpret_cast<i::CpuProfiler*>(this)->set_sampling_interval( 7263 i::TimeDelta::FromMicroseconds(us)); 7264 } 7265 7266 7267 const CpuProfile* CpuProfiler::GetCpuProfile(int index) { 7268 return reinterpret_cast<const CpuProfile*>( 7269 reinterpret_cast<i::CpuProfiler*>(this)->GetProfile(index)); 7270 } 7271 7272 7273 void CpuProfiler::StartCpuProfiling(Handle<String> title, bool record_samples) { 7274 reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling( 7275 *Utils::OpenHandle(*title), record_samples); 7276 } 7277 7278 7279 const CpuProfile* CpuProfiler::StopCpuProfiling(Handle<String> title) { 7280 return reinterpret_cast<const CpuProfile*>( 7281 reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling( 7282 *Utils::OpenHandle(*title))); 7283 } 7284 7285 7286 void CpuProfiler::DeleteAllCpuProfiles() { 7287 reinterpret_cast<i::CpuProfiler*>(this)->DeleteAllProfiles(); 7288 } 7289 7290 7291 void CpuProfiler::SetIdle(bool is_idle) { 7292 i::Isolate* isolate = reinterpret_cast<i::CpuProfiler*>(this)->isolate(); 7293 i::StateTag state = isolate->current_vm_state(); 7294 ASSERT(state == i::EXTERNAL || state == i::IDLE); 7295 if (isolate->js_entry_sp() != NULL) return; 7296 if (is_idle) { 7297 isolate->set_current_vm_state(i::IDLE); 7298 } else if (state == i::IDLE) { 7299 isolate->set_current_vm_state(i::EXTERNAL); 7300 } 7301 } 7302 7303 7304 static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) { 7305 return const_cast<i::HeapGraphEdge*>( 7306 reinterpret_cast<const i::HeapGraphEdge*>(edge)); 7307 } 7308 7309 7310 HeapGraphEdge::Type HeapGraphEdge::GetType() const { 7311 return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type()); 7312 } 7313 7314 7315 Handle<Value> HeapGraphEdge::GetName() const { 7316 i::Isolate* isolate = i::Isolate::Current(); 7317 i::HeapGraphEdge* edge = ToInternal(this); 7318 switch (edge->type()) { 7319 case i::HeapGraphEdge::kContextVariable: 7320 case i::HeapGraphEdge::kInternal: 7321 case i::HeapGraphEdge::kProperty: 7322 case i::HeapGraphEdge::kShortcut: 7323 return ToApiHandle<String>( 7324 isolate->factory()->InternalizeUtf8String(edge->name())); 7325 case i::HeapGraphEdge::kElement: 7326 case i::HeapGraphEdge::kHidden: 7327 case i::HeapGraphEdge::kWeak: 7328 return ToApiHandle<Number>( 7329 isolate->factory()->NewNumberFromInt(edge->index())); 7330 default: UNREACHABLE(); 7331 } 7332 return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); 7333 } 7334 7335 7336 const HeapGraphNode* HeapGraphEdge::GetFromNode() const { 7337 const i::HeapEntry* from = ToInternal(this)->from(); 7338 return reinterpret_cast<const HeapGraphNode*>(from); 7339 } 7340 7341 7342 const HeapGraphNode* HeapGraphEdge::GetToNode() const { 7343 const i::HeapEntry* to = ToInternal(this)->to(); 7344 return reinterpret_cast<const HeapGraphNode*>(to); 7345 } 7346 7347 7348 static i::HeapEntry* ToInternal(const HeapGraphNode* entry) { 7349 return const_cast<i::HeapEntry*>( 7350 reinterpret_cast<const i::HeapEntry*>(entry)); 7351 } 7352 7353 7354 HeapGraphNode::Type HeapGraphNode::GetType() const { 7355 return static_cast<HeapGraphNode::Type>(ToInternal(this)->type()); 7356 } 7357 7358 7359 Handle<String> HeapGraphNode::GetName() const { 7360 i::Isolate* isolate = i::Isolate::Current(); 7361 return ToApiHandle<String>( 7362 isolate->factory()->InternalizeUtf8String(ToInternal(this)->name())); 7363 } 7364 7365 7366 SnapshotObjectId HeapGraphNode::GetId() const { 7367 return ToInternal(this)->id(); 7368 } 7369 7370 7371 int HeapGraphNode::GetSelfSize() const { 7372 return ToInternal(this)->self_size(); 7373 } 7374 7375 7376 int HeapGraphNode::GetChildrenCount() const { 7377 return ToInternal(this)->children().length(); 7378 } 7379 7380 7381 const HeapGraphEdge* HeapGraphNode::GetChild(int index) const { 7382 return reinterpret_cast<const HeapGraphEdge*>( 7383 ToInternal(this)->children()[index]); 7384 } 7385 7386 7387 v8::Handle<v8::Value> HeapGraphNode::GetHeapValue() const { 7388 i::Isolate* isolate = i::Isolate::Current(); 7389 i::Handle<i::HeapObject> object = ToInternal(this)->GetHeapObject(); 7390 return !object.is_null() ? 7391 ToApiHandle<Value>(object) : 7392 ToApiHandle<Value>(isolate->factory()->undefined_value()); 7393 } 7394 7395 7396 static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) { 7397 return const_cast<i::HeapSnapshot*>( 7398 reinterpret_cast<const i::HeapSnapshot*>(snapshot)); 7399 } 7400 7401 7402 void HeapSnapshot::Delete() { 7403 i::Isolate* isolate = i::Isolate::Current(); 7404 if (isolate->heap_profiler()->GetSnapshotsCount() > 1) { 7405 ToInternal(this)->Delete(); 7406 } else { 7407 // If this is the last snapshot, clean up all accessory data as well. 7408 isolate->heap_profiler()->DeleteAllSnapshots(); 7409 } 7410 } 7411 7412 7413 unsigned HeapSnapshot::GetUid() const { 7414 return ToInternal(this)->uid(); 7415 } 7416 7417 7418 Handle<String> HeapSnapshot::GetTitle() const { 7419 i::Isolate* isolate = i::Isolate::Current(); 7420 return ToApiHandle<String>( 7421 isolate->factory()->InternalizeUtf8String(ToInternal(this)->title())); 7422 } 7423 7424 7425 const HeapGraphNode* HeapSnapshot::GetRoot() const { 7426 return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root()); 7427 } 7428 7429 7430 const HeapGraphNode* HeapSnapshot::GetNodeById(SnapshotObjectId id) const { 7431 return reinterpret_cast<const HeapGraphNode*>( 7432 ToInternal(this)->GetEntryById(id)); 7433 } 7434 7435 7436 int HeapSnapshot::GetNodesCount() const { 7437 return ToInternal(this)->entries().length(); 7438 } 7439 7440 7441 const HeapGraphNode* HeapSnapshot::GetNode(int index) const { 7442 return reinterpret_cast<const HeapGraphNode*>( 7443 &ToInternal(this)->entries().at(index)); 7444 } 7445 7446 7447 SnapshotObjectId HeapSnapshot::GetMaxSnapshotJSObjectId() const { 7448 return ToInternal(this)->max_snapshot_js_object_id(); 7449 } 7450 7451 7452 void HeapSnapshot::Serialize(OutputStream* stream, 7453 HeapSnapshot::SerializationFormat format) const { 7454 ApiCheck(format == kJSON, 7455 "v8::HeapSnapshot::Serialize", 7456 "Unknown serialization format"); 7457 ApiCheck(stream->GetOutputEncoding() == OutputStream::kAscii, 7458 "v8::HeapSnapshot::Serialize", 7459 "Unsupported output encoding"); 7460 ApiCheck(stream->GetChunkSize() > 0, 7461 "v8::HeapSnapshot::Serialize", 7462 "Invalid stream chunk size"); 7463 i::HeapSnapshotJSONSerializer serializer(ToInternal(this)); 7464 serializer.Serialize(stream); 7465 } 7466 7467 7468 int HeapProfiler::GetSnapshotCount() { 7469 return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotsCount(); 7470 } 7471 7472 7473 const HeapSnapshot* HeapProfiler::GetHeapSnapshot(int index) { 7474 return reinterpret_cast<const HeapSnapshot*>( 7475 reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshot(index)); 7476 } 7477 7478 7479 SnapshotObjectId HeapProfiler::GetObjectId(Handle<Value> value) { 7480 i::Handle<i::Object> obj = Utils::OpenHandle(*value); 7481 return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotObjectId(obj); 7482 } 7483 7484 7485 const HeapSnapshot* HeapProfiler::TakeHeapSnapshot( 7486 Handle<String> title, 7487 ActivityControl* control, 7488 ObjectNameResolver* resolver) { 7489 return reinterpret_cast<const HeapSnapshot*>( 7490 reinterpret_cast<i::HeapProfiler*>(this)->TakeSnapshot( 7491 *Utils::OpenHandle(*title), control, resolver)); 7492 } 7493 7494 7495 void HeapProfiler::StartTrackingHeapObjects(bool track_allocations) { 7496 reinterpret_cast<i::HeapProfiler*>(this)->StartHeapObjectsTracking( 7497 track_allocations); 7498 } 7499 7500 7501 void HeapProfiler::StopTrackingHeapObjects() { 7502 reinterpret_cast<i::HeapProfiler*>(this)->StopHeapObjectsTracking(); 7503 } 7504 7505 7506 SnapshotObjectId HeapProfiler::GetHeapStats(OutputStream* stream) { 7507 return reinterpret_cast<i::HeapProfiler*>(this)->PushHeapObjectsStats(stream); 7508 } 7509 7510 7511 void HeapProfiler::DeleteAllHeapSnapshots() { 7512 reinterpret_cast<i::HeapProfiler*>(this)->DeleteAllSnapshots(); 7513 } 7514 7515 7516 void HeapProfiler::SetWrapperClassInfoProvider(uint16_t class_id, 7517 WrapperInfoCallback callback) { 7518 reinterpret_cast<i::HeapProfiler*>(this)->DefineWrapperClass(class_id, 7519 callback); 7520 } 7521 7522 7523 size_t HeapProfiler::GetProfilerMemorySize() { 7524 return reinterpret_cast<i::HeapProfiler*>(this)-> 7525 GetMemorySizeUsedByProfiler(); 7526 } 7527 7528 7529 void HeapProfiler::SetRetainedObjectInfo(UniqueId id, 7530 RetainedObjectInfo* info) { 7531 reinterpret_cast<i::HeapProfiler*>(this)->SetRetainedObjectInfo(id, info); 7532 } 7533 7534 7535 void HeapProfiler::StartRecordingHeapAllocations() { 7536 reinterpret_cast<i::HeapProfiler*>(this)->StartHeapObjectsTracking(true); 7537 } 7538 7539 7540 void HeapProfiler::StopRecordingHeapAllocations() { 7541 reinterpret_cast<i::HeapProfiler*>(this)->StopHeapObjectsTracking(); 7542 } 7543 7544 7545 v8::Testing::StressType internal::Testing::stress_type_ = 7546 v8::Testing::kStressTypeOpt; 7547 7548 7549 void Testing::SetStressRunType(Testing::StressType type) { 7550 internal::Testing::set_stress_type(type); 7551 } 7552 7553 7554 int Testing::GetStressRuns() { 7555 if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs; 7556 #ifdef DEBUG 7557 // In debug mode the code runs much slower so stressing will only make two 7558 // runs. 7559 return 2; 7560 #else 7561 return 5; 7562 #endif 7563 } 7564 7565 7566 static void SetFlagsFromString(const char* flags) { 7567 V8::SetFlagsFromString(flags, i::StrLength(flags)); 7568 } 7569 7570 7571 void Testing::PrepareStressRun(int run) { 7572 static const char* kLazyOptimizations = 7573 "--prepare-always-opt " 7574 "--max-inlined-source-size=999999 " 7575 "--max-inlined-nodes=999999 " 7576 "--max-inlined-nodes-cumulative=999999 " 7577 "--noalways-opt"; 7578 static const char* kForcedOptimizations = "--always-opt"; 7579 7580 // If deoptimization stressed turn on frequent deoptimization. If no value 7581 // is spefified through --deopt-every-n-times use a default default value. 7582 static const char* kDeoptEvery13Times = "--deopt-every-n-times=13"; 7583 if (internal::Testing::stress_type() == Testing::kStressTypeDeopt && 7584 internal::FLAG_deopt_every_n_times == 0) { 7585 SetFlagsFromString(kDeoptEvery13Times); 7586 } 7587 7588 #ifdef DEBUG 7589 // As stressing in debug mode only make two runs skip the deopt stressing 7590 // here. 7591 if (run == GetStressRuns() - 1) { 7592 SetFlagsFromString(kForcedOptimizations); 7593 } else { 7594 SetFlagsFromString(kLazyOptimizations); 7595 } 7596 #else 7597 if (run == GetStressRuns() - 1) { 7598 SetFlagsFromString(kForcedOptimizations); 7599 } else if (run != GetStressRuns() - 2) { 7600 SetFlagsFromString(kLazyOptimizations); 7601 } 7602 #endif 7603 } 7604 7605 7606 // TODO(svenpanne) Deprecate this. 7607 void Testing::DeoptimizeAll() { 7608 i::Isolate* isolate = i::Isolate::Current(); 7609 i::HandleScope scope(isolate); 7610 internal::Deoptimizer::DeoptimizeAll(isolate); 7611 } 7612 7613 7614 namespace internal { 7615 7616 7617 void HandleScopeImplementer::FreeThreadResources() { 7618 Free(); 7619 } 7620 7621 7622 char* HandleScopeImplementer::ArchiveThread(char* storage) { 7623 v8::ImplementationUtilities::HandleScopeData* current = 7624 isolate_->handle_scope_data(); 7625 handle_scope_data_ = *current; 7626 OS::MemCopy(storage, this, sizeof(*this)); 7627 7628 ResetAfterArchive(); 7629 current->Initialize(); 7630 7631 return storage + ArchiveSpacePerThread(); 7632 } 7633 7634 7635 int HandleScopeImplementer::ArchiveSpacePerThread() { 7636 return sizeof(HandleScopeImplementer); 7637 } 7638 7639 7640 char* HandleScopeImplementer::RestoreThread(char* storage) { 7641 OS::MemCopy(this, storage, sizeof(*this)); 7642 *isolate_->handle_scope_data() = handle_scope_data_; 7643 return storage + ArchiveSpacePerThread(); 7644 } 7645 7646 7647 void HandleScopeImplementer::IterateThis(ObjectVisitor* v) { 7648 #ifdef DEBUG 7649 bool found_block_before_deferred = false; 7650 #endif 7651 // Iterate over all handles in the blocks except for the last. 7652 for (int i = blocks()->length() - 2; i >= 0; --i) { 7653 Object** block = blocks()->at(i); 7654 if (last_handle_before_deferred_block_ != NULL && 7655 (last_handle_before_deferred_block_ <= &block[kHandleBlockSize]) && 7656 (last_handle_before_deferred_block_ >= block)) { 7657 v->VisitPointers(block, last_handle_before_deferred_block_); 7658 ASSERT(!found_block_before_deferred); 7659 #ifdef DEBUG 7660 found_block_before_deferred = true; 7661 #endif 7662 } else { 7663 v->VisitPointers(block, &block[kHandleBlockSize]); 7664 } 7665 } 7666 7667 ASSERT(last_handle_before_deferred_block_ == NULL || 7668 found_block_before_deferred); 7669 7670 // Iterate over live handles in the last block (if any). 7671 if (!blocks()->is_empty()) { 7672 v->VisitPointers(blocks()->last(), handle_scope_data_.next); 7673 } 7674 7675 List<Context*>* context_lists[2] = { &saved_contexts_, &entered_contexts_}; 7676 for (unsigned i = 0; i < ARRAY_SIZE(context_lists); i++) { 7677 if (context_lists[i]->is_empty()) continue; 7678 Object** start = reinterpret_cast<Object**>(&context_lists[i]->first()); 7679 v->VisitPointers(start, start + context_lists[i]->length()); 7680 } 7681 } 7682 7683 7684 void HandleScopeImplementer::Iterate(ObjectVisitor* v) { 7685 v8::ImplementationUtilities::HandleScopeData* current = 7686 isolate_->handle_scope_data(); 7687 handle_scope_data_ = *current; 7688 IterateThis(v); 7689 } 7690 7691 7692 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) { 7693 HandleScopeImplementer* scope_implementer = 7694 reinterpret_cast<HandleScopeImplementer*>(storage); 7695 scope_implementer->IterateThis(v); 7696 return storage + ArchiveSpacePerThread(); 7697 } 7698 7699 7700 DeferredHandles* HandleScopeImplementer::Detach(Object** prev_limit) { 7701 DeferredHandles* deferred = 7702 new DeferredHandles(isolate()->handle_scope_data()->next, isolate()); 7703 7704 while (!blocks_.is_empty()) { 7705 Object** block_start = blocks_.last(); 7706 Object** block_limit = &block_start[kHandleBlockSize]; 7707 // We should not need to check for SealHandleScope here. Assert this. 7708 ASSERT(prev_limit == block_limit || 7709 !(block_start <= prev_limit && prev_limit <= block_limit)); 7710 if (prev_limit == block_limit) break; 7711 deferred->blocks_.Add(blocks_.last()); 7712 blocks_.RemoveLast(); 7713 } 7714 7715 // deferred->blocks_ now contains the blocks installed on the 7716 // HandleScope stack since BeginDeferredScope was called, but in 7717 // reverse order. 7718 7719 ASSERT(prev_limit == NULL || !blocks_.is_empty()); 7720 7721 ASSERT(!blocks_.is_empty() && prev_limit != NULL); 7722 ASSERT(last_handle_before_deferred_block_ != NULL); 7723 last_handle_before_deferred_block_ = NULL; 7724 return deferred; 7725 } 7726 7727 7728 void HandleScopeImplementer::BeginDeferredScope() { 7729 ASSERT(last_handle_before_deferred_block_ == NULL); 7730 last_handle_before_deferred_block_ = isolate()->handle_scope_data()->next; 7731 } 7732 7733 7734 DeferredHandles::~DeferredHandles() { 7735 isolate_->UnlinkDeferredHandles(this); 7736 7737 for (int i = 0; i < blocks_.length(); i++) { 7738 #ifdef ENABLE_HANDLE_ZAPPING 7739 HandleScope::ZapRange(blocks_[i], &blocks_[i][kHandleBlockSize]); 7740 #endif 7741 isolate_->handle_scope_implementer()->ReturnBlock(blocks_[i]); 7742 } 7743 } 7744 7745 7746 void DeferredHandles::Iterate(ObjectVisitor* v) { 7747 ASSERT(!blocks_.is_empty()); 7748 7749 ASSERT((first_block_limit_ >= blocks_.first()) && 7750 (first_block_limit_ <= &(blocks_.first())[kHandleBlockSize])); 7751 7752 v->VisitPointers(blocks_.first(), first_block_limit_); 7753 7754 for (int i = 1; i < blocks_.length(); i++) { 7755 v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]); 7756 } 7757 } 7758 7759 7760 void InvokeAccessorGetterCallback( 7761 v8::Local<v8::String> property, 7762 const v8::PropertyCallbackInfo<v8::Value>& info, 7763 v8::AccessorGetterCallback getter) { 7764 // Leaving JavaScript. 7765 Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate()); 7766 Address getter_address = reinterpret_cast<Address>(reinterpret_cast<intptr_t>( 7767 getter)); 7768 VMState<EXTERNAL> state(isolate); 7769 ExternalCallbackScope call_scope(isolate, getter_address); 7770 getter(property, info); 7771 } 7772 7773 7774 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info, 7775 v8::FunctionCallback callback) { 7776 Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate()); 7777 Address callback_address = 7778 reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback)); 7779 VMState<EXTERNAL> state(isolate); 7780 ExternalCallbackScope call_scope(isolate, callback_address); 7781 callback(info); 7782 } 7783 7784 7785 } } // namespace v8::internal 7786