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 "isolate-inl.h" 37 #include "runtime-profiler.h" 38 #include "simulator.h" 39 #include "v8threads.h" 40 #include "vm-state-inl.h" 41 42 namespace v8 { 43 namespace internal { 44 45 46 StackGuard::StackGuard() 47 : isolate_(NULL) { 48 } 49 50 51 void StackGuard::set_interrupt_limits(const ExecutionAccess& lock) { 52 ASSERT(isolate_ != NULL); 53 // Ignore attempts to interrupt when interrupts are postponed. 54 if (should_postpone_interrupts(lock)) return; 55 thread_local_.jslimit_ = kInterruptLimit; 56 thread_local_.climit_ = kInterruptLimit; 57 isolate_->heap()->SetStackLimits(); 58 } 59 60 61 void StackGuard::reset_limits(const ExecutionAccess& lock) { 62 ASSERT(isolate_ != NULL); 63 thread_local_.jslimit_ = thread_local_.real_jslimit_; 64 thread_local_.climit_ = thread_local_.real_climit_; 65 isolate_->heap()->SetStackLimits(); 66 } 67 68 69 static Handle<Object> Invoke(bool is_construct, 70 Handle<JSFunction> function, 71 Handle<Object> receiver, 72 int argc, 73 Handle<Object> args[], 74 bool* has_pending_exception) { 75 Isolate* isolate = function->GetIsolate(); 76 77 // Entering JavaScript. 78 VMState state(isolate, JS); 79 80 // Placeholder for return value. 81 MaybeObject* value = reinterpret_cast<Object*>(kZapValue); 82 83 typedef Object* (*JSEntryFunction)(byte* entry, 84 Object* function, 85 Object* receiver, 86 int argc, 87 Object*** args); 88 89 Handle<Code> code = is_construct 90 ? isolate->factory()->js_construct_entry_code() 91 : isolate->factory()->js_entry_code(); 92 93 // Convert calls on global objects to be calls on the global 94 // receiver instead to avoid having a 'this' pointer which refers 95 // directly to a global object. 96 if (receiver->IsGlobalObject()) { 97 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); 98 receiver = Handle<JSObject>(global->global_receiver()); 99 } 100 101 // Make sure that the global object of the context we're about to 102 // make the current one is indeed a global object. 103 ASSERT(function->context()->global()->IsGlobalObject()); 104 105 { 106 // Save and restore context around invocation and block the 107 // allocation of handles without explicit handle scopes. 108 SaveContext save(isolate); 109 NoHandleAllocation na; 110 JSEntryFunction stub_entry = FUNCTION_CAST<JSEntryFunction>(code->entry()); 111 112 // Call the function through the right JS entry stub. 113 byte* function_entry = function->code()->entry(); 114 JSFunction* func = *function; 115 Object* recv = *receiver; 116 Object*** argv = reinterpret_cast<Object***>(args); 117 value = 118 CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv); 119 } 120 121 #ifdef DEBUG 122 value->Verify(); 123 #endif 124 125 // Update the pending exception flag and return the value. 126 *has_pending_exception = value->IsException(); 127 ASSERT(*has_pending_exception == Isolate::Current()->has_pending_exception()); 128 if (*has_pending_exception) { 129 isolate->ReportPendingMessages(); 130 if (isolate->pending_exception() == Failure::OutOfMemoryException()) { 131 if (!isolate->ignore_out_of_memory()) { 132 V8::FatalProcessOutOfMemory("JS", true); 133 } 134 } 135 return Handle<Object>(); 136 } else { 137 isolate->clear_pending_message(); 138 } 139 140 return Handle<Object>(value->ToObjectUnchecked(), isolate); 141 } 142 143 144 Handle<Object> Execution::Call(Handle<Object> callable, 145 Handle<Object> receiver, 146 int argc, 147 Handle<Object> argv[], 148 bool* pending_exception, 149 bool convert_receiver) { 150 *pending_exception = false; 151 152 if (!callable->IsJSFunction()) { 153 callable = TryGetFunctionDelegate(callable, pending_exception); 154 if (*pending_exception) return callable; 155 } 156 Handle<JSFunction> func = Handle<JSFunction>::cast(callable); 157 158 // In non-strict mode, convert receiver. 159 if (convert_receiver && !receiver->IsJSReceiver() && 160 !func->shared()->native() && func->shared()->is_classic_mode()) { 161 if (receiver->IsUndefined() || receiver->IsNull()) { 162 Object* global = func->context()->global()->global_receiver(); 163 // Under some circumstances, 'global' can be the JSBuiltinsObject 164 // In that case, don't rewrite. 165 // (FWIW, the same holds for GetIsolate()->global()->global_receiver().) 166 if (!global->IsJSBuiltinsObject()) receiver = Handle<Object>(global); 167 } else { 168 receiver = ToObject(receiver, pending_exception); 169 } 170 if (*pending_exception) return callable; 171 } 172 173 return Invoke(false, func, receiver, argc, argv, pending_exception); 174 } 175 176 177 Handle<Object> Execution::New(Handle<JSFunction> func, 178 int argc, 179 Handle<Object> argv[], 180 bool* pending_exception) { 181 return Invoke(true, func, Isolate::Current()->global(), argc, argv, 182 pending_exception); 183 } 184 185 186 Handle<Object> Execution::TryCall(Handle<JSFunction> func, 187 Handle<Object> receiver, 188 int argc, 189 Handle<Object> args[], 190 bool* caught_exception) { 191 // Enter a try-block while executing the JavaScript code. To avoid 192 // duplicate error printing it must be non-verbose. Also, to avoid 193 // creating message objects during stack overflow we shouldn't 194 // capture messages. 195 v8::TryCatch catcher; 196 catcher.SetVerbose(false); 197 catcher.SetCaptureMessage(false); 198 *caught_exception = false; 199 200 Handle<Object> result = Invoke(false, func, receiver, argc, args, 201 caught_exception); 202 203 if (*caught_exception) { 204 ASSERT(catcher.HasCaught()); 205 Isolate* isolate = Isolate::Current(); 206 ASSERT(isolate->has_pending_exception()); 207 ASSERT(isolate->external_caught_exception()); 208 if (isolate->pending_exception() == 209 isolate->heap()->termination_exception()) { 210 result = isolate->factory()->termination_exception(); 211 } else { 212 result = v8::Utils::OpenHandle(*catcher.Exception()); 213 } 214 isolate->OptionalRescheduleException(true); 215 } 216 217 ASSERT(!Isolate::Current()->has_pending_exception()); 218 ASSERT(!Isolate::Current()->external_caught_exception()); 219 return result; 220 } 221 222 223 Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) { 224 ASSERT(!object->IsJSFunction()); 225 Isolate* isolate = Isolate::Current(); 226 Factory* factory = isolate->factory(); 227 228 // If you return a function from here, it will be called when an 229 // attempt is made to call the given object as a function. 230 231 // If object is a function proxy, get its handler. Iterate if necessary. 232 Object* fun = *object; 233 while (fun->IsJSFunctionProxy()) { 234 fun = JSFunctionProxy::cast(fun)->call_trap(); 235 } 236 if (fun->IsJSFunction()) return Handle<Object>(fun); 237 238 // Objects created through the API can have an instance-call handler 239 // that should be used when calling the object as a function. 240 if (fun->IsHeapObject() && 241 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 242 return Handle<JSFunction>( 243 isolate->global_context()->call_as_function_delegate()); 244 } 245 246 return factory->undefined_value(); 247 } 248 249 250 Handle<Object> Execution::TryGetFunctionDelegate(Handle<Object> object, 251 bool* has_pending_exception) { 252 ASSERT(!object->IsJSFunction()); 253 Isolate* isolate = Isolate::Current(); 254 255 // If object is a function proxy, 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); 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->global_context()->call_as_function_delegate()); 268 } 269 270 // If the Object doesn't have an instance-call handler we should 271 // throw a non-callable exception. 272 i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( 273 "called_non_callable", i::HandleVector<i::Object>(&object, 1)); 274 isolate->Throw(*error_obj); 275 *has_pending_exception = true; 276 277 return isolate->factory()->undefined_value(); 278 } 279 280 281 Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) { 282 ASSERT(!object->IsJSFunction()); 283 Isolate* isolate = Isolate::Current(); 284 285 // If you return a function from here, it will be called when an 286 // attempt is made to call the given object as a constructor. 287 288 // If object is a function proxies, get its handler. Iterate if necessary. 289 Object* fun = *object; 290 while (fun->IsJSFunctionProxy()) { 291 fun = JSFunctionProxy::cast(fun)->call_trap(); 292 } 293 if (fun->IsJSFunction()) return Handle<Object>(fun); 294 295 // Objects created through the API can have an instance-call handler 296 // that should be used when calling the object as a function. 297 if (fun->IsHeapObject() && 298 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 299 return Handle<JSFunction>( 300 isolate->global_context()->call_as_constructor_delegate()); 301 } 302 303 return isolate->factory()->undefined_value(); 304 } 305 306 307 Handle<Object> Execution::TryGetConstructorDelegate( 308 Handle<Object> object, 309 bool* has_pending_exception) { 310 ASSERT(!object->IsJSFunction()); 311 Isolate* isolate = Isolate::Current(); 312 313 // If you return a function from here, it will be called when an 314 // attempt is made to call the given object as a constructor. 315 316 // If object is a function proxies, get its handler. Iterate if necessary. 317 Object* fun = *object; 318 while (fun->IsJSFunctionProxy()) { 319 fun = JSFunctionProxy::cast(fun)->call_trap(); 320 } 321 if (fun->IsJSFunction()) return Handle<Object>(fun); 322 323 // Objects created through the API can have an instance-call handler 324 // that should be used when calling the object as a function. 325 if (fun->IsHeapObject() && 326 HeapObject::cast(fun)->map()->has_instance_call_handler()) { 327 return Handle<JSFunction>( 328 isolate->global_context()->call_as_constructor_delegate()); 329 } 330 331 // If the Object doesn't have an instance-call handler we should 332 // throw a non-callable exception. 333 i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( 334 "called_non_callable", i::HandleVector<i::Object>(&object, 1)); 335 isolate->Throw(*error_obj); 336 *has_pending_exception = true; 337 338 return isolate->factory()->undefined_value(); 339 } 340 341 342 bool StackGuard::IsStackOverflow() { 343 ExecutionAccess access(isolate_); 344 return (thread_local_.jslimit_ != kInterruptLimit && 345 thread_local_.climit_ != kInterruptLimit); 346 } 347 348 349 void StackGuard::EnableInterrupts() { 350 ExecutionAccess access(isolate_); 351 if (has_pending_interrupts(access)) { 352 set_interrupt_limits(access); 353 } 354 } 355 356 357 void StackGuard::SetStackLimit(uintptr_t limit) { 358 ExecutionAccess access(isolate_); 359 // If the current limits are special (e.g. due to a pending interrupt) then 360 // leave them alone. 361 uintptr_t jslimit = SimulatorStack::JsLimitFromCLimit(isolate_, limit); 362 if (thread_local_.jslimit_ == thread_local_.real_jslimit_) { 363 thread_local_.jslimit_ = jslimit; 364 } 365 if (thread_local_.climit_ == thread_local_.real_climit_) { 366 thread_local_.climit_ = limit; 367 } 368 thread_local_.real_climit_ = limit; 369 thread_local_.real_jslimit_ = jslimit; 370 } 371 372 373 void StackGuard::DisableInterrupts() { 374 ExecutionAccess access(isolate_); 375 reset_limits(access); 376 } 377 378 379 bool StackGuard::ShouldPostponeInterrupts() { 380 ExecutionAccess access(isolate_); 381 return should_postpone_interrupts(access); 382 } 383 384 385 bool StackGuard::IsInterrupted() { 386 ExecutionAccess access(isolate_); 387 return (thread_local_.interrupt_flags_ & INTERRUPT) != 0; 388 } 389 390 391 void StackGuard::Interrupt() { 392 ExecutionAccess access(isolate_); 393 thread_local_.interrupt_flags_ |= INTERRUPT; 394 set_interrupt_limits(access); 395 } 396 397 398 bool StackGuard::IsPreempted() { 399 ExecutionAccess access(isolate_); 400 return thread_local_.interrupt_flags_ & PREEMPT; 401 } 402 403 404 void StackGuard::Preempt() { 405 ExecutionAccess access(isolate_); 406 thread_local_.interrupt_flags_ |= PREEMPT; 407 set_interrupt_limits(access); 408 } 409 410 411 bool StackGuard::IsTerminateExecution() { 412 ExecutionAccess access(isolate_); 413 return (thread_local_.interrupt_flags_ & TERMINATE) != 0; 414 } 415 416 417 void StackGuard::TerminateExecution() { 418 ExecutionAccess access(isolate_); 419 thread_local_.interrupt_flags_ |= TERMINATE; 420 set_interrupt_limits(access); 421 } 422 423 424 bool StackGuard::IsRuntimeProfilerTick() { 425 ExecutionAccess access(isolate_); 426 return (thread_local_.interrupt_flags_ & RUNTIME_PROFILER_TICK) != 0; 427 } 428 429 430 void StackGuard::RequestRuntimeProfilerTick() { 431 // Ignore calls if we're not optimizing or if we can't get the lock. 432 if (FLAG_opt && ExecutionAccess::TryLock(isolate_)) { 433 thread_local_.interrupt_flags_ |= RUNTIME_PROFILER_TICK; 434 if (thread_local_.postpone_interrupts_nesting_ == 0) { 435 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit; 436 isolate_->heap()->SetStackLimits(); 437 } 438 ExecutionAccess::Unlock(isolate_); 439 } 440 } 441 442 443 bool StackGuard::IsGCRequest() { 444 ExecutionAccess access(isolate_); 445 return (thread_local_.interrupt_flags_ & GC_REQUEST) != 0; 446 } 447 448 449 void StackGuard::RequestGC() { 450 ExecutionAccess access(isolate_); 451 thread_local_.interrupt_flags_ |= GC_REQUEST; 452 if (thread_local_.postpone_interrupts_nesting_ == 0) { 453 thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit; 454 isolate_->heap()->SetStackLimits(); 455 } 456 } 457 458 459 #ifdef ENABLE_DEBUGGER_SUPPORT 460 bool StackGuard::IsDebugBreak() { 461 ExecutionAccess access(isolate_); 462 return thread_local_.interrupt_flags_ & DEBUGBREAK; 463 } 464 465 466 void StackGuard::DebugBreak() { 467 ExecutionAccess access(isolate_); 468 thread_local_.interrupt_flags_ |= DEBUGBREAK; 469 set_interrupt_limits(access); 470 } 471 472 473 bool StackGuard::IsDebugCommand() { 474 ExecutionAccess access(isolate_); 475 return thread_local_.interrupt_flags_ & DEBUGCOMMAND; 476 } 477 478 479 void StackGuard::DebugCommand() { 480 if (FLAG_debugger_auto_break) { 481 ExecutionAccess access(isolate_); 482 thread_local_.interrupt_flags_ |= DEBUGCOMMAND; 483 set_interrupt_limits(access); 484 } 485 } 486 #endif 487 488 void StackGuard::Continue(InterruptFlag after_what) { 489 ExecutionAccess access(isolate_); 490 thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what); 491 if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) { 492 reset_limits(access); 493 } 494 } 495 496 497 char* StackGuard::ArchiveStackGuard(char* to) { 498 ExecutionAccess access(isolate_); 499 memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); 500 ThreadLocal blank; 501 502 // Set the stack limits using the old thread_local_. 503 // TODO(isolates): This was the old semantics of constructing a ThreadLocal 504 // (as the ctor called SetStackLimits, which looked at the 505 // current thread_local_ from StackGuard)-- but is this 506 // really what was intended? 507 isolate_->heap()->SetStackLimits(); 508 thread_local_ = blank; 509 510 return to + sizeof(ThreadLocal); 511 } 512 513 514 char* StackGuard::RestoreStackGuard(char* from) { 515 ExecutionAccess access(isolate_); 516 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); 517 isolate_->heap()->SetStackLimits(); 518 return from + sizeof(ThreadLocal); 519 } 520 521 522 void StackGuard::FreeThreadResources() { 523 Isolate::PerIsolateThreadData* per_thread = 524 isolate_->FindOrAllocatePerThreadDataForThisThread(); 525 per_thread->set_stack_limit(thread_local_.real_climit_); 526 } 527 528 529 void StackGuard::ThreadLocal::Clear() { 530 real_jslimit_ = kIllegalLimit; 531 jslimit_ = kIllegalLimit; 532 real_climit_ = kIllegalLimit; 533 climit_ = kIllegalLimit; 534 nesting_ = 0; 535 postpone_interrupts_nesting_ = 0; 536 interrupt_flags_ = 0; 537 } 538 539 540 bool StackGuard::ThreadLocal::Initialize(Isolate* isolate) { 541 bool should_set_stack_limits = false; 542 if (real_climit_ == kIllegalLimit) { 543 // Takes the address of the limit variable in order to find out where 544 // the top of stack is right now. 545 const uintptr_t kLimitSize = FLAG_stack_size * KB; 546 uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize; 547 ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize); 548 real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); 549 jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit); 550 real_climit_ = limit; 551 climit_ = limit; 552 should_set_stack_limits = true; 553 } 554 nesting_ = 0; 555 postpone_interrupts_nesting_ = 0; 556 interrupt_flags_ = 0; 557 return should_set_stack_limits; 558 } 559 560 561 void StackGuard::ClearThread(const ExecutionAccess& lock) { 562 thread_local_.Clear(); 563 isolate_->heap()->SetStackLimits(); 564 } 565 566 567 void StackGuard::InitThread(const ExecutionAccess& lock) { 568 if (thread_local_.Initialize(isolate_)) isolate_->heap()->SetStackLimits(); 569 Isolate::PerIsolateThreadData* per_thread = 570 isolate_->FindOrAllocatePerThreadDataForThisThread(); 571 uintptr_t stored_limit = per_thread->stack_limit(); 572 // You should hold the ExecutionAccess lock when you call this. 573 if (stored_limit != 0) { 574 SetStackLimit(stored_limit); 575 } 576 } 577 578 579 // --- C a l l s t o n a t i v e s --- 580 581 #define RETURN_NATIVE_CALL(name, args, has_pending_exception) \ 582 do { \ 583 Isolate* isolate = Isolate::Current(); \ 584 Handle<Object> argv[] = args; \ 585 ASSERT(has_pending_exception != NULL); \ 586 return Call(isolate->name##_fun(), \ 587 isolate->js_builtins_object(), \ 588 ARRAY_SIZE(argv), argv, \ 589 has_pending_exception); \ 590 } while (false) 591 592 593 Handle<Object> Execution::ToBoolean(Handle<Object> obj) { 594 // See the similar code in runtime.js:ToBoolean. 595 if (obj->IsBoolean()) return obj; 596 bool result = true; 597 if (obj->IsString()) { 598 result = Handle<String>::cast(obj)->length() != 0; 599 } else if (obj->IsNull() || obj->IsUndefined()) { 600 result = false; 601 } else if (obj->IsNumber()) { 602 double value = obj->Number(); 603 result = !((value == 0) || isnan(value)); 604 } 605 return Handle<Object>(HEAP->ToBoolean(result)); 606 } 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 Handle<Object> time_obj = FACTORY->NewNumber(time); 647 RETURN_NATIVE_CALL(create_date, { time_obj }, exc); 648 } 649 650 651 #undef RETURN_NATIVE_CALL 652 653 654 Handle<JSRegExp> Execution::NewJSRegExp(Handle<String> pattern, 655 Handle<String> flags, 656 bool* exc) { 657 Handle<JSFunction> function = Handle<JSFunction>( 658 pattern->GetIsolate()->global_context()->regexp_function()); 659 Handle<Object> re_obj = RegExpImpl::CreateRegExpLiteral( 660 function, pattern, flags, exc); 661 if (*exc) return Handle<JSRegExp>(); 662 return Handle<JSRegExp>::cast(re_obj); 663 } 664 665 666 Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) { 667 Isolate* isolate = string->GetIsolate(); 668 Factory* factory = isolate->factory(); 669 670 int int_index = static_cast<int>(index); 671 if (int_index < 0 || int_index >= string->length()) { 672 return factory->undefined_value(); 673 } 674 675 Handle<Object> char_at = 676 GetProperty(isolate->js_builtins_object(), 677 factory->char_at_symbol()); 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->global_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_symbol(); 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 StackLimitCheck check(isolate); 830 if (check.HasOverflowed()) { 831 return isolate->heap()->undefined_value(); 832 } 833 834 { 835 JavaScriptFrameIterator it(isolate); 836 ASSERT(!it.done()); 837 Object* fun = it.frame()->function(); 838 if (fun && fun->IsJSFunction()) { 839 // Don't stop in builtin functions. 840 if (JSFunction::cast(fun)->IsBuiltin()) { 841 return isolate->heap()->undefined_value(); 842 } 843 GlobalObject* global = JSFunction::cast(fun)->context()->global(); 844 // Don't stop in debugger functions. 845 if (isolate->debug()->IsDebugGlobal(global)) { 846 return isolate->heap()->undefined_value(); 847 } 848 } 849 } 850 851 // Collect the break state before clearing the flags. 852 bool debug_command_only = 853 isolate->stack_guard()->IsDebugCommand() && 854 !isolate->stack_guard()->IsDebugBreak(); 855 856 // Clear the debug break request flag. 857 isolate->stack_guard()->Continue(DEBUGBREAK); 858 859 ProcessDebugMessages(debug_command_only); 860 861 // Return to continue execution. 862 return isolate->heap()->undefined_value(); 863 } 864 865 void Execution::ProcessDebugMessages(bool debug_command_only) { 866 Isolate* isolate = Isolate::Current(); 867 // Clear the debug command request flag. 868 isolate->stack_guard()->Continue(DEBUGCOMMAND); 869 870 StackLimitCheck check(isolate); 871 if (check.HasOverflowed()) { 872 return; 873 } 874 875 HandleScope scope(isolate); 876 // Enter the debugger. Just continue if we fail to enter the debugger. 877 EnterDebugger debugger; 878 if (debugger.FailedToEnter()) { 879 return; 880 } 881 882 // Notify the debug event listeners. Indicate auto continue if the break was 883 // a debug command break. 884 isolate->debugger()->OnDebugBreak(isolate->factory()->undefined_value(), 885 debug_command_only); 886 } 887 888 889 #endif 890 891 MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) { 892 StackGuard* stack_guard = isolate->stack_guard(); 893 if (stack_guard->ShouldPostponeInterrupts()) { 894 return isolate->heap()->undefined_value(); 895 } 896 897 if (stack_guard->IsGCRequest()) { 898 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, 899 "StackGuard GC request"); 900 stack_guard->Continue(GC_REQUEST); 901 } 902 903 isolate->counters()->stack_interrupts()->Increment(); 904 // If FLAG_count_based_interrupts, every interrupt is a profiler interrupt. 905 if (FLAG_count_based_interrupts || 906 stack_guard->IsRuntimeProfilerTick()) { 907 isolate->counters()->runtime_profiler_ticks()->Increment(); 908 stack_guard->Continue(RUNTIME_PROFILER_TICK); 909 isolate->runtime_profiler()->OptimizeNow(); 910 } 911 #ifdef ENABLE_DEBUGGER_SUPPORT 912 if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) { 913 DebugBreakHelper(); 914 } 915 #endif 916 if (stack_guard->IsPreempted()) RuntimePreempt(); 917 if (stack_guard->IsTerminateExecution()) { 918 stack_guard->Continue(TERMINATE); 919 return isolate->TerminateExecution(); 920 } 921 if (stack_guard->IsInterrupted()) { 922 stack_guard->Continue(INTERRUPT); 923 return isolate->StackOverflow(); 924 } 925 return isolate->heap()->undefined_value(); 926 } 927 928 929 } } // namespace v8::internal 930