1 // Copyright 2014 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/execution.h" 6 7 #include "src/bootstrapper.h" 8 #include "src/codegen.h" 9 #include "src/deoptimizer.h" 10 #include "src/isolate-inl.h" 11 #include "src/vm-state-inl.h" 12 13 namespace v8 { 14 namespace internal { 15 16 StackGuard::StackGuard() 17 : isolate_(NULL) { 18 } 19 20 21 void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) { 22 DCHECK(isolate_ != NULL); 23 thread_local_.jslimit_ = kInterruptLimit; 24 thread_local_.climit_ = kInterruptLimit; 25 isolate_->heap()->SetStackLimits(); 26 } 27 28 29 void StackGuard::reset_limits(const ExecutionAccess& lock) { 30 DCHECK(isolate_ != NULL); 31 thread_local_.jslimit_ = thread_local_.real_jslimit_; 32 thread_local_.climit_ = thread_local_.real_climit_; 33 isolate_->heap()->SetStackLimits(); 34 } 35 36 37 MUST_USE_RESULT static MaybeHandle<Object> Invoke( 38 bool is_construct, 39 Handle<JSFunction> function, 40 Handle<Object> receiver, 41 int argc, 42 Handle<Object> args[]) { 43 Isolate* isolate = function->GetIsolate(); 44 45 // Entering JavaScript. 46 VMState<JS> state(isolate); 47 CHECK(AllowJavascriptExecution::IsAllowed(isolate)); 48 if (!ThrowOnJavascriptExecution::IsAllowed(isolate)) { 49 isolate->ThrowIllegalOperation(); 50 isolate->ReportPendingMessages(); 51 return MaybeHandle<Object>(); 52 } 53 54 // Placeholder for return value. 55 Object* value = NULL; 56 57 typedef Object* (*JSEntryFunction)(byte* entry, 58 Object* function, 59 Object* receiver, 60 int argc, 61 Object*** args); 62 63 Handle<Code> code = is_construct 64 ? isolate->factory()->js_construct_entry_code() 65 : isolate->factory()->js_entry_code(); 66 67 // Convert calls on global objects to be calls on the global 68 // receiver instead to avoid having a 'this' pointer which refers 69 // directly to a global object. 70 if (receiver->IsGlobalObject()) { 71 receiver = handle(Handle<GlobalObject>::cast(receiver)->global_proxy()); 72 } 73 74 // Make sure that the global object of the context we're about to 75 // make the current one is indeed a global object. 76 DCHECK(function->context()->global_object()->IsGlobalObject()); 77 78 { 79 // Save and restore context around invocation and block the 80 // allocation of handles without explicit handle scopes. 81 SaveContext save(isolate); 82 SealHandleScope shs(isolate); 83 JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry()); 84 85 // Call the function through the right JS entry stub. 86 byte* function_entry = function->code()->entry(); 87 JSFunction* func = *function; 88 Object* recv = *receiver; 89 Object*** argv = reinterpret_cast<Object***>(args); 90 value = 91 CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv); 92 } 93 94 #ifdef VERIFY_HEAP 95 value->ObjectVerify(); 96 #endif 97 98 // Update the pending exception flag and return the value. 99 bool has_exception = value->IsException(); 100 DCHECK(has_exception == isolate->has_pending_exception()); 101 if (has_exception) { 102 isolate->ReportPendingMessages(); 103 // Reset stepping state when script exits with uncaught exception. 104 if (isolate->debug()->is_active()) { 105 isolate->debug()->ClearStepping(); 106 } 107 return MaybeHandle<Object>(); 108 } else { 109 isolate->clear_pending_message(); 110 } 111 112 return Handle<Object>(value, isolate); 113 } 114 115 116 MaybeHandle<Object> Execution::Call(Isolate* isolate, 117 Handle<Object> callable, 118 Handle<Object> receiver, 119 int argc, 120 Handle<Object> argv[], 121 bool convert_receiver) { 122 if (!callable->IsJSFunction()) { 123 ASSIGN_RETURN_ON_EXCEPTION( 124 isolate, callable, TryGetFunctionDelegate(isolate, callable), Object); 125 } 126 Handle<JSFunction> func = Handle<JSFunction>::cast(callable); 127 128 // In sloppy mode, convert receiver. 129 if (convert_receiver && !receiver->IsJSReceiver() && 130 !func->shared()->native() && 131 func->shared()->strict_mode() == SLOPPY) { 132 if (receiver->IsUndefined() || receiver->IsNull()) { 133 receiver = handle(func->global_proxy()); 134 DCHECK(!receiver->IsJSBuiltinsObject()); 135 } else { 136 ASSIGN_RETURN_ON_EXCEPTION( 137 isolate, receiver, ToObject(isolate, receiver), Object); 138 } 139 } 140 141 return Invoke(false, func, receiver, argc, argv); 142 } 143 144 145 MaybeHandle<Object> Execution::New(Handle<JSFunction> func, 146 int argc, 147 Handle<Object> argv[]) { 148 return Invoke(true, func, handle(func->global_proxy()), argc, argv); 149 } 150 151 152 MaybeHandle<Object> Execution::TryCall(Handle<JSFunction> func, 153 Handle<Object> receiver, int argc, 154 Handle<Object> args[], 155 MaybeHandle<Object>* exception_out) { 156 bool is_termination = false; 157 Isolate* isolate = func->GetIsolate(); 158 MaybeHandle<Object> maybe_result; 159 if (exception_out != NULL) *exception_out = MaybeHandle<Object>(); 160 // Enter a try-block while executing the JavaScript code. To avoid 161 // duplicate error printing it must be non-verbose. Also, to avoid 162 // creating message objects during stack overflow we shouldn't 163 // capture messages. 164 { 165 v8::TryCatch catcher; 166 catcher.SetVerbose(false); 167 catcher.SetCaptureMessage(false); 168 169 maybe_result = Invoke(false, func, receiver, argc, args); 170 171 if (maybe_result.is_null()) { 172 DCHECK(catcher.HasCaught()); 173 DCHECK(isolate->has_pending_exception()); 174 DCHECK(isolate->external_caught_exception()); 175 if (exception_out != NULL) { 176 if (isolate->pending_exception() == 177 isolate->heap()->termination_exception()) { 178 is_termination = true; 179 } else { 180 *exception_out = v8::Utils::OpenHandle(*catcher.Exception()); 181 } 182 } 183 isolate->OptionalRescheduleException(true); 184 } 185 186 DCHECK(!isolate->has_pending_exception()); 187 DCHECK(!isolate->external_caught_exception()); 188 } 189 if (is_termination) isolate->TerminateExecution(); 190 return maybe_result; 191 } 192 193 194 Handle<Object> Execution::GetFunctionDelegate(Isolate* isolate, 195 Handle<Object> object) { 196 DCHECK(!object->IsJSFunction()); 197 Factory* factory = isolate->factory(); 198 199 // If you return a function from here, it will be called when an 200 // attempt is made to call the given object as a function. 201 202 // If object is a function proxy, get its handler. Iterate if necessary. 203 Object* fun = *object; 204 while (fun->IsJSFunctionProxy()) { 205 fun = JSFunctionProxy::cast(fun)->call_trap(); 206 } 207 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate); 208 209 // Objects created through the API can have an instance-call handler 210 // that should be used when calling the object as a function. 211 if (fun->IsHeapObject() && 212 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 213 return Handle<JSFunction>( 214 isolate->native_context()->call_as_function_delegate()); 215 } 216 217 return factory->undefined_value(); 218 } 219 220 221 MaybeHandle<Object> Execution::TryGetFunctionDelegate(Isolate* isolate, 222 Handle<Object> object) { 223 DCHECK(!object->IsJSFunction()); 224 225 // If object is a function proxy, get its handler. Iterate if necessary. 226 Object* fun = *object; 227 while (fun->IsJSFunctionProxy()) { 228 fun = JSFunctionProxy::cast(fun)->call_trap(); 229 } 230 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate); 231 232 // Objects created through the API can have an instance-call handler 233 // that should be used when calling the object as a function. 234 if (fun->IsHeapObject() && 235 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 236 return Handle<JSFunction>( 237 isolate->native_context()->call_as_function_delegate()); 238 } 239 240 // If the Object doesn't have an instance-call handler we should 241 // throw a non-callable exception. 242 THROW_NEW_ERROR(isolate, NewTypeError("called_non_callable", 243 i::HandleVector<i::Object>(&object, 1)), 244 Object); 245 } 246 247 248 Handle<Object> Execution::GetConstructorDelegate(Isolate* isolate, 249 Handle<Object> object) { 250 DCHECK(!object->IsJSFunction()); 251 252 // If you return a function from here, it will be called when an 253 // attempt is made to call the given object as a constructor. 254 255 // If object is a function proxies, get its handler. Iterate if necessary. 256 Object* fun = *object; 257 while (fun->IsJSFunctionProxy()) { 258 fun = JSFunctionProxy::cast(fun)->call_trap(); 259 } 260 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate); 261 262 // Objects created through the API can have an instance-call handler 263 // that should be used when calling the object as a function. 264 if (fun->IsHeapObject() && 265 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 266 return Handle<JSFunction>( 267 isolate->native_context()->call_as_constructor_delegate()); 268 } 269 270 return isolate->factory()->undefined_value(); 271 } 272 273 274 MaybeHandle<Object> Execution::TryGetConstructorDelegate( 275 Isolate* isolate, Handle<Object> object) { 276 DCHECK(!object->IsJSFunction()); 277 278 // If you return a function from here, it will be called when an 279 // attempt is made to call the given object as a constructor. 280 281 // If object is a function proxies, get its handler. Iterate if necessary. 282 Object* fun = *object; 283 while (fun->IsJSFunctionProxy()) { 284 fun = JSFunctionProxy::cast(fun)->call_trap(); 285 } 286 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate); 287 288 // Objects created through the API can have an instance-call handler 289 // that should be used when calling the object as a function. 290 if (fun->IsHeapObject() && 291 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 292 return Handle<JSFunction>( 293 isolate->native_context()->call_as_constructor_delegate()); 294 } 295 296 // If the Object doesn't have an instance-call handler we should 297 // throw a non-callable exception. 298 THROW_NEW_ERROR(isolate, NewTypeError("called_non_callable", 299 i::HandleVector<i::Object>(&object, 1)), 300 Object); 301 } 302 303 304 void StackGuard::EnableInterrupts() { 305 ExecutionAccess access(isolate_); 306 if (has_pending_interrupts(access)) { 307 set_interrupt_limits(access); 308 } 309 } 310 311 312 void StackGuard::SetStackLimit(uintptr_t limit) { 313 ExecutionAccess access(isolate_); 314 // If the current limits are special (e.g. due to a pending interrupt) then 315 // leave them alone. 316 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit); 317 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) { 318 thread_local_.jslimit_ = jslimit; 319 } 320 if (thread_local_.climit_ == thread_local_.real_climit_) { 321 thread_local_.climit_ = limit; 322 } 323 thread_local_.real_climit_ = limit; 324 thread_local_.real_jslimit_ = jslimit; 325 } 326 327 328 void StackGuard::DisableInterrupts() { 329 ExecutionAccess access(isolate_); 330 reset_limits(access); 331 } 332 333 334 void StackGuard::PushPostponeInterruptsScope(PostponeInterruptsScope* scope) { 335 ExecutionAccess access(isolate_); 336 // Intercept already requested interrupts. 337 int intercepted = thread_local_.interrupt_flags_ & scope->intercept_mask_; 338 scope->intercepted_flags_ = intercepted; 339 thread_local_.interrupt_flags_ &= ~intercepted; 340 if (!has_pending_interrupts(access)) reset_limits(access); 341 // Add scope to the chain. 342 scope->prev_ = thread_local_.postpone_interrupts_; 343 thread_local_.postpone_interrupts_ = scope; 344 } 345 346 347 void StackGuard::PopPostponeInterruptsScope() { 348 ExecutionAccess access(isolate_); 349 PostponeInterruptsScope* top = thread_local_.postpone_interrupts_; 350 // Make intercepted interrupts active. 351 DCHECK((thread_local_.interrupt_flags_ & top->intercept_mask_) == 0); 352 thread_local_.interrupt_flags_ |= top->intercepted_flags_; 353 if (has_pending_interrupts(access)) set_interrupt_limits(access); 354 // Remove scope from chain. 355 thread_local_.postpone_interrupts_ = top->prev_; 356 } 357 358 359 bool StackGuard::CheckInterrupt(InterruptFlag flag) { 360 ExecutionAccess access(isolate_); 361 return thread_local_.interrupt_flags_ & flag; 362 } 363 364 365 void StackGuard::RequestInterrupt(InterruptFlag flag) { 366 ExecutionAccess access(isolate_); 367 // Check the chain of PostponeInterruptsScopes for interception. 368 if (thread_local_.postpone_interrupts_ && 369 thread_local_.postpone_interrupts_->Intercept(flag)) { 370 return; 371 } 372 373 // Not intercepted. Set as active interrupt flag. 374 thread_local_.interrupt_flags_ |= flag; 375 set_interrupt_limits(access); 376 } 377 378 379 void StackGuard::ClearInterrupt(InterruptFlag flag) { 380 ExecutionAccess access(isolate_); 381 // Clear the interrupt flag from the chain of PostponeInterruptsScopes. 382 for (PostponeInterruptsScope* current = thread_local_.postpone_interrupts_; 383 current != NULL; 384 current = current->prev_) { 385 current->intercepted_flags_ &= ~flag; 386 } 387 388 // Clear the interrupt flag from the active interrupt flags. 389 thread_local_.interrupt_flags_ &= ~flag; 390 if (!has_pending_interrupts(access)) reset_limits(access); 391 } 392 393 394 bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) { 395 ExecutionAccess access(isolate_); 396 bool result = (thread_local_.interrupt_flags_ & flag); 397 thread_local_.interrupt_flags_ &= ~flag; 398 if (!has_pending_interrupts(access)) reset_limits(access); 399 return result; 400 } 401 402 403 char* StackGuard::ArchiveStackGuard(char* to) { 404 ExecutionAccess access(isolate_); 405 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); 406 ThreadLocal blank; 407 408 // Set the stack limits using the old thread_local_. 409 // TODO(isolates): This was the old semantics of constructing a ThreadLocal 410 // (as the ctor called SetStackLimits, which looked at the 411 // current thread_local_ from StackGuard)-- but is this 412 // really what was intended? 413 isolate_->heap()->SetStackLimits(); 414 thread_local_ = blank; 415 416 return to + sizeof(ThreadLocal); 417 } 418 419 420 char* StackGuard::RestoreStackGuard(char* from) { 421 ExecutionAccess access(isolate_); 422 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); 423 isolate_->heap()->SetStackLimits(); 424 return from + sizeof(ThreadLocal); 425 } 426 427 428 void StackGuard::FreeThreadResources() { 429 Isolate::PerIsolateThreadData* per_thread = 430 isolate_->FindOrAllocatePerThreadDataForThisThread(); 431 per_thread->set_stack_limit(thread_local_.real_climit_); 432 } 433 434 435 void StackGuard::ThreadLocal::Clear() { 436 real_jslimit_ = kIllegalLimit; 437 jslimit_ = kIllegalLimit; 438 real_climit_ = kIllegalLimit; 439 climit_ = kIllegalLimit; 440 postpone_interrupts_ = NULL; 441 interrupt_flags_ = 0; 442 } 443 444 445 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) { 446 bool should_set_stack_limits = false; 447 if (real_climit_ == kIllegalLimit) { 448 const uintptr_t kLimitSize = FLAG_stack_size * KB; 449 DCHECK(GetCurrentStackPosition() > kLimitSize); 450 uintptr_t limit = GetCurrentStackPosition() - kLimitSize; 451 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); 452 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); 453 real_climit_ = limit; 454 climit_ = limit; 455 should_set_stack_limits = true; 456 } 457 postpone_interrupts_ = NULL; 458 interrupt_flags_ = 0; 459 return should_set_stack_limits; 460 } 461 462 463 void StackGuard::ClearThread(const ExecutionAccess& lock) { 464 thread_local_.Clear(); 465 isolate_->heap()->SetStackLimits(); 466 } 467 468 469 void StackGuard::InitThread(const ExecutionAccess& lock) { 470 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits(); 471 Isolate::PerIsolateThreadData* per_thread = 472 isolate_->FindOrAllocatePerThreadDataForThisThread(); 473 uintptr_t stored_limit = per_thread->stack_limit(); 474 // You should hold the ExecutionAccess lock when you call this. 475 if (stored_limit != 0) { 476 SetStackLimit(stored_limit); 477 } 478 } 479 480 481 // --- C a l l s t o n a t i v e s --- 482 483 #define RETURN_NATIVE_CALL(name, args) \ 484 do { \ 485 Handle<Object> argv[] = args; \ 486 return Call(isolate, \ 487 isolate->name##_fun(), \ 488 isolate->js_builtins_object(), \ 489 arraysize(argv), argv); \ 490 } while (false) 491 492 493 MaybeHandle<Object> Execution::ToNumber( 494 Isolate* isolate, Handle<Object> obj) { 495 RETURN_NATIVE_CALL(to_number, { obj }); 496 } 497 498 499 MaybeHandle<Object> Execution::ToString( 500 Isolate* isolate, Handle<Object> obj) { 501 RETURN_NATIVE_CALL(to_string, { obj }); 502 } 503 504 505 MaybeHandle<Object> Execution::ToDetailString( 506 Isolate* isolate, Handle<Object> obj) { 507 RETURN_NATIVE_CALL(to_detail_string, { obj }); 508 } 509 510 511 MaybeHandle<Object> Execution::ToObject( 512 Isolate* isolate, Handle<Object> obj) { 513 if (obj->IsSpecObject()) return obj; 514 RETURN_NATIVE_CALL(to_object, { obj }); 515 } 516 517 518 MaybeHandle<Object> Execution::ToInteger( 519 Isolate* isolate, Handle<Object> obj) { 520 RETURN_NATIVE_CALL(to_integer, { obj }); 521 } 522 523 524 MaybeHandle<Object> Execution::ToUint32( 525 Isolate* isolate, Handle<Object> obj) { 526 RETURN_NATIVE_CALL(to_uint32, { obj }); 527 } 528 529 530 MaybeHandle<Object> Execution::ToInt32( 531 Isolate* isolate, Handle<Object> obj) { 532 RETURN_NATIVE_CALL(to_int32, { obj }); 533 } 534 535 536 MaybeHandle<Object> Execution::NewDate(Isolate* isolate, double time) { 537 Handle<Object> time_obj = isolate->factory()->NewNumber(time); 538 RETURN_NATIVE_CALL(create_date, { time_obj }); 539 } 540 541 542 #undef RETURN_NATIVE_CALL 543 544 545 MaybeHandle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern, 546 Handle<String> flags) { 547 Isolate* isolate = pattern->GetIsolate(); 548 Handle<JSFunction> function = Handle<JSFunction>( 549 isolate->native_context()->regexp_function()); 550 Handle<Object> re_obj; 551 ASSIGN_RETURN_ON_EXCEPTION( 552 isolate, re_obj, 553 RegExpImpl::CreateRegExpLiteral(function, pattern, flags), 554 JSRegExp); 555 return Handle<JSRegExp>::cast(re_obj); 556 } 557 558 559 Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) { 560 Isolate* isolate = string->GetIsolate(); 561 Factory* factory = isolate->factory(); 562 563 int int_index = static_cast<int>(index); 564 if (int_index < 0 || int_index >= string->length()) { 565 return factory->undefined_value(); 566 } 567 568 Handle<Object> char_at = Object::GetProperty( 569 isolate->js_builtins_object(), 570 factory->char_at_string()).ToHandleChecked(); 571 if (!char_at->IsJSFunction()) { 572 return factory->undefined_value(); 573 } 574 575 Handle<Object> index_object = factory->NewNumberFromInt(int_index); 576 Handle<Object> index_arg[] = { index_object }; 577 Handle<Object> result; 578 if (!TryCall(Handle<JSFunction>::cast(char_at), 579 string, 580 arraysize(index_arg), 581 index_arg).ToHandle(&result)) { 582 return factory->undefined_value(); 583 } 584 return result; 585 } 586 587 588 MaybeHandle<JSFunction> Execution::InstantiateFunction( 589 Handle<FunctionTemplateInfo> data) { 590 Isolate* isolate = data->GetIsolate(); 591 if (!data->do_not_cache()) { 592 // Fast case: see if the function has already been instantiated 593 int serial_number = Smi::cast(data->serial_number())->value(); 594 Handle<JSObject> cache(isolate->native_context()->function_cache()); 595 Handle<Object> elm = 596 Object::GetElement(isolate, cache, serial_number).ToHandleChecked(); 597 if (elm->IsJSFunction()) return Handle<JSFunction>::cast(elm); 598 } 599 // The function has not yet been instantiated in this context; do it. 600 Handle<Object> args[] = { data }; 601 Handle<Object> result; 602 ASSIGN_RETURN_ON_EXCEPTION( 603 isolate, result, 604 Call(isolate, 605 isolate->instantiate_fun(), 606 isolate->js_builtins_object(), 607 arraysize(args), 608 args), 609 JSFunction); 610 return Handle<JSFunction>::cast(result); 611 } 612 613 614 MaybeHandle<JSObject> Execution::InstantiateObject( 615 Handle<ObjectTemplateInfo> data) { 616 Isolate* isolate = data->GetIsolate(); 617 Handle<Object> result; 618 if (data->property_list()->IsUndefined() && 619 !data->constructor()->IsUndefined()) { 620 Handle<FunctionTemplateInfo> cons_template = 621 Handle<FunctionTemplateInfo>( 622 FunctionTemplateInfo::cast(data->constructor())); 623 Handle<JSFunction> cons; 624 ASSIGN_RETURN_ON_EXCEPTION( 625 isolate, cons, InstantiateFunction(cons_template), JSObject); 626 ASSIGN_RETURN_ON_EXCEPTION(isolate, result, New(cons, 0, NULL), JSObject); 627 } else { 628 Handle<Object> args[] = { data }; 629 ASSIGN_RETURN_ON_EXCEPTION( 630 isolate, result, 631 Call(isolate, 632 isolate->instantiate_fun(), 633 isolate->js_builtins_object(), 634 arraysize(args), 635 args), 636 JSObject); 637 } 638 return Handle<JSObject>::cast(result); 639 } 640 641 642 MaybeHandle<Object> Execution::ConfigureInstance( 643 Isolate* isolate, 644 Handle<Object> instance, 645 Handle<Object> instance_template) { 646 Handle<Object> args[] = { instance, instance_template }; 647 return Execution::Call(isolate, 648 isolate->configure_instance_fun(), 649 isolate->js_builtins_object(), 650 arraysize(args), 651 args); 652 } 653 654 655 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv, 656 Handle<JSFunction> fun, 657 Handle<Object> pos, 658 Handle<Object> is_global) { 659 Isolate* isolate = fun->GetIsolate(); 660 Handle<Object> args[] = { recv, fun, pos, is_global }; 661 MaybeHandle<Object> maybe_result = 662 TryCall(isolate->get_stack_trace_line_fun(), 663 isolate->js_builtins_object(), 664 arraysize(args), 665 args); 666 Handle<Object> result; 667 if (!maybe_result.ToHandle(&result) || !result->IsString()) { 668 return isolate->factory()->empty_string(); 669 } 670 671 return Handle<String>::cast(result); 672 } 673 674 675 Object* StackGuard::HandleInterrupts() { 676 if (CheckAndClearInterrupt(GC_REQUEST)) { 677 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt"); 678 } 679 680 if (CheckDebugBreak() || CheckDebugCommand()) { 681 isolate_->debug()->HandleDebugBreak(); 682 } 683 684 if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) { 685 return isolate_->TerminateExecution(); 686 } 687 688 if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) { 689 isolate_->heap()->DeoptMarkedAllocationSites(); 690 } 691 692 if (CheckAndClearInterrupt(INSTALL_CODE)) { 693 DCHECK(isolate_->concurrent_recompilation_enabled()); 694 isolate_->optimizing_compiler_thread()->InstallOptimizedFunctions(); 695 } 696 697 if (CheckAndClearInterrupt(API_INTERRUPT)) { 698 // Callback must be invoked outside of ExecusionAccess lock. 699 isolate_->InvokeApiInterruptCallback(); 700 } 701 702 isolate_->counters()->stack_interrupts()->Increment(); 703 isolate_->counters()->runtime_profiler_ticks()->Increment(); 704 isolate_->runtime_profiler()->OptimizeNow(); 705 706 return isolate_->heap()->undefined_value(); 707 } 708 709 } } // namespace v8::internal 710