Permalink
Browse files

Upgrade v8 to 1.3.6

  • Loading branch information...
1 parent 90ac9ab commit 048a1b8b9e5184f959ce924e76c61f8cd9e91089 @ry ry committed Aug 21, 2009
View
@@ -1,3 +1,19 @@
+2009-08-21: Version 1.3.6
+
+ Add support for forceful termination of JavaScript execution.
+
+ Add low memory notification to the API. The embedding host can signal
+ a low memory situation to V8.
+
+ Changed the handling of global handles (persistent handles in the API
+ sense) to avoid issues regarding allocation of new global handles
+ during weak handle callbacks.
+
+ Changed the growth policy of the young space.
+
+ Fixed a GC issue introduced in version 1.3.5.
+
+
2009-08-19: Version 1.3.5
Optimize initialization of some arrays in the builtins.
View
@@ -2223,6 +2223,47 @@ class V8EXPORT V8 {
*/
static int GetLogLines(int from_pos, char* dest_buf, int max_size);
+ /**
+ * Retrieve the V8 thread id of the calling thread.
+ *
+ * The thread id for a thread should only be retrieved after the V8
+ * lock has been acquired with a Locker object with that thread.
+ */
+ static int GetCurrentThreadId();
+
+ /**
+ * Forcefully terminate execution of a JavaScript thread. This can
+ * be used to terminate long-running scripts.
+ *
+ * TerminateExecution should only be called when then V8 lock has
+ * been acquired with a Locker object. Therefore, in order to be
+ * able to terminate long-running threads, preemption must be
+ * enabled to allow the user of TerminateExecution to acquire the
+ * lock.
+ *
+ * The termination is achieved by throwing an exception that is
+ * uncatchable by JavaScript exception handlers. Termination
+ * exceptions act as if they were caught by a C++ TryCatch exception
+ * handlers. If forceful termination is used, any C++ TryCatch
+ * exception handler that catches an exception should check if that
+ * exception is a termination exception and immediately return if
+ * that is the case. Returning immediately in that case will
+ * continue the propagation of the termination exception if needed.
+ *
+ * The thread id passed to TerminateExecution must have been
+ * obtained by calling GetCurrentThreadId on the thread in question.
+ *
+ * \param thread_id The thread id of the thread to terminate.
+ */
+ static void TerminateExecution(int thread_id);
+
+ /**
+ * Forcefully terminate the current thread of JavaScript execution.
+ *
+ * This method can be used by any thread even if that thread has not
+ * acquired the V8 lock with a Locker object.
+ */
+ static void TerminateExecution();
/**
* Releases any resources used by v8 and stops any utility threads
@@ -2243,6 +2284,12 @@ class V8EXPORT V8 {
*/
static void IdleNotification(bool is_high_priority);
+ /**
+ * Optional notification that the system is running low on memory.
+ * V8 uses these notifications to attempt to free memory.
+ */
+ static void LowMemoryNotification();
+
private:
V8();
@@ -2282,6 +2329,21 @@ class V8EXPORT TryCatch {
bool HasCaught() const;
/**
+ * For certain types of exceptions, it makes no sense to continue
+ * execution.
+ *
+ * Currently, the only type of exception that can be caught by a
+ * TryCatch handler and for which it does not make sense to continue
+ * is termination exception. Such exceptions are thrown when the
+ * TerminateExecution methods are called to terminate a long-running
+ * script.
+ *
+ * If CanContinue returns false, the correct action is to perform
+ * any C++ cleanup needed and then return.
+ */
+ bool CanContinue() const;
+
+ /**
* Returns the exception caught by this try/catch block. If no exception has
* been caught an empty handle is returned.
*
@@ -2337,6 +2399,7 @@ class V8EXPORT TryCatch {
void* exception_;
void* message_;
bool is_verbose_;
+ bool can_continue_;
bool capture_message_;
void* js_handler_;
};
View
@@ -75,7 +75,7 @@ namespace v8 {
i::V8::FatalProcessOutOfMemory(NULL); \
} \
bool call_depth_is_zero = thread_local.CallDepthIsZero(); \
- i::Top::optional_reschedule_exception(call_depth_is_zero); \
+ i::Top::OptionalRescheduleException(call_depth_is_zero, false); \
return value; \
} \
} while (false)
@@ -1208,6 +1208,11 @@ bool v8::TryCatch::HasCaught() const {
}
+bool v8::TryCatch::CanContinue() const {
+ return can_continue_;
+}
+
+
v8::Local<Value> v8::TryCatch::Exception() const {
if (HasCaught()) {
// Check for out of memory exception.
@@ -2599,10 +2604,18 @@ bool v8::V8::Dispose() {
}
-void v8::V8::IdleNotification(bool is_high_priority) {
+void v8::V8::IdleNotification(bool is_high_priority) {
i::V8::IdleNotification(is_high_priority);
}
+
+void v8::V8::LowMemoryNotification() {
+#if defined(ANDROID)
+ i::Heap::CollectAllGarbage(true);
+#endif
+}
+
+
const char* v8::V8::GetVersion() {
static v8::internal::EmbeddedVector<char, 128> buffer;
v8::internal::Version::GetString(buffer);
@@ -3354,6 +3367,34 @@ int V8::GetLogLines(int from_pos, char* dest_buf, int max_size) {
return 0;
}
+
+int V8::GetCurrentThreadId() {
+ API_ENTRY_CHECK("V8::GetCurrentThreadId()");
+ EnsureInitialized("V8::GetCurrentThreadId()");
+ return i::Top::thread_id();
+}
+
+
+void V8::TerminateExecution(int thread_id) {
+ if (!i::V8::IsRunning()) return;
+ API_ENTRY_CHECK("V8::GetCurrentThreadId()");
+ // If the thread_id identifies the current thread just terminate
+ // execution right away. Otherwise, ask the thread manager to
+ // terminate the thread with the given id if any.
+ if (thread_id == i::Top::thread_id()) {
+ i::StackGuard::TerminateExecution();
+ } else {
+ i::ThreadManager::TerminateExecution(thread_id);
+ }
+}
+
+
+void V8::TerminateExecution() {
+ if (!i::V8::IsRunning()) return;
+ i::StackGuard::TerminateExecution();
+}
+
+
String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
if (obj.IsEmpty()) {
@@ -5701,7 +5701,8 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
}
-void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
+void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm,
+ UncatchableExceptionType type) {
// Adjust this code if not the case.
ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
@@ -5725,20 +5726,22 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
// Set the top handler address to next handler past the current ENTRY handler.
ASSERT(StackHandlerConstants::kNextOffset == 0);
- __ pop(r0);
- __ str(r0, MemOperand(r3));
-
- // Set external caught exception to false.
- ExternalReference external_caught(Top::k_external_caught_exception_address);
- __ mov(r0, Operand(false));
- __ mov(r2, Operand(external_caught));
- __ str(r0, MemOperand(r2));
+ __ pop(r2);
+ __ str(r2, MemOperand(r3));
- // Set pending exception and r0 to out of memory exception.
- Failure* out_of_memory = Failure::OutOfMemoryException();
- __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
- __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address)));
- __ str(r0, MemOperand(r2));
+ if (type == OUT_OF_MEMORY) {
+ // Set external caught exception to false.
+ ExternalReference external_caught(Top::k_external_caught_exception_address);
+ __ mov(r0, Operand(false));
+ __ mov(r2, Operand(external_caught));
+ __ str(r0, MemOperand(r2));
+
+ // Set pending exception and r0 to out of memory exception.
+ Failure* out_of_memory = Failure::OutOfMemoryException();
+ __ mov(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
+ __ mov(r2, Operand(ExternalReference(Top::k_pending_exception_address)));
+ __ str(r0, MemOperand(r2));
+ }
// Stack layout at this point. See also StackHandlerConstants.
// sp -> state (ENTRY)
@@ -5768,6 +5771,7 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
void CEntryStub::GenerateCore(MacroAssembler* masm,
Label* throw_normal_exception,
+ Label* throw_termination_exception,
Label* throw_out_of_memory_exception,
StackFrame::Type frame_type,
bool do_gc,
@@ -5838,10 +5842,10 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
__ tst(r0, Operand(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
__ b(eq, &retry);
- Label continue_exception;
- // If the returned failure is EXCEPTION then promote Top::pending_exception().
- __ cmp(r0, Operand(reinterpret_cast<int32_t>(Failure::Exception())));
- __ b(ne, &continue_exception);
+ // Special handling of out of memory exceptions.
+ Failure* out_of_memory = Failure::OutOfMemoryException();
+ __ cmp(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
+ __ b(eq, throw_out_of_memory_exception);
// Retrieve the pending exception and clear the variable.
__ mov(ip, Operand(ExternalReference::the_hole_value_location()));
@@ -5850,11 +5854,10 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
__ ldr(r0, MemOperand(ip));
__ str(r3, MemOperand(ip));
- __ bind(&continue_exception);
- // Special handling of out of memory exception.
- Failure* out_of_memory = Failure::OutOfMemoryException();
- __ cmp(r0, Operand(reinterpret_cast<int32_t>(out_of_memory)));
- __ b(eq, throw_out_of_memory_exception);
+ // Special handling of termination exceptions which are uncatchable
+ // by javascript code.
+ __ cmp(r0, Operand(Factory::termination_exception()));
+ __ b(eq, throw_termination_exception);
// Handle normal exception.
__ jmp(throw_normal_exception);
@@ -5887,11 +5890,14 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
// r5: pointer to builtin function (C callee-saved)
// r6: pointer to first argument (C callee-saved)
- Label throw_out_of_memory_exception;
Label throw_normal_exception;
+ Label throw_termination_exception;
+ Label throw_out_of_memory_exception;
// Call into the runtime system.
- GenerateCore(masm, &throw_normal_exception,
+ GenerateCore(masm,
+ &throw_normal_exception,
+ &throw_termination_exception,
&throw_out_of_memory_exception,
frame_type,
false,
@@ -5900,6 +5906,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
// Do space-specific GC and retry runtime call.
GenerateCore(masm,
&throw_normal_exception,
+ &throw_termination_exception,
&throw_out_of_memory_exception,
frame_type,
true,
@@ -5910,14 +5917,17 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
__ mov(r0, Operand(reinterpret_cast<int32_t>(failure)));
GenerateCore(masm,
&throw_normal_exception,
+ &throw_termination_exception,
&throw_out_of_memory_exception,
frame_type,
true,
true);
__ bind(&throw_out_of_memory_exception);
- GenerateThrowOutOfMemory(masm);
- // control flow for generated will not return.
+ GenerateThrowUncatchable(masm, OUT_OF_MEMORY);
+
+ __ bind(&throw_termination_exception);
+ GenerateThrowUncatchable(masm, TERMINATION);
__ bind(&throw_normal_exception);
GenerateThrowTOS(masm);
View
@@ -70,6 +70,9 @@
// Mode to overwrite BinaryExpression values.
enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
+// Types of uncatchable exceptions.
+enum UncatchableExceptionType { OUT_OF_MEMORY, TERMINATION };
+
#if V8_TARGET_ARCH_IA32
#include "ia32/codegen-ia32.h"
@@ -291,12 +294,14 @@ class CEntryStub : public CodeStub {
void GenerateBody(MacroAssembler* masm, bool is_debug_break);
void GenerateCore(MacroAssembler* masm,
Label* throw_normal_exception,
+ Label* throw_termination_exception,
Label* throw_out_of_memory_exception,
StackFrame::Type frame_type,
bool do_gc,
bool always_allocate_scope);
void GenerateThrowTOS(MacroAssembler* masm);
- void GenerateThrowOutOfMemory(MacroAssembler* masm);
+ void GenerateThrowUncatchable(MacroAssembler* masm,
+ UncatchableExceptionType type);
private:
Major MajorKey() { return CEntry; }
View
@@ -156,7 +156,8 @@ Handle<Object> Execution::TryCall(Handle<JSFunction> func,
ASSERT(catcher.HasCaught());
ASSERT(Top::has_pending_exception());
ASSERT(Top::external_caught_exception());
- Top::optional_reschedule_exception(true);
+ bool is_bottom_call = HandleScopeImplementer::instance()->CallDepthIsZero();
+ Top::OptionalRescheduleException(is_bottom_call, true);
result = v8::Utils::OpenHandle(*catcher.Exception());
}
@@ -328,6 +329,19 @@ void StackGuard::Preempt() {
}
+bool StackGuard::IsTerminateExecution() {
+ ExecutionAccess access;
+ return thread_local_.interrupt_flags_ & TERMINATE;
+}
+
+
+void StackGuard::TerminateExecution() {
+ ExecutionAccess access;
+ thread_local_.interrupt_flags_ |= TERMINATE;
+ set_limits(kInterruptLimit, access);
+}
+
+
#ifdef ENABLE_DEBUGGER_SUPPORT
bool StackGuard::IsDebugBreak() {
ExecutionAccess access;
@@ -638,6 +652,10 @@ Object* Execution::HandleStackGuardInterrupt() {
}
#endif
if (StackGuard::IsPreempted()) RuntimePreempt();
+ if (StackGuard::IsTerminateExecution()) {
+ StackGuard::Continue(TERMINATE);
+ return Top::TerminateExecution();
+ }
if (StackGuard::IsInterrupted()) {
// interrupt
StackGuard::Continue(INTERRUPT);
Oops, something went wrong.

0 comments on commit 048a1b8

Please sign in to comment.