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(Handle<Object> callable, 152 Handle<Object> receiver, 153 int argc, 154 Handle<Object> argv[], 155 bool* pending_exception, 156 bool convert_receiver) { 157 *pending_exception = false; 158 159 if (!callable->IsJSFunction()) { 160 callable = TryGetFunctionDelegate(callable, pending_exception); 161 if (*pending_exception) return callable; 162 } 163 Handle<JSFunction> func = Handle<JSFunction>::cast(callable); 164 165 // In non-strict mode, convert receiver. 166 if (convert_receiver && !receiver->IsJSReceiver() && 167 !func->shared()->native() && func->shared()->is_classic_mode()) { 168 if (receiver->IsUndefined() || receiver->IsNull()) { 169 Object* global = func->context()->global_object()->global_receiver(); 170 // Under some circumstances, 'global' can be the JSBuiltinsObject 171 // In that case, don't rewrite. (FWIW, the same holds for 172 // GetIsolate()->global_object()->global_receiver().) 173 if (!global->IsJSBuiltinsObject()) { 174 receiver = Handle<Object>(global, func->GetIsolate()); 175 } 176 } else { 177 receiver = ToObject(receiver, pending_exception); 178 } 179 if (*pending_exception) return callable; 180 } 181 182 return Invoke(false, func, receiver, argc, argv, pending_exception); 183 } 184 185 186 Handle<Object> Execution::New(Handle<JSFunction> func, 187 int argc, 188 Handle<Object> argv[], 189 bool* pending_exception) { 190 return Invoke(true, func, func->GetIsolate()->global_object(), argc, argv, 191 pending_exception); 192 } 193 194 195 Handle<Object> Execution::TryCall(Handle<JSFunction> func, 196 Handle<Object> receiver, 197 int argc, 198 Handle<Object> args[], 199 bool* caught_exception) { 200 // Enter a try-block while executing the JavaScript code. To avoid 201 // duplicate error printing it must be non-verbose. Also, to avoid 202 // creating message objects during stack overflow we shouldn't 203 // capture messages. 204 v8::TryCatch catcher; 205 catcher.SetVerbose(false); 206 catcher.SetCaptureMessage(false); 207 *caught_exception = false; 208 209 // Get isolate now, because handle might be persistent 210 // and get destroyed in the next call. 211 Isolate* isolate = func->GetIsolate(); 212 Handle<Object> result = Invoke(false, func, receiver, argc, args, 213 caught_exception); 214 215 if (*caught_exception) { 216 ASSERT(catcher.HasCaught()); 217 ASSERT(isolate->has_pending_exception()); 218 ASSERT(isolate->external_caught_exception()); 219 if (isolate->is_out_of_memory() && !isolate->ignore_out_of_memory()) { 220 V8::FatalProcessOutOfMemory("OOM during Execution::TryCall"); 221 } 222 if (isolate->pending_exception() == 223 isolate->heap()->termination_exception()) { 224 result = isolate->factory()->termination_exception(); 225 } else { 226 result = v8::Utils::OpenHandle(*catcher.Exception()); 227 } 228 isolate->OptionalRescheduleException(true); 229 } 230 231 ASSERT(!isolate->has_pending_exception()); 232 ASSERT(!isolate->external_caught_exception()); 233 return result; 234 } 235 236 237 Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) { 238 ASSERT(!object->IsJSFunction()); 239 Isolate* isolate = Isolate::Current(); 240 Factory* factory = isolate->factory(); 241 242 // If you return a function from here, it will be called when an 243 // attempt is made to call the given object as a function. 244 245 // If object is a function proxy, get its handler. Iterate if necessary. 246 Object* fun = *object; 247 while (fun->IsJSFunctionProxy()) { 248 fun = JSFunctionProxy::cast(fun)->call_trap(); 249 } 250 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate); 251 252 // Objects created through the API can have an instance-call handler 253 // that should be used when calling the object as a function. 254 if (fun->IsHeapObject() && 255 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 256 return Handle<JSFunction>( 257 isolate->native_context()->call_as_function_delegate()); 258 } 259 260 return factory->undefined_value(); 261 } 262 263 264 Handle<Object> Execution::TryGetFunctionDelegate(Handle<Object> object, 265 bool* has_pending_exception) { 266 ASSERT(!object->IsJSFunction()); 267 Isolate* isolate = Isolate::Current(); 268 269 // If object is a function proxy, get its handler. Iterate if necessary. 270 Object* fun = *object; 271 while (fun->IsJSFunctionProxy()) { 272 fun = JSFunctionProxy::cast(fun)->call_trap(); 273 } 274 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate); 275 276 // Objects created through the API can have an instance-call handler 277 // that should be used when calling the object as a function. 278 if (fun->IsHeapObject() && 279 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 280 return Handle<JSFunction>( 281 isolate->native_context()->call_as_function_delegate()); 282 } 283 284 // If the Object doesn't have an instance-call handler we should 285 // throw a non-callable exception. 286 i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( 287 "called_non_callable", i::HandleVector<i::Object>(&object, 1)); 288 isolate->Throw(*error_obj); 289 *has_pending_exception = true; 290 291 return isolate->factory()->undefined_value(); 292 } 293 294 295 Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) { 296 ASSERT(!object->IsJSFunction()); 297 Isolate* isolate = Isolate::Current(); 298 299 // If you return a function from here, it will be called when an 300 // attempt is made to call the given object as a constructor. 301 302 // If object is a function proxies, get its handler. Iterate if necessary. 303 Object* fun = *object; 304 while (fun->IsJSFunctionProxy()) { 305 fun = JSFunctionProxy::cast(fun)->call_trap(); 306 } 307 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate); 308 309 // Objects created through the API can have an instance-call handler 310 // that should be used when calling the object as a function. 311 if (fun->IsHeapObject() && 312 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 313 return Handle<JSFunction>( 314 isolate->native_context()->call_as_constructor_delegate()); 315 } 316 317 return isolate->factory()->undefined_value(); 318 } 319 320 321 Handle<Object> Execution::TryGetConstructorDelegate( 322 Handle<Object> object, 323 bool* has_pending_exception) { 324 ASSERT(!object->IsJSFunction()); 325 Isolate* isolate = Isolate::Current(); 326 327 // If you return a function from here, it will be called when an 328 // attempt is made to call the given object as a constructor. 329 330 // If object is a function proxies, get its handler. Iterate if necessary. 331 Object* fun = *object; 332 while (fun->IsJSFunctionProxy()) { 333 fun = JSFunctionProxy::cast(fun)->call_trap(); 334 } 335 if (fun->IsJSFunction()) return Handle<Object>(fun, isolate); 336 337 // Objects created through the API can have an instance-call handler 338 // that should be used when calling the object as a function. 339 if (fun->IsHeapObject() && 340 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 341 return Handle<JSFunction>( 342 isolate->native_context()->call_as_constructor_delegate()); 343 } 344 345 // If the Object doesn't have an instance-call handler we should 346 // throw a non-callable exception. 347 i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( 348 "called_non_callable", i::HandleVector<i::Object>(&object, 1)); 349 isolate->Throw(*error_obj); 350 *has_pending_exception = true; 351 352 return isolate->factory()->undefined_value(); 353 } 354 355 356 bool StackGuard::IsStackOverflow() { 357 ExecutionAccess access(isolate_); 358 return (thread_local_.jslimit_ != kInterruptLimit && 359 thread_local_.climit_ != kInterruptLimit); 360 } 361 362 363 void StackGuard::EnableInterrupts() { 364 ExecutionAccess access(isolate_); 365 if (has_pending_interrupts(access)) { 366 set_interrupt_limits(access); 367 } 368 } 369 370 371 void StackGuard::SetStackLimit(uintptr_t limit) { 372 ExecutionAccess access(isolate_); 373 // If the current limits are special (e.g. due to a pending interrupt) then 374 // leave them alone. 375 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit); 376 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) { 377 thread_local_.jslimit_ = jslimit; 378 } 379 if (thread_local_.climit_ == thread_local_.real_climit_) { 380 thread_local_.climit_ = limit; 381 } 382 thread_local_.real_climit_ = limit; 383 thread_local_.real_jslimit_ = jslimit; 384 } 385 386 387 void StackGuard::DisableInterrupts() { 388 ExecutionAccess access(isolate_); 389 reset_limits(access); 390 } 391 392 393 bool StackGuard::ShouldPostponeInterrupts() { 394 ExecutionAccess access(isolate_); 395 return should_postpone_interrupts(access); 396 } 397 398 399 bool StackGuard::IsInterrupted() { 400 ExecutionAccess access(isolate_); 401 return (thread_local_.interrupt_flags_ & INTERRUPT) != 0; 402 } 403 404 405 void StackGuard::Interrupt() { 406 ExecutionAccess access(isolate_); 407 thread_local_.interrupt_flags_ |= INTERRUPT; 408 set_interrupt_limits(access); 409 } 410 411 412 bool StackGuard::IsPreempted() { 413 ExecutionAccess access(isolate_); 414 return thread_local_.interrupt_flags_ & PREEMPT; 415 } 416 417 418 void StackGuard::Preempt() { 419 ExecutionAccess access(isolate_); 420 thread_local_.interrupt_flags_ |= PREEMPT; 421 set_interrupt_limits(access); 422 } 423 424 425 bool StackGuard::IsTerminateExecution() { 426 ExecutionAccess access(isolate_); 427 return (thread_local_.interrupt_flags_ & TERMINATE) != 0; 428 } 429 430 431 void StackGuard::CancelTerminateExecution() { 432 ExecutionAccess access(isolate_); 433 Continue(TERMINATE); 434 isolate_->CancelTerminateExecution(); 435 } 436 437 438 void StackGuard::TerminateExecution() { 439 ExecutionAccess access(isolate_); 440 thread_local_.interrupt_flags_ |= TERMINATE; 441 set_interrupt_limits(access); 442 } 443 444 445 bool StackGuard::IsGCRequest() { 446 ExecutionAccess access(isolate_); 447 return (thread_local_.interrupt_flags_ & GC_REQUEST) != 0; 448 } 449 450 451 void StackGuard::RequestGC() { 452 ExecutionAccess access(isolate_); 453 thread_local_.interrupt_flags_ |= GC_REQUEST; 454 if (thread_local_.postpone_interrupts_nesting_ == 0) { 455 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit; 456 isolate_->heap()->SetStackLimits(); 457 } 458 } 459 460 461 bool StackGuard::IsFullDeopt() { 462 ExecutionAccess access(isolate_); 463 return (thread_local_.interrupt_flags_ & FULL_DEOPT) != 0; 464 } 465 466 467 void StackGuard::FullDeopt() { 468 ExecutionAccess access(isolate_); 469 thread_local_.interrupt_flags_ |= FULL_DEOPT; 470 set_interrupt_limits(access); 471 } 472 473 474 #ifdef ENABLE_DEBUGGER_SUPPORT 475 bool StackGuard::IsDebugBreak() { 476 ExecutionAccess access(isolate_); 477 return thread_local_.interrupt_flags_ & DEBUGBREAK; 478 } 479 480 481 void StackGuard::DebugBreak() { 482 ExecutionAccess access(isolate_); 483 thread_local_.interrupt_flags_ |= DEBUGBREAK; 484 set_interrupt_limits(access); 485 } 486 487 488 bool StackGuard::IsDebugCommand() { 489 ExecutionAccess access(isolate_); 490 return thread_local_.interrupt_flags_ & DEBUGCOMMAND; 491 } 492 493 494 void StackGuard::DebugCommand() { 495 if (FLAG_debugger_auto_break) { 496 ExecutionAccess access(isolate_); 497 thread_local_.interrupt_flags_ |= DEBUGCOMMAND; 498 set_interrupt_limits(access); 499 } 500 } 501 #endif 502 503 void StackGuard::Continue(InterruptFlag after_what) { 504 ExecutionAccess access(isolate_); 505 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what); 506 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) { 507 reset_limits(access); 508 } 509 } 510 511 512 char* StackGuard::ArchiveStackGuard(char* to) { 513 ExecutionAccess access(isolate_); 514 OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); 515 ThreadLocal blank; 516 517 // Set the stack limits using the old thread_local_. 518 // TODO(isolates): This was the old semantics of constructing a ThreadLocal 519 // (as the ctor called SetStackLimits, which looked at the 520 // current thread_local_ from StackGuard)-- but is this 521 // really what was intended? 522 isolate_->heap()->SetStackLimits(); 523 thread_local_ = blank; 524 525 return to + sizeof(ThreadLocal); 526 } 527 528 529 char* StackGuard::RestoreStackGuard(char* from) { 530 ExecutionAccess access(isolate_); 531 OS::MemCopy( 532 reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); 533 isolate_->heap()->SetStackLimits(); 534 return from + sizeof(ThreadLocal); 535 } 536 537 538 void StackGuard::FreeThreadResources() { 539 Isolate::PerIsolateThreadData* per_thread = 540 isolate_->FindOrAllocatePerThreadDataForThisThread(); 541 per_thread->set_stack_limit(thread_local_.real_climit_); 542 } 543 544 545 void StackGuard::ThreadLocal::Clear() { 546 real_jslimit_ = kIllegalLimit; 547 jslimit_ = kIllegalLimit; 548 real_climit_ = kIllegalLimit; 549 climit_ = kIllegalLimit; 550 nesting_ = 0; 551 postpone_interrupts_nesting_ = 0; 552 interrupt_flags_ = 0; 553 } 554 555 556 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) { 557 bool should_set_stack_limits = false; 558 if (real_climit_ == kIllegalLimit) { 559 // Takes the address of the limit variable in order to find out where 560 // the top of stack is right now. 561 const uintptr_t kLimitSize = FLAG_stack_size * KB; 562 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize; 563 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize); 564 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); 565 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); 566 real_climit_ = limit; 567 climit_ = limit; 568 should_set_stack_limits = true; 569 } 570 nesting_ = 0; 571 postpone_interrupts_nesting_ = 0; 572 interrupt_flags_ = 0; 573 return should_set_stack_limits; 574 } 575 576 577 void StackGuard::ClearThread(const ExecutionAccess& lock) { 578 thread_local_.Clear(); 579 isolate_->heap()->SetStackLimits(); 580 } 581 582 583 void StackGuard::InitThread(const ExecutionAccess& lock) { 584 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits(); 585 Isolate::PerIsolateThreadData* per_thread = 586 isolate_->FindOrAllocatePerThreadDataForThisThread(); 587 uintptr_t stored_limit = per_thread->stack_limit(); 588 // You should hold the ExecutionAccess lock when you call this. 589 if (stored_limit != 0) { 590 SetStackLimit(stored_limit); 591 } 592 } 593 594 595 // --- C a l l s t o n a t i v e s --- 596 597 #define RETURN_NATIVE_CALL(name, args, has_pending_exception) \ 598 do { \ 599 Isolate* isolate = Isolate::Current(); \ 600 Handle<Object> argv[] = args; \ 601 ASSERT(has_pending_exception != NULL); \ 602 return Call(isolate->name##_fun(), \ 603 isolate->js_builtins_object(), \ 604 ARRAY_SIZE(argv), argv, \ 605 has_pending_exception); \ 606 } while (false) 607 608 609 Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) { 610 RETURN_NATIVE_CALL(to_number, { obj }, exc); 611 } 612 613 614 Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) { 615 RETURN_NATIVE_CALL(to_string, { obj }, exc); 616 } 617 618 619 Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) { 620 RETURN_NATIVE_CALL(to_detail_string, { obj }, exc); 621 } 622 623 624 Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) { 625 if (obj->IsSpecObject()) return obj; 626 RETURN_NATIVE_CALL(to_object, { obj }, exc); 627 } 628 629 630 Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) { 631 RETURN_NATIVE_CALL(to_integer, { obj }, exc); 632 } 633 634 635 Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) { 636 RETURN_NATIVE_CALL(to_uint32, { obj }, exc); 637 } 638 639 640 Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) { 641 RETURN_NATIVE_CALL(to_int32, { obj }, exc); 642 } 643 644 645 Handle<Object> Execution::NewDate(double time, bool* exc) { 646 Isolate* isolate = Isolate::Current(); 647 Handle<Object> time_obj = isolate->factory()->NewNumber(time); 648 RETURN_NATIVE_CALL(create_date, { time_obj }, exc); 649 } 650 651 652 #undef RETURN_NATIVE_CALL 653 654 655 Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern, 656 Handle<String> flags, 657 bool* exc) { 658 Handle<JSFunction> function = Handle<JSFunction>( 659 pattern->GetIsolate()->native_context()->regexp_function()); 660 Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral( 661 function, pattern, flags, exc); 662 if (*exc) return Handle<JSRegExp>(); 663 return Handle<JSRegExp>::cast(re_obj); 664 } 665 666 667 Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) { 668 Isolate* isolate = string->GetIsolate(); 669 Factory* factory = isolate->factory(); 670 671 int int_index = static_cast<int>(index); 672 if (int_index < 0 || int_index >= string->length()) { 673 return factory->undefined_value(); 674 } 675 676 Handle<Object> char_at = GetProperty( 677 isolate, isolate->js_builtins_object(), factory->char_at_string()); 678 if (!char_at->IsJSFunction()) { 679 return factory->undefined_value(); 680 } 681 682 bool caught_exception; 683 Handle<Object> index_object = factory->NewNumberFromInt(int_index); 684 Handle<Object> index_arg[] = { index_object }; 685 Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at), 686 string, 687 ARRAY_SIZE(index_arg), 688 index_arg, 689 &caught_exception); 690 if (caught_exception) { 691 return factory->undefined_value(); 692 } 693 return result; 694 } 695 696 697 Handle<JSFunction> Execution::InstantiateFunction( 698 Handle<FunctionTemplateInfo> data, 699 bool* exc) { 700 Isolate* isolate = data->GetIsolate(); 701 // Fast case: see if the function has already been instantiated 702 int serial_number = Smi::cast(data->serial_number())->value(); 703 Object* elm = 704 isolate->native_context()->function_cache()-> 705 GetElementNoExceptionThrown(serial_number); 706 if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm)); 707 // The function has not yet been instantiated in this context; do it. 708 Handle<Object> args[] = { data }; 709 Handle<Object> result = Call(isolate->instantiate_fun(), 710 isolate->js_builtins_object(), 711 ARRAY_SIZE(args), 712 args, 713 exc); 714 if (*exc) return Handle<JSFunction>::null(); 715 return Handle<JSFunction>::cast(result); 716 } 717 718 719 Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data, 720 bool* exc) { 721 Isolate* isolate = data->GetIsolate(); 722 if (data->property_list()->IsUndefined() && 723 !data->constructor()->IsUndefined()) { 724 // Initialization to make gcc happy. 725 Object* result = NULL; 726 { 727 HandleScope scope(isolate); 728 Handle<FunctionTemplateInfo> cons_template = 729 Handle<FunctionTemplateInfo>( 730 FunctionTemplateInfo::cast(data->constructor())); 731 Handle<JSFunction> cons = InstantiateFunction(cons_template, exc); 732 if (*exc) return Handle<JSObject>::null(); 733 Handle<Object> value = New(cons, 0, NULL, exc); 734 if (*exc) return Handle<JSObject>::null(); 735 result = *value; 736 } 737 ASSERT(!*exc); 738 return Handle<JSObject>(JSObject::cast(result)); 739 } else { 740 Handle<Object> args[] = { data }; 741 Handle<Object> result = Call(isolate->instantiate_fun(), 742 isolate->js_builtins_object(), 743 ARRAY_SIZE(args), 744 args, 745 exc); 746 if (*exc) return Handle<JSObject>::null(); 747 return Handle<JSObject>::cast(result); 748 } 749 } 750 751 752 void Execution::ConfigureInstance(Handle<Object> instance, 753 Handle<Object> instance_template, 754 bool* exc) { 755 Isolate* isolate = Isolate::Current(); 756 Handle<Object> args[] = { instance, instance_template }; 757 Execution::Call(isolate->configure_instance_fun(), 758 isolate->js_builtins_object(), 759 ARRAY_SIZE(args), 760 args, 761 exc); 762 } 763 764 765 Handle<String> Execution::GetStackTraceLine(Handle<Object> recv, 766 Handle<JSFunction> fun, 767 Handle<Object> pos, 768 Handle<Object> is_global) { 769 Isolate* isolate = fun->GetIsolate(); 770 Handle<Object> args[] = { recv, fun, pos, is_global }; 771 bool caught_exception; 772 Handle<Object> result = TryCall(isolate->get_stack_trace_line_fun(), 773 isolate->js_builtins_object(), 774 ARRAY_SIZE(args), 775 args, 776 &caught_exception); 777 if (caught_exception || !result->IsString()) { 778 return isolate->factory()->empty_string(); 779 } 780 781 return Handle<String>::cast(result); 782 } 783 784 785 static Object* RuntimePreempt() { 786 Isolate* isolate = Isolate::Current(); 787 788 // Clear the preempt request flag. 789 isolate->stack_guard()->Continue(PREEMPT); 790 791 ContextSwitcher::PreemptionReceived(); 792 793 #ifdef ENABLE_DEBUGGER_SUPPORT 794 if (isolate->debug()->InDebugger()) { 795 // If currently in the debugger don't do any actual preemption but record 796 // that preemption occoured while in the debugger. 797 isolate->debug()->PreemptionWhileInDebugger(); 798 } else { 799 // Perform preemption. 800 v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate)); 801 Thread::YieldCPU(); 802 } 803 #else 804 { // NOLINT 805 // Perform preemption. 806 v8::Unlocker unlocker(reinterpret_cast<v8::Isolate*>(isolate)); 807 Thread::YieldCPU(); 808 } 809 #endif 810 811 return isolate->heap()->undefined_value(); 812 } 813 814 815 #ifdef ENABLE_DEBUGGER_SUPPORT 816 Object* Execution::DebugBreakHelper() { 817 Isolate* isolate = Isolate::Current(); 818 819 // Just continue if breaks are disabled. 820 if (isolate->debug()->disable_break()) { 821 return isolate->heap()->undefined_value(); 822 } 823 824 // Ignore debug break during bootstrapping. 825 if (isolate->bootstrapper()->IsActive()) { 826 return isolate->heap()->undefined_value(); 827 } 828 829 // Ignore debug break if debugger is not active. 830 if (!isolate->debugger()->IsDebuggerActive()) { 831 return isolate->heap()->undefined_value(); 832 } 833 834 StackLimitCheck check(isolate); 835 if (check.HasOverflowed()) { 836 return isolate->heap()->undefined_value(); 837 } 838 839 { 840 JavaScriptFrameIterator it(isolate); 841 ASSERT(!it.done()); 842 Object* fun = it.frame()->function(); 843 if (fun && fun->IsJSFunction()) { 844 // Don't stop in builtin functions. 845 if (JSFunction::cast(fun)->IsBuiltin()) { 846 return isolate->heap()->undefined_value(); 847 } 848 GlobalObject* global = JSFunction::cast(fun)->context()->global_object(); 849 // Don't stop in debugger functions. 850 if (isolate->debug()->IsDebugGlobal(global)) { 851 return isolate->heap()->undefined_value(); 852 } 853 } 854 } 855 856 // Collect the break state before clearing the flags. 857 bool debug_command_only = 858 isolate->stack_guard()->IsDebugCommand() && 859 !isolate->stack_guard()->IsDebugBreak(); 860 861 // Clear the debug break request flag. 862 isolate->stack_guard()->Continue(DEBUGBREAK); 863 864 ProcessDebugMessages(debug_command_only); 865 866 // Return to continue execution. 867 return isolate->heap()->undefined_value(); 868 } 869 870 871 void Execution::ProcessDebugMessages(bool debug_command_only) { 872 Isolate* isolate = Isolate::Current(); 873 // Clear the debug command request flag. 874 isolate->stack_guard()->Continue(DEBUGCOMMAND); 875 876 StackLimitCheck check(isolate); 877 if (check.HasOverflowed()) { 878 return; 879 } 880 881 HandleScope scope(isolate); 882 // Enter the debugger. Just continue if we fail to enter the debugger. 883 EnterDebugger debugger; 884 if (debugger.FailedToEnter()) { 885 return; 886 } 887 888 // Notify the debug event listeners. Indicate auto continue if the break was 889 // a debug command break. 890 isolate->debugger()->OnDebugBreak(isolate->factory()->undefined_value(), 891 debug_command_only); 892 } 893 894 895 #endif 896 897 MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) { 898 StackGuard* stack_guard = isolate->stack_guard(); 899 if (stack_guard->ShouldPostponeInterrupts()) { 900 return isolate->heap()->undefined_value(); 901 } 902 903 if (stack_guard->IsGCRequest()) { 904 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, 905 "StackGuard GC request"); 906 stack_guard->Continue(GC_REQUEST); 907 } 908 909 isolate->counters()->stack_interrupts()->Increment(); 910 isolate->counters()->runtime_profiler_ticks()->Increment(); 911 isolate->runtime_profiler()->OptimizeNow(); 912 #ifdef ENABLE_DEBUGGER_SUPPORT 913 if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) { 914 DebugBreakHelper(); 915 } 916 #endif 917 if (stack_guard->IsPreempted()) RuntimePreempt(); 918 if (stack_guard->IsTerminateExecution()) { 919 stack_guard->Continue(TERMINATE); 920 return isolate->TerminateExecution(); 921 } 922 if (stack_guard->IsInterrupted()) { 923 stack_guard->Continue(INTERRUPT); 924 return isolate->StackOverflow(); 925 } 926 if (stack_guard->IsFullDeopt()) { 927 stack_guard->Continue(FULL_DEOPT); 928 Deoptimizer::DeoptimizeAll(isolate); 929 } 930 return isolate->heap()->undefined_value(); 931 } 932 933 934 } } // namespace v8::internal 935