📄 execution.cc.svn-base
字号:
// Copyright 2006-2008 the V8 project authors. All rights reserved.// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following// disclaimer in the documentation and/or other materials provided// with the distribution.// * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived// from this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include <stdlib.h>#include "v8.h"#include "api.h"#include "codegen-inl.h"#if defined(ARM) || defined (__arm__) || defined(__thumb__)#include "simulator-arm.h"#else // ia32#include "simulator-ia32.h"#endifnamespace v8 { namespace internal {static Handle<Object> Invoke(bool construct, Handle<JSFunction> func, Handle<Object> receiver, int argc, Object*** args, bool* has_pending_exception) { // Make sure we have a real function, not a boilerplate function. ASSERT(!func->IsBoilerplate()); // Entering JavaScript. VMState state(JS); // Guard the stack against too much recursion. StackGuard guard; // Placeholder for return value. Object* value = reinterpret_cast<Object*>(kZapValue); typedef Object* (*JSEntryFunction)( byte* entry, Object* function, Object* receiver, int argc, Object*** args); Handle<Code> code; if (construct) { JSConstructEntryStub stub; code = stub.GetCode(); } else { JSEntryStub stub; code = stub.GetCode(); } { // Save and restore context around invocation and block the // allocation of handles without explicit handle scopes. SaveContext save; NoHandleAllocation na; JSEntryFunction entry = FUNCTION_CAST<JSEntryFunction>(code->entry()); // Call the function through the right JS entry stub. value = CALL_GENERATED_CODE(entry, func->code()->entry(), *func, *receiver, argc, args); }#ifdef DEBUG value->Verify();#endif // Update the pending exception flag and return the value. *has_pending_exception = value->IsException(); ASSERT(*has_pending_exception == Top::has_pending_exception()); // If the pending exception is OutOfMemoryException set out_of_memory in // the global context. Note: We have to mark the global context here // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to // set it. if (*has_pending_exception) { if (Top::pending_exception() == Failure::OutOfMemoryException()) { Top::context()->mark_out_of_memory(); } } return Handle<Object>(value);}Handle<Object> Execution::Call(Handle<JSFunction> func, Handle<Object> receiver, int argc, Object*** args, bool* pending_exception) { return Invoke(false, func, receiver, argc, args, pending_exception);}Handle<Object> Execution::New(Handle<JSFunction> func, int argc, Object*** args, bool* pending_exception) { return Invoke(true, func, Top::global(), argc, args, pending_exception);}Handle<Object> Execution::TryCall(Handle<JSFunction> func, Handle<Object> receiver, int argc, Object*** args, bool* caught_exception) { // Enter a try-block while executing the JavaScript code. To avoid // duplicate error printing it must be non-verbose. Also, to avoid // creating message objects during stack overflow we shouldn't // capture messages. v8::TryCatch catcher; catcher.SetVerbose(false); catcher.SetCaptureMessage(false); Handle<Object> result = Invoke(false, func, receiver, argc, args, caught_exception); if (*caught_exception) { ASSERT(catcher.HasCaught()); ASSERT(Top::has_pending_exception()); ASSERT(Top::external_caught_exception()); Top::optional_reschedule_exception(true); result = v8::Utils::OpenHandle(*catcher.Exception()); } ASSERT(!Top::has_pending_exception()); ASSERT(!Top::external_caught_exception()); return result;}Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) { ASSERT(!object->IsJSFunction()); // If you return a function from here, it will be called when an // attempt is made to call the given object as a function. // The regular expression code here is really meant more as an // example than anything else. KJS does not support calling regular // expressions as functions, but SpiderMonkey does. if (FLAG_call_regexp) { bool is_regexp = object->IsHeapObject() && (HeapObject::cast(*object)->map()->constructor() == *Top::regexp_function()); if (is_regexp) { Handle<String> exec = Factory::exec_symbol(); return Handle<Object>(object->GetProperty(*exec)); } } // Objects created through the API can have an instance-call handler // that should be used when calling the object as a function. if (object->IsHeapObject() && HeapObject::cast(*object)->map()->has_instance_call_handler()) { return Handle<JSFunction>( Top::global_context()->call_as_function_delegate()); } return Factory::undefined_value();}// Static state for stack guards.StackGuard::ThreadLocal StackGuard::thread_local_;StackGuard::StackGuard() { ExecutionAccess access; if (thread_local_.nesting_++ == 0 && thread_local_.jslimit_ != kInterruptLimit) { // NOTE: We assume that the stack grows towards lower addresses. ASSERT(thread_local_.jslimit_ == kIllegalLimit); ASSERT(thread_local_.climit_ == kIllegalLimit); thread_local_.initial_jslimit_ = thread_local_.jslimit_ = GENERATED_CODE_STACK_LIMIT(kLimitSize); // NOTE: The check for overflow is not safe as there is no guarantee that // the running thread has its stack in all memory up to address 0x00000000. thread_local_.initial_climit_ = thread_local_.climit_ = reinterpret_cast<uintptr_t>(this) >= kLimitSize ? reinterpret_cast<uintptr_t>(this) - kLimitSize : 0; if (thread_local_.interrupt_flags_ != 0) { set_limits(kInterruptLimit, access); } } // make sure we have proper limits setup ASSERT(thread_local_.jslimit_ != kIllegalLimit && thread_local_.climit_ != kIllegalLimit);}StackGuard::~StackGuard() { ExecutionAccess access; if (--thread_local_.nesting_ == 0) { set_limits(kIllegalLimit, access); }}bool StackGuard::IsStackOverflow() { ExecutionAccess access; return (thread_local_.jslimit_ != kInterruptLimit && thread_local_.climit_ != kInterruptLimit);}void StackGuard::EnableInterrupts() { ExecutionAccess access; if (IsSet(access)) { set_limits(kInterruptLimit, access); }}void StackGuard::SetStackLimit(uintptr_t limit) { ExecutionAccess access; // If the current limits are special (eg due to a pending interrupt) then // leave them alone. if (thread_local_.jslimit_ == thread_local_.initial_jslimit_) { thread_local_.jslimit_ = limit; } if (thread_local_.climit_ == thread_local_.initial_climit_) { thread_local_.climit_ = limit; } thread_local_.initial_climit_ = limit; thread_local_.initial_jslimit_ = limit;}void StackGuard::DisableInterrupts() { ExecutionAccess access; reset_limits(access);}bool StackGuard::IsSet(const ExecutionAccess& lock) { return thread_local_.interrupt_flags_ != 0;}bool StackGuard::IsInterrupted() { ExecutionAccess access; return thread_local_.interrupt_flags_ & INTERRUPT;}void StackGuard::Interrupt() { ExecutionAccess access; thread_local_.interrupt_flags_ |= INTERRUPT; set_limits(kInterruptLimit, access);}bool StackGuard::IsPreempted() { ExecutionAccess access; return thread_local_.interrupt_flags_ & PREEMPT;}void StackGuard::Preempt() { ExecutionAccess access; thread_local_.interrupt_flags_ |= PREEMPT; set_limits(kInterruptLimit, access);}bool StackGuard::IsDebugBreak() { ExecutionAccess access; return thread_local_.interrupt_flags_ & DEBUGBREAK;}void StackGuard::DebugBreak() { ExecutionAccess access; thread_local_.interrupt_flags_ |= DEBUGBREAK; set_limits(kInterruptLimit, access);}void StackGuard::Continue(InterruptFlag after_what) { ExecutionAccess access; thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what); if (thread_local_.interrupt_flags_ == 0) { reset_limits(access); }}int StackGuard::ArchiveSpacePerThread() { return sizeof(ThreadLocal);}char* StackGuard::ArchiveStackGuard(char* to) { ExecutionAccess access; memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); ThreadLocal blank; thread_local_ = blank; return to + sizeof(ThreadLocal);}char* StackGuard::RestoreStackGuard(char* from) { ExecutionAccess access; memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); return from + sizeof(ThreadLocal);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -