1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #include <stdlib.h> 29 30 #include "v8.h" 31 32 #include "api.h" 33 #include "bootstrapper.h" 34 #include "codegen.h" 35 #include "debug.h" 36 #include "deoptimizer.h" 37 #include "isolate-inl.h" 38 #include "runtime-profiler.h" 39 #include "simulator.h" 40 #include "v8threads.h" 41 #include "vm-state-inl.h" 42 43 namespace v8 { 44 namespace internal { 45 46 47 StackGuard::StackGuard() 48 : isolate_(NULL) { 49 } 50 51 52 void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) { 53 ASSERT(isolate_ != NULL); 54 // Ignore attempts to interrupt when interrupts are postponed. 55 if (should_postpone_interrupts(lock)) return; 56 thread_local_.jslimit_ = kInterruptLimit; 57 thread_local_.climit_ = kInterruptLimit; 58 isolate_->heap()->SetStackLimits(); 59 } 60 61 62 void StackGuard::reset_limits(const ExecutionAccess& lock) { 63 ASSERT(isolate_ != NULL); 64 thread_local_.jslimit_ = thread_local_.real_jslimit_; 65 thread_local_.climit_ = thread_local_.real_climit_; 66 isolate_->heap()->SetStackLimits(); 67 } 68 69 70 static Handle<Object> Invoke(bool is_construct, 71 Handle<JSFunction> function, 72 Handle<Object> receiver, 73 int argc, 74 Handle<Object> args[], 75 bool* has_pending_exception) { 76 Isolate* isolate = function->GetIsolate(); 77 78 // Entering JavaScript. 79 VMState<JS> state(isolate); 80 81 // Placeholder for return value. 82 MaybeObject* value = reinterpret_cast<Object*>(kZapValue); 83 84 typedef Object* (*JSEntryFunction)(byte* entry, 85 Object* function, 86 Object* receiver, 87 int argc, 88 Object*** args); 89 90 Handle<Code> code = is_construct 91 ? isolate->factory()->js_construct_entry_code() 92 : isolate->factory()->js_entry_code(); 93 94 // Convert calls on global objects to be calls on the global 95 // receiver instead to avoid having a 'this' pointer which refers 96 // directly to a global object. 97 if (receiver->IsGlobalObject()) { 98 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); 99 receiver = Handle<JSObject>(global->global_receiver()); 100 } 101 102 // Make sure that the global object of the context we're about to 103 // make the current one is indeed a global object. 104 ASSERT(function->context()->global_object()->IsGlobalObject()); 105 106 { 107 // Save and restore context around invocation and block the 108 // allocation of handles without explicit handle scopes. 109 SaveContext save(isolate); 110 SealHandleScope shs(isolate); 111 JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry()); 112 113 // Call the function through the right JS entry stub. 114 byte* function_entry = function->code()->entry(); 115 JSFunction* func = *function; 116 Object* recv = *receiver; 117 Object*** argv = reinterpret_cast<Object***>(args); 118 value = 119 CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv); 120 } 121 122 #ifdef VERIFY_HEAP 123 value->Verify(); 124 #endif 125 126 // Update the pending exception flag and return the value. 127 *has_pending_exception = value->IsException(); 128 ASSERT(*has_pending_exception == isolate->has_pending_exception()); 129 if (*has_pending_exception) { 130 isolate->ReportPendingMessages(); 131 if (isolate->pending_exception()->IsOutOfMemory()) { 132 if (!isolate->ignore_out_of_memory()) { 133 V8::FatalProcessOutOfMemory("JS", true); 134 } 135 } 136 #ifdef ENABLE_DEBUGGER_SUPPORT 137 // Reset stepping state when script exits with uncaught exception. 138 if (isolate->debugger()->IsDebuggerActive()) { 139 isolate->debug()->ClearStepping(); 140 } 141 #endif // ENABLE_DEBUGGER_SUPPORT 142 return Handle<Object>(); 143 } else { 144 isolate->clear_pending_message(); 145 } 146 147 return Handle<Object>(value->ToObjectUnchecked(), isolate); 148 } 149 150 151 Handle<Object> Execution::Call(Isolate* isolate, 152 Handle<Object> callable, 153 Handle<Object> receiver, 154 int argc, 155 Handle<Object> argv[], 156 bool* pending_exception, 157 bool convert_receiver) { 158 *pending_exception = false; 159 160 if (!callable->IsJSFunction()) { 161 callable = TryGetFunctionDelegate(isolate, callable, pending_exception); 162 if (*pending_exception) return callable; 163 } 164 Handle<JSFunction> func = Handle<JSFunction>::cast(callable); 165 166 // In non-strict mode, convert receiver. 167 if (convert_receiver && !receiver->IsJSReceiver() && 168 !func->shared()->native() && func->shared()->is_classic_mode()) { 169 if (receiver->IsUndefined() || receiver->IsNull()) { 170 Object* global = func->context()->global_object()->global_receiver(); 171 // Under some circumstances, 'global' can be the JSBuiltinsObject 172 // In that case, don't rewrite. (FWIW, the same holds for 173 // GetIsolate()->global_object()->global_receiver().) 174 if (!global->IsJSBuiltinsObject()) { 175 receiver = Handle<Object>(global, func->GetIsolate()); 176 } 177 } else { 178 receiver = ToObject(isolate, receiver, pending_exception); 179 } 180 if (*pending_exception) return callable; 181 } 182 183 return Invoke(false, func, receiver, argc, argv, pending_exception); 184 } 185 186 187 Handle<Object> Execution::New(Handle<JSFunction> func, 188 int argc, 189 Handle<Object> argv[], 190 bool* pending_exception) { 191 return Invoke(true, func, func->GetIsolate()->global_object(), argc, argv, 192 pending_exception); 193 } 194 195 196 Handle<Object> Execution::TryCall(Handle<JSFunction> func, 197 Handle<Object> receiver, 198 int argc, 199 Handle<Object> args[], 200 bool* caught_exception) { 201 // Enter a try-block while executing the JavaScript code. To avoid 202 // duplicate error printing it must be non-verbose. Also, to avoid 203 // creating message objects during stack overflow we shouldn't 204 // capture messages. 205 v8::TryCatch catcher; 206 catcher.SetVerbose(false); 207 catcher.SetCaptureMessage(false); 208 *caught_exception = false; 209 210 // Get isolate now, because handle might be persistent 211 // and get destroyed in the next call. 212 Isolate* isolate = func->GetIsolate(); 213 Handle<Object> result = Invoke(false, func, receiver, argc, args, 214 caught_exception); 215 216 if (*caught_exception) { 217 ASSERT(catcher.HasCaught()); 218 ASSERT(isolate->has_pending_exception()); 219 ASSERT(isolate->external_caught_exception()); 220 if (isolate->is_out_of_memory() && !isolate->ignore_out_of_memory()) { 221 V8::FatalProcessOutOfMemory("OOM during Execution::TryCall"); 222 } 223 if (isolate->pending_exception() == 224 isolate->heap()->termination_exception()) { 225 result = isolate->factory()->termination_exception(); 226 } else { 227 result = v8::Utils::OpenHandle(*catcher.Exception()); 228 } 229 isolate->OptionalRescheduleException(true); 230 } 231 232 ASSERT(!isolate->has_pending_exception()); 233 ASSERT(!isolate->external_caught_exception()); 234 return result; 235 } 236 237 238 Handle<Object> Execution::GetFunctionDelegate(Isolate* isolate, 239 Handle<Object> object) { 240 ASSERT(!object->IsJSFunction()); 241 Factory* factory = isolate->factory(); 242 243 // If you return a function from here, it will be called when an 244 // attempt is made to call the given object as a function. 245 246 // If object is a function proxy, get its handler. Iterate if necessary. 247 Object* fun = *object; 248 while (fun->IsJSFunctionProxy()) { 249 fun = JSFunctionProxy::cast(fun)->call_trap(); 250 } 251 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate); 252 253 // Objects created through the API can have an instance-call handler 254 // that should be used when calling the object as a function. 255 if (fun->IsHeapObject() && 256 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 257 return Handle<JSFunction>( 258 isolate->native_context()->call_as_function_delegate()); 259 } 260 261 return factory->undefined_value(); 262 } 263 264 265 Handle<Object> Execution::TryGetFunctionDelegate(Isolate* isolate, 266 Handle<Object> object, 267 bool* has_pending_exception) { 268 ASSERT(!object->IsJSFunction()); 269 270 // If object is a function proxy, get its handler. Iterate if necessary. 271 Object* fun = *object; 272 while (fun->IsJSFunctionProxy()) { 273 fun = JSFunctionProxy::cast(fun)->call_trap(); 274 } 275 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate); 276 277 // Objects created through the API can have an instance-call handler 278 // that should be used when calling the object as a function. 279 if (fun->IsHeapObject() && 280 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 281 return Handle<JSFunction>( 282 isolate->native_context()->call_as_function_delegate()); 283 } 284 285 // If the Object doesn't have an instance-call handler we should 286 // throw a non-callable exception. 287 i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( 288 "called_non_callable", i::HandleVector<i::Object>(&object, 1)); 289 isolate->Throw(*error_obj); 290 *has_pending_exception = true; 291 292 return isolate->factory()->undefined_value(); 293 } 294 295 296 Handle<Object> Execution::GetConstructorDelegate(Isolate* isolate, 297 Handle<Object> object) { 298 ASSERT(!object->IsJSFunction()); 299 300 // If you return a function from here, it will be called when an 301 // attempt is made to call the given object as a constructor. 302 303 // If object is a function proxies, get its handler. Iterate if necessary. 304 Object* fun = *object; 305 while (fun->IsJSFunctionProxy()) { 306 fun = JSFunctionProxy::cast(fun)->call_trap(); 307 } 308 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate); 309 310 // Objects created through the API can have an instance-call handler 311 // that should be used when calling the object as a function. 312 if (fun->IsHeapObject() && 313 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 314 return Handle<JSFunction>( 315 isolate->native_context()->call_as_constructor_delegate()); 316 } 317 318 return isolate->factory()->undefined_value(); 319 } 320 321 322 Handle<Object> Execution::TryGetConstructorDelegate( 323 Isolate* isolate, 324 Handle<Object> object, 325 bool* has_pending_exception) { 326 ASSERT(!object->IsJSFunction()); 327 328 // If you return a function from here, it will be called when an 329 // attempt is made to call the given object as a constructor. 330 331 // If object is a function proxies, get its handler. Iterate if necessary. 332 Object* fun = *object; 333 while (fun->IsJSFunctionProxy()) { 334 fun = JSFunctionProxy::cast(fun)->call_trap(); 335 } 336 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate); 337 338 // Objects created through the API can have an instance-call handler 339 // that should be used when calling the object as a function. 340 if (fun->IsHeapObject() && 341 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 342 return Handle<JSFunction>( 343 isolate->native_context()->call_as_constructor_delegate()); 344 } 345 346 // If the Object doesn't have an instance-call handler we should 347 // throw a non-callable exception. 348 i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( 349 "called_non_callable", i::HandleVector<i::Object>(&object, 1)); 350 isolate->Throw(*error_obj); 351 *has_pending_exception = true; 352 353 return isolate->factory()->undefined_value(); 354 } 355 356 357 void Execution::RunMicrotasks(Isolate* isolate) { 358 ASSERT(isolate->microtask_pending()); 359 bool threw = false; 360 Execution::Call( 361 isolate, 362 isolate->run_microtasks(), 363 isolate->factory()->undefined_value(), 364 0, 365 NULL, 366 &threw); 367 ASSERT(!threw); 368 } 369 370 371 bool StackGuard::IsStackOverflow() { 372 ExecutionAccess access(isolate_); 373 return (thread_local_.jslimit_ != kInterruptLimit && 374 thread_local_.climit_ != kInterruptLimit); 375 } 376 377 378 void StackGuard::EnableInterrupts() { 379 ExecutionAccess access(isolate_); 380 if (has_pending_interrupts(access)) { 381 set_interrupt_limits(access); 382 } 383 } 384 385 386 void StackGuard::SetStackLimit(uintptr_t limit) { 387 ExecutionAccess access(isolate_); 388 // If the current limits are special (e.g. due to a pending interrupt) then 389 // leave them alone. 390 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit); 391 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) { 392 thread_local_.jslimit_ = jslimit; 393 } 394 if (thread_local_.climit_ == thread_local_.real_climit_) { 395 thread_local_.climit_ = limit; 396 } 397 thread_local_.real_climit_ = limit; 398 thread_local_.real_jslimit_ = jslimit; 399 } 400 401 402 void StackGuard::DisableInterrupts() { 403 ExecutionAccess access(isolate_); 404 reset_limits(access); 405 } 406 407 408 bool StackGuard::ShouldPostponeInterrupts() { 409 ExecutionAccess access(isolate_); 410 return should_postpone_interrupts(access); 411 } 412 413 414 bool StackGuard::IsInterrupted() { 415 ExecutionAccess access(isolate_); 416 return (thread_local_.interrupt_flags_ & INTERRUPT) != 0; 417 } 418 419 420 void StackGuard::Interrupt() { 421 ExecutionAccess access(isolate_); 422 thread_local_.interrupt_flags_ |= INTERRUPT; 423 set_interrupt_limits(access); 424 } 425 426 427 bool StackGuard::IsPreempted() { 428 ExecutionAccess access(isolate_); 429 return thread_local_.interrupt_flags_ & PREEMPT; 430 } 431 432 433 void StackGuard::Preempt() { 434 ExecutionAccess access(isolate_); 435 thread_local_.interrupt_flags_ |= PREEMPT; 436 set_interrupt_limits(access); 437 } 438 439 440 bool StackGuard::IsTerminateExecution() { 441 ExecutionAccess access(isolate_); 442 return (thread_local_.interrupt_flags_ & TERMINATE) != 0; 443 } 444 445 446 void StackGuard::CancelTerminateExecution() { 447 ExecutionAccess access(isolate_); 448 Continue(TERMINATE); 449 isolate_->CancelTerminateExecution(); 450 } 451 452 453 void StackGuard::TerminateExecution() { 454 ExecutionAccess access(isolate_); 455 thread_local_.interrupt_flags_ |= TERMINATE; 456 set_interrupt_limits(access); 457 } 458 459 460 bool StackGuard::IsGCRequest() { 461 ExecutionAccess access(isolate_); 462 return (thread_local_.interrupt_flags_ & GC_REQUEST) != 0; 463 } 464 465 466 void StackGuard::RequestGC() { 467 ExecutionAccess access(isolate_); 468 thread_local_.interrupt_flags_ |= GC_REQUEST; 469 if (thread_local_.postpone_interrupts_nesting_ == 0) { 470 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit; 471 isolate_->heap()->SetStackLimits(); 472 } 473 } 474 475 476 bool StackGuard::IsInstallCodeRequest() { 477 ExecutionAccess access(isolate_); 478 return (thread_local_.interrupt_flags_ & INSTALL_CODE) != 0; 479 } 480 481 482 void StackGuard::RequestInstallCode() { 483 ExecutionAccess access(isolate_); 484 thread_local_.interrupt_flags_ |= INSTALL_CODE; 485 if (thread_local_.postpone_interrupts_nesting_ == 0) { 486 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit; 487 isolate_->heap()->SetStackLimits(); 488 } 489 } 490 491 492 bool StackGuard::IsFullDeopt() { 493 ExecutionAccess access(isolate_); 494 return (thread_local_.interrupt_flags_ & FULL_DEOPT) != 0; 495 } 496 497 498 void StackGuard::FullDeopt() { 499 ExecutionAccess access(isolate_); 500 thread_local_.interrupt_flags_ |= FULL_DEOPT; 501 set_interrupt_limits(access); 502 } 503 504 505 #ifdef ENABLE_DEBUGGER_SUPPORT 506 bool StackGuard::IsDebugBreak() { 507 ExecutionAccess access(isolate_); 508 return thread_local_.interrupt_flags_ & DEBUGBREAK; 509 } 510 511 512 void StackGuard::DebugBreak() { 513 ExecutionAccess access(isolate_); 514 thread_local_.interrupt_flags_ |= DEBUGBREAK; 515 set_interrupt_limits(access); 516 } 517 518 519 bool StackGuard::IsDebugCommand() { 520 ExecutionAccess access(isolate_); 521 return thread_local_.interrupt_flags_ & DEBUGCOMMAND; 522 } 523 524 525 void StackGuard::DebugCommand() { 526 if (FLAG_debugger_auto_break) { 527 ExecutionAccess access(isolate_); 528 thread_local_.interrupt_flags_ |= DEBUGCOMMAND; 529 set_interrupt_limits(access); 530 } 531 } 532 #endif 533 534 void StackGuard::Continue(InterruptFlag after_what) { 535 ExecutionAccess access(isolate_); 536 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what); 537 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) { 538 reset_limits(access); 539 } 540 } 541 542 543 char* StackGuard::ArchiveStackGuard(char* to) { 544 ExecutionAccess access(isolate_); 545 OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); 546 ThreadLocal blank; 547 548 // Set the stack limits using the old thread_local_. 549 // TODO(isolates): This was the old semantics of constructing a ThreadLocal 550 // (as the ctor called SetStackLimits, which looked at the 551 // current thread_local_ from StackGuard)-- but is this 552 // really what was intended? 553 isolate_->heap()->SetStackLimits(); 554 thread_local_ = blank; 555 556 return to + sizeof(ThreadLocal); 557 } 558 559 560 char* StackGuard::RestoreStackGuard(char* from) { 561 ExecutionAccess access(isolate_); 562 OS::MemCopy( 563 reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); 564 isolate_->heap()->SetStackLimits(); 565 return from + sizeof(ThreadLocal); 566 } 567 568 569 void StackGuard::FreeThreadResources() { 570 Isolate::PerIsolateThreadData* per_thread = 571 isolate_->FindOrAllocatePerThreadDataForThisThread(); 572 per_thread->set_stack_limit(thread_local_.real_climit_); 573 } 574 575 576 void StackGuard::ThreadLocal::Clear() { 577 real_jslimit_ = kIllegalLimit; 578 jslimit_ = kIllegalLimit; 579 real_climit_ = kIllegalLimit; 580 climit_ = kIllegalLimit; 581 nesting_ = 0; 582 postpone_interrupts_nesting_ = 0; 583 interrupt_flags_ = 0; 584 } 585 586 587 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) { 588 bool should_set_stack_limits = false; 589 if (real_climit_ == kIllegalLimit) { 590 // Takes the address of the limit variable in order to find out where 591 // the top of stack is right now. 592 const uintptr_t kLimitSize = FLAG_stack_size * KB; 593 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize; 594 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize); 595 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); 596 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); 597 real_climit_ = limit; 598 climit_ = limit; 599 should_set_stack_limits = true; 600 } 601 nesting_ = 0; 602 postpone_interrupts_nesting_ = 0; 603 interrupt_flags_ = 0; 604 return should_set_stack_limits; 605 } 606 607 608 void StackGuard::ClearThread(const ExecutionAccess& lock) { 609 thread_local_.Clear(); 610 isolate_->heap()->SetStackLimits(); 611 } 612 613 614 void StackGuard::InitThread(const ExecutionAccess& lock) { 615 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits(); 616 Isolate::PerIsolateThreadData* per_thread = 617 isolate_->FindOrAllocatePerThreadDataForThisThread(); 618 uintptr_t stored_limit = per_thread->stack_limit(); 619 // You should hold the ExecutionAccess lock when you call this. 620 if (stored_limit != 0) { 621 SetStackLimit(stored_limit); 622 } 623 } 624 625 626 // --- C a l l s t o n a t i v e s --- 627 628 #define RETURN_NATIVE_CALL(name, args, has_pending_exception) \ 629 do { \ 630 Handle<Object> argv[] = args; \ 631 ASSERT(has_pending_exception != NULL); \ 632 return Call(isolate, \ 633 isolate->name##_fun(), \ 634 isolate->js_builtins_object(), \ 635 ARRAY_SIZE(argv), argv, \ 636 has_pending_exception); \ 637 } while (false) 638 639 640 Handle<Object> Execution::ToNumber( 641 Isolate* isolate, Handle<Object> obj, bool* exc) { 642 RETURN_NATIVE_CALL(to_number, { obj }, exc); 643 } 644 645 646 Handle<Object> Execution::ToString( 647 Isolate* isolate, Handle<Object> obj, bool* exc) { 648 RETURN_NATIVE_CALL(to_string, { obj }, exc); 649 } 650 651 652 Handle<Object> Execution::ToDetailString( 653 Isolate* isolate, Handle<Object> obj, bool* exc) { 654 RETURN_NATIVE_CALL(to_detail_string, { obj }, exc); 655 } 656 657 658 Handle<Object> Execution::ToObject( 659 Isolate* isolate, Handle<Object> obj, bool* exc) { 660 if (obj->IsSpecObject()) return obj; 661 RETURN_NATIVE_CALL(to_object, { obj }, exc); 662 } 663 664 665 Handle<Object> Execution::ToInteger( 666 Isolate* isolate, Handle<Object> obj, bool* exc) { 667 RETURN_NATIVE_CALL(to_integer, { obj }, exc); 668 } 669 670 671 Handle<Object> Execution::ToUint32( 672 Isolate* isolate, Handle<Object> obj, bool* exc) { 673 RETURN_NATIVE_CALL(to_uint32, { obj }, exc); 674 } 675 676 677 Handle<Object> Execution::ToInt32( 678 Isolate* isolate, Handle<Object> obj, bool* exc) { 679 RETURN_NATIVE_CALL(to_int32, { obj }, exc); 680 } 681 682 683 Handle<Object> Execution::NewDate(Isolate* isolate, double time, bool* exc) { 684 Handle<Object> time_obj = isolate->factory()->NewNumber(time); 685 RETURN_NATIVE_CALL(create_date, { time_obj }, exc); 686 } 687 688 689 #undef RETURN_NATIVE_CALL 690 691 692 Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern, 693 Handle<String> flags, 694 bool* exc) { 695 Handle<JSFunction> function = Handle<JSFunction>( 696 pattern->GetIsolate()->native_context()->regexp_function()); 697 Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral( 698 function, pattern, flags, exc); 699 if (*exc) return Handle<JSRegExp>(); 700 return Handle<JSRegExp>::cast(re_obj); 701 } 702 703 704 Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) { 705 Isolate* isolate = string->GetIsolate(); 706 Factory* factory = isolate->factory(); 707 708 int int_index = static_cast<int>(index); 709 if (int_index < 0 || int_index >= string->length()) { 710 return factory->undefined_value(); 711 } 712 713 Handle<Object> char_at = GetProperty( 714 isolate, isolate->js_builtins_object(), factory->char_at_string()); 715 if (!char_at->IsJSFunction()) { 716 return factory->undefined_value(); 717 } 718 719 bool caught_exception; 720 Handle<Object> index_object = factory->NewNumberFromInt(int_index); 721 Handle<Object> index_arg[] = { index_object }; 722 Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at), 723 string, 724 ARRAY_SIZE(index_arg), 725 index_arg, 726 &caught_exception); 727 if (caught_exception) { 728 return factory->undefined_value(); 729 } 730 return result; 731 } 732 733 734 Handle<JSFunction> Execution::InstantiateFunction( 735 Handle<FunctionTemplateInfo> data, 736 bool* exc) { 737 Isolate* isolate = data->GetIsolate(); 738 if (!data->do_not_cache()) { 739 // Fast case: see if the function has already been instantiated 740 int serial_number = Smi::cast(data->serial_number())->value(); 741 Object* elm = 742 isolate->native_context()->function_cache()-> 743 GetElementNoExceptionThrown(isolate, serial_number); 744 if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm)); 745 } 746 // The function has not yet been instantiated in this context; do it. 747 Handle<Object> args[] = { data }; 748 Handle<Object> result = Call(isolate, 749 isolate->instantiate_fun(), 750 isolate->js_builtins_object(), 751 ARRAY_SIZE(args), 752 args, 753 exc); 754 if (*exc) return Handle<JSFunction>::null(); 755 return Handle<JSFunction>::cast(result); 756 } 757 758 759 Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data, 760 bool* exc) { 761 Isolate* isolate = data->GetIsolate(); 762 if (data->property_list()->IsUndefined() && 763 !data->constructor()->IsUndefined()) { 764 // Initialization to make gcc happy. 765 Object* result = NULL; 766 { 767 HandleScope scope(isolate); 768 Handle<FunctionTemplateInfo> cons_template = 769 Handle<FunctionTemplateInfo>( 770 FunctionTemplateInfo::cast(data->constructor())); 771 Handle<JSFunction> cons = InstantiateFunction(cons_template, exc); 772 if (*exc) return Handle<JSObject>::null(); 773 Handle<Object> value = New(cons, 0, NULL, exc); 774 if (*exc) return Handle<JSObject>::null(); 775 result = *value; 776 } 777 ASSERT(!*exc); 778 return Handle<JSObject>(JSObject::cast(result)); 779 } else { 780 Handle<Object> args[] = { data }; 781 Handle<Object> result = Call(isolate, 782 isolate->instantiate_fun(), 783 isolate->js_builtins_object(), 784 ARRAY_SIZE(args), 785 args, 786 exc); 787 if (*exc) return Handle<JSObject>::null(); 788 return Handle<JSObject>::cast(result); 789 } 790 } 791 792 793 void Execution::ConfigureInstance(Isolate* isolate, 794 Handle<Object> instance, 795 Handle<Object> instance_template, 796 bool* exc) { 797 Handle<Object> args[] = { instance, instance_template }; 798 Execution::Call(isolate, 799 isolate->configure_instance_fun(), 800 isolate->js_builtins_object(), 801 ARRAY_SIZE(args), 802 args, 803 exc); 804 } 805 806 807 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv, 808 Handle<JSFunction> fun, 809 Handle<Object> pos, 810 Handle<Object> is_global) { 811 Isolate* isolate = fun->GetIsolate(); 812 Handle<Object> args[] = { recv, fun, pos, is_global }; 813 bool caught_exception; 814 Handle<Object> result = TryCall(isolate->get_stack_trace_line_fun(), 815 isolate->js_builtins_object(), 816 ARRAY_SIZE(args), 817 args, 818 &caught_exception); 819 if (caught_exception || !result->IsString()) { 820 return isolate->factory()->empty_string(); 821 } 822 823 return Handle<String>::cast(result); 824 } 825 826 827 static Object* RuntimePreempt(Isolate* isolate) { 828 // Clear the preempt request flag. 829 isolate->stack_guard()->Continue(PREEMPT); 830 831 #ifdef ENABLE_DEBUGGER_SUPPORT 832 if (isolate->debug()->InDebugger()) { 833 // If currently in the debugger don't do any actual preemption but record 834 // that preemption occoured while in the debugger. 835 isolate->debug()->PreemptionWhileInDebugger(); 836 } else { 837 // Perform preemption. 838 v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate)); 839 Thread::YieldCPU(); 840 } 841 #else 842 { // NOLINT 843 // Perform preemption. 844 v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate)); 845 Thread::YieldCPU(); 846 } 847 #endif 848 849 return isolate->heap()->undefined_value(); 850 } 851 852 853 #ifdef ENABLE_DEBUGGER_SUPPORT 854 Object* Execution::DebugBreakHelper(Isolate* isolate) { 855 // Just continue if breaks are disabled. 856 if (isolate->debug()->disable_break()) { 857 return isolate->heap()->undefined_value(); 858 } 859 860 // Ignore debug break during bootstrapping. 861 if (isolate->bootstrapper()->IsActive()) { 862 return isolate->heap()->undefined_value(); 863 } 864 865 // Ignore debug break if debugger is not active. 866 if (!isolate->debugger()->IsDebuggerActive()) { 867 return isolate->heap()->undefined_value(); 868 } 869 870 StackLimitCheck check(isolate); 871 if (check.HasOverflowed()) { 872 return isolate->heap()->undefined_value(); 873 } 874 875 { 876 JavaScriptFrameIterator it(isolate); 877 ASSERT(!it.done()); 878 Object* fun = it.frame()->function(); 879 if (fun && fun->IsJSFunction()) { 880 // Don't stop in builtin functions. 881 if (JSFunction::cast(fun)->IsBuiltin()) { 882 return isolate->heap()->undefined_value(); 883 } 884 GlobalObject* global = JSFunction::cast(fun)->context()->global_object(); 885 // Don't stop in debugger functions. 886 if (isolate->debug()->IsDebugGlobal(global)) { 887 return isolate->heap()->undefined_value(); 888 } 889 } 890 } 891 892 // Collect the break state before clearing the flags. 893 bool debug_command_only = 894 isolate->stack_guard()->IsDebugCommand() && 895 !isolate->stack_guard()->IsDebugBreak(); 896 897 // Clear the debug break request flag. 898 isolate->stack_guard()->Continue(DEBUGBREAK); 899 900 ProcessDebugMessages(isolate, debug_command_only); 901 902 // Return to continue execution. 903 return isolate->heap()->undefined_value(); 904 } 905 906 907 void Execution::ProcessDebugMessages(Isolate* isolate, 908 bool debug_command_only) { 909 // Clear the debug command request flag. 910 isolate->stack_guard()->Continue(DEBUGCOMMAND); 911 912 StackLimitCheck check(isolate); 913 if (check.HasOverflowed()) { 914 return; 915 } 916 917 HandleScope scope(isolate); 918 // Enter the debugger. Just continue if we fail to enter the debugger. 919 EnterDebugger debugger(isolate); 920 if (debugger.FailedToEnter()) { 921 return; 922 } 923 924 // Notify the debug event listeners. Indicate auto continue if the break was 925 // a debug command break. 926 isolate->debugger()->OnDebugBreak(isolate->factory()->undefined_value(), 927 debug_command_only); 928 } 929 930 931 #endif 932 933 MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) { 934 StackGuard* stack_guard = isolate->stack_guard(); 935 if (stack_guard->ShouldPostponeInterrupts()) { 936 return isolate->heap()->undefined_value(); 937 } 938 939 if (stack_guard->IsGCRequest()) { 940 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, 941 "StackGuard GC request"); 942 stack_guard->Continue(GC_REQUEST); 943 } 944 945 isolate->counters()->stack_interrupts()->Increment(); 946 isolate->counters()->runtime_profiler_ticks()->Increment(); 947 #ifdef ENABLE_DEBUGGER_SUPPORT 948 if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) { 949 DebugBreakHelper(isolate); 950 } 951 #endif 952 if (stack_guard->IsPreempted()) RuntimePreempt(isolate); 953 if (stack_guard->IsTerminateExecution()) { 954 stack_guard->Continue(TERMINATE); 955 return isolate->TerminateExecution(); 956 } 957 if (stack_guard->IsInterrupted()) { 958 stack_guard->Continue(INTERRUPT); 959 return isolate->StackOverflow(); 960 } 961 if (stack_guard->IsFullDeopt()) { 962 stack_guard->Continue(FULL_DEOPT); 963 Deoptimizer::DeoptimizeAll(isolate); 964 } 965 if (stack_guard->IsInstallCodeRequest()) { 966 ASSERT(isolate->concurrent_recompilation_enabled()); 967 stack_guard->Continue(INSTALL_CODE); 968 isolate->optimizing_compiler_thread()->InstallOptimizedFunctions(); 969 } 970 isolate->runtime_profiler()->OptimizeNow(); 971 return isolate->heap()->undefined_value(); 972 } 973 974 975 } } // namespace v8::internal 976