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