summaryrefslogtreecommitdiffstats
path: root/v8/src/execution.cc
diff options
context:
space:
mode:
Diffstat (limited to 'v8/src/execution.cc')
-rw-r--r--v8/src/execution.cc647
1 files changed, 0 insertions, 647 deletions
diff --git a/v8/src/execution.cc b/v8/src/execution.cc
deleted file mode 100644
index be04a5b..0000000
--- a/v8/src/execution.cc
+++ /dev/null
@@ -1,647 +0,0 @@
-// 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"
-
-#ifdef ARM
-#include "simulator-arm.h"
-#else // ia32
-#include "simulator-ia32.h"
-#endif
-
-#include "debug.h"
-#include "v8threads.h"
-
-namespace 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 (*has_pending_exception) {
- Top::ReportPendingMessages();
- return Handle<Object>();
- } else {
- Top::clear_pending_message();
- }
-
- 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() {
- // NOTE: Overall the StackGuard code assumes that the stack grows towards
- // lower addresses.
- ExecutionAccess access;
- if (thread_local_.nesting_++ == 0) {
- // Initial StackGuard is being set. We will set the stack limits based on
- // the current stack pointer allowing the stack to grow kLimitSize from
- // here.
-
- // Ensure that either the stack limits are unset (kIllegalLimit) or that
- // they indicate a pending interruption. The interrupt limit will be
- // temporarily reset through the code below and reestablished if the
- // interrupt flags indicate that an interrupt is pending.
- ASSERT(thread_local_.jslimit_ == kIllegalLimit ||
- (thread_local_.jslimit_ == kInterruptLimit &&
- thread_local_.interrupt_flags_ != 0));
- ASSERT(thread_local_.climit_ == kIllegalLimit ||
- (thread_local_.climit_ == kInterruptLimit &&
- thread_local_.interrupt_flags_ != 0));
-
- 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);
- }
- }
- // Ensure that proper limits have been set.
- ASSERT(thread_local_.jslimit_ != kIllegalLimit &&
- thread_local_.climit_ != kIllegalLimit);
- ASSERT(thread_local_.initial_jslimit_ != kIllegalLimit &&
- thread_local_.initial_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);
-}
-
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
-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);
-}
-
-
-bool StackGuard::IsDebugCommand() {
- ExecutionAccess access;
- return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
-}
-
-
-void StackGuard::DebugCommand() {
- if (FLAG_debugger_auto_break) {
- ExecutionAccess access;
- thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
- set_limits(kInterruptLimit, access);
- }
-}
-#endif
-
-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);
-}
-
-
-// --- C a l l s t o n a t i v e s ---
-
-#define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \
- do { \
- Object** args[argc] = argv; \
- ASSERT(has_pending_exception != NULL); \
- return Call(Top::name##_fun(), Top::builtins(), argc, args, \
- has_pending_exception); \
- } while (false)
-
-
-Handle<Object> Execution::ToBoolean(Handle<Object> obj) {
- // See the similar code in runtime.js:ToBoolean.
- if (obj->IsBoolean()) return obj;
- bool result = true;
- if (obj->IsString()) {
- result = Handle<String>::cast(obj)->length() != 0;
- } else if (obj->IsNull() || obj->IsUndefined()) {
- result = false;
- } else if (obj->IsNumber()) {
- double value = obj->Number();
- result = !((value == 0) || isnan(value));
- }
- return Handle<Object>(Heap::ToBoolean(result));
-}
-
-
-Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) {
- RETURN_NATIVE_CALL(to_number, 1, { obj.location() }, exc);
-}
-
-
-Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) {
- RETURN_NATIVE_CALL(to_string, 1, { obj.location() }, exc);
-}
-
-
-Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) {
- RETURN_NATIVE_CALL(to_detail_string, 1, { obj.location() }, exc);
-}
-
-
-Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) {
- if (obj->IsJSObject()) return obj;
- RETURN_NATIVE_CALL(to_object, 1, { obj.location() }, exc);
-}
-
-
-Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) {
- RETURN_NATIVE_CALL(to_integer, 1, { obj.location() }, exc);
-}
-
-
-Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) {
- RETURN_NATIVE_CALL(to_uint32, 1, { obj.location() }, exc);
-}
-
-
-Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {
- RETURN_NATIVE_CALL(to_int32, 1, { obj.location() }, exc);
-}
-
-
-Handle<Object> Execution::NewDate(double time, bool* exc) {
- Handle<Object> time_obj = Factory::NewNumber(time);
- RETURN_NATIVE_CALL(create_date, 1, { time_obj.location() }, exc);
-}
-
-
-#undef RETURN_NATIVE_CALL
-
-
-Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
- int int_index = static_cast<int>(index);
- if (int_index < 0 || int_index >= string->length()) {
- return Factory::undefined_value();
- }
-
- Handle<Object> char_at =
- GetProperty(Top::builtins(), Factory::char_at_symbol());
- if (!char_at->IsJSFunction()) {
- return Factory::undefined_value();
- }
-
- bool caught_exception;
- Handle<Object> index_object = Factory::NewNumberFromInt(int_index);
- Object** index_arg[] = { index_object.location() };
- Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
- string,
- ARRAY_SIZE(index_arg),
- index_arg,
- &caught_exception);
- if (caught_exception) {
- return Factory::undefined_value();
- }
- return result;
-}
-
-
-Handle<JSFunction> Execution::InstantiateFunction(
- Handle<FunctionTemplateInfo> data, bool* exc) {
- // Fast case: see if the function has already been instantiated
- int serial_number = Smi::cast(data->serial_number())->value();
- Object* elm =
- Top::global_context()->function_cache()->GetElement(serial_number);
- if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
- // The function has not yet been instantiated in this context; do it.
- Object** args[1] = { Handle<Object>::cast(data).location() };
- Handle<Object> result =
- Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
- if (*exc) return Handle<JSFunction>::null();
- return Handle<JSFunction>::cast(result);
-}
-
-
-Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
- bool* exc) {
- if (data->property_list()->IsUndefined() &&
- !data->constructor()->IsUndefined()) {
- // Initialization to make gcc happy.
- Object* result = NULL;
- {
- HandleScope scope;
- Handle<FunctionTemplateInfo> cons_template =
- Handle<FunctionTemplateInfo>(
- FunctionTemplateInfo::cast(data->constructor()));
- Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
- if (*exc) return Handle<JSObject>::null();
- Handle<Object> value = New(cons, 0, NULL, exc);
- if (*exc) return Handle<JSObject>::null();
- result = *value;
- }
- ASSERT(!*exc);
- return Handle<JSObject>(JSObject::cast(result));
- } else {
- Object** args[1] = { Handle<Object>::cast(data).location() };
- Handle<Object> result =
- Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
- if (*exc) return Handle<JSObject>::null();
- return Handle<JSObject>::cast(result);
- }
-}
-
-
-void Execution::ConfigureInstance(Handle<Object> instance,
- Handle<Object> instance_template,
- bool* exc) {
- Object** args[2] = { instance.location(), instance_template.location() };
- Execution::Call(Top::configure_instance_fun(), Top::builtins(), 2, args, exc);
-}
-
-
-Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
- Handle<JSFunction> fun,
- Handle<Object> pos,
- Handle<Object> is_global) {
- const int argc = 4;
- Object** args[argc] = { recv.location(),
- Handle<Object>::cast(fun).location(),
- pos.location(),
- is_global.location() };
- bool caught_exception = false;
- Handle<Object> result = TryCall(Top::get_stack_trace_line_fun(),
- Top::builtins(), argc, args,
- &caught_exception);
- if (caught_exception || !result->IsString()) return Factory::empty_symbol();
- return Handle<String>::cast(result);
-}
-
-
-static Object* RuntimePreempt() {
- // Clear the preempt request flag.
- StackGuard::Continue(PREEMPT);
-
- ContextSwitcher::PreemptionReceived();
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
- if (Debug::InDebugger()) {
- // If currently in the debugger don't do any actual preemption but record
- // that preemption occoured while in the debugger.
- Debug::PreemptionWhileInDebugger();
- } else {
- // Perform preemption.
- v8::Unlocker unlocker;
- Thread::YieldCPU();
- }
-#else
- // Perform preemption.
- v8::Unlocker unlocker;
- Thread::YieldCPU();
-#endif
-
- return Heap::undefined_value();
-}
-
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
-Object* Execution::DebugBreakHelper() {
- // Just continue if breaks are disabled.
- if (Debug::disable_break()) {
- return Heap::undefined_value();
- }
-
- // Don't break in system functions. If the current function is
- // either in the builtins object of some context or is in the debug
- // context just return with the debug break stack guard active.
- JavaScriptFrameIterator it;
- JavaScriptFrame* frame = it.frame();
- Object* fun = frame->function();
- if (fun->IsJSFunction()) {
- GlobalObject* global = JSFunction::cast(fun)->context()->global();
- if (global->IsJSBuiltinsObject() || Debug::IsDebugGlobal(global)) {
- return Heap::undefined_value();
- }
- }
-
- // Check for debug command break only.
- bool debug_command_only =
- StackGuard::IsDebugCommand() && !StackGuard::IsDebugBreak();
-
- // Clear the debug request flags.
- StackGuard::Continue(DEBUGBREAK);
- StackGuard::Continue(DEBUGCOMMAND);
-
- // If debug command only and already in debugger ignore it.
- if (debug_command_only && Debug::InDebugger()) {
- return Heap::undefined_value();
- }
-
- HandleScope scope;
- // Enter the debugger. Just continue if we fail to enter the debugger.
- EnterDebugger debugger;
- if (debugger.FailedToEnter()) {
- return Heap::undefined_value();
- }
-
- // Notify the debug event listeners.
- Debugger::OnDebugBreak(Factory::undefined_value(), debug_command_only);
-
- // Return to continue execution.
- return Heap::undefined_value();
-}
-#endif
-
-Object* Execution::HandleStackGuardInterrupt() {
-#ifdef ENABLE_DEBUGGER_SUPPORT
- if (StackGuard::IsDebugBreak() || StackGuard::IsDebugCommand()) {
- DebugBreakHelper();
- }
-#endif
- if (StackGuard::IsPreempted()) RuntimePreempt();
- if (StackGuard::IsInterrupted()) {
- // interrupt
- StackGuard::Continue(INTERRUPT);
- return Top::StackOverflow();
- }
- return Heap::undefined_value();
-}
-
-// --- G C E x t e n s i o n ---
-
-const char* GCExtension::kSource = "native function gc();";
-
-
-v8::Handle<v8::FunctionTemplate> GCExtension::GetNativeFunction(
- v8::Handle<v8::String> str) {
- return v8::FunctionTemplate::New(GCExtension::GC);
-}
-
-
-v8::Handle<v8::Value> GCExtension::GC(const v8::Arguments& args) {
- // All allocation spaces other than NEW_SPACE have the same effect.
- Heap::CollectGarbage(0, OLD_DATA_SPACE);
- return v8::Undefined();
-}
-
-
-static GCExtension kGCExtension;
-v8::DeclareExtension kGCExtensionDeclaration(&kGCExtension);
-
-} } // namespace v8::internal