Browse Source

Upgrade v8 to 1.3.6

v0.7.4-release
Ryan 16 years ago
parent
commit
048a1b8b9e
  1. 16
      deps/v8/ChangeLog
  2. 63
      deps/v8/include/v8.h
  3. 45
      deps/v8/src/api.cc
  4. 64
      deps/v8/src/arm/codegen-arm.cc
  5. 7
      deps/v8/src/codegen.h
  6. 20
      deps/v8/src/execution.cc
  7. 11
      deps/v8/src/execution.h
  8. 36
      deps/v8/src/global-handles.cc
  9. 19
      deps/v8/src/heap.cc
  10. 26
      deps/v8/src/heap.h
  11. 54
      deps/v8/src/ia32/codegen-ia32.cc
  12. 3
      deps/v8/src/mark-compact.cc
  13. 10
      deps/v8/src/mark-compact.h
  14. 6
      deps/v8/src/messages.cc
  15. 3
      deps/v8/src/objects-debug.cc
  16. 1
      deps/v8/src/objects-inl.h
  17. 3
      deps/v8/src/scanner.cc
  18. 4
      deps/v8/src/scanner.h
  19. 4
      deps/v8/src/spaces.cc
  20. 2
      deps/v8/src/third_party/dtoa/dtoa.c
  21. 61
      deps/v8/src/top.cc
  22. 12
      deps/v8/src/top.h
  23. 1
      deps/v8/src/v8.cc
  24. 21
      deps/v8/src/v8threads.cc
  25. 9
      deps/v8/src/v8threads.h
  26. 2
      deps/v8/src/version.cc
  27. 64
      deps/v8/src/x64/codegen-x64.cc
  28. 1
      deps/v8/test/cctest/SConscript
  29. 78
      deps/v8/test/cctest/test-api.cc
  30. 195
      deps/v8/test/cctest/test-thread-termination.cc
  31. 2
      deps/v8/test/cctest/test-threads.cc
  32. 6
      deps/v8/test/mozilla/mozilla.status
  33. 22
      deps/v8/tools/gyp/v8.gyp

16
deps/v8/ChangeLog

@ -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.

63
deps/v8/include/v8.h

@ -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();
@ -2281,6 +2328,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_;
};

45
deps/v8/src/api.cc

@ -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()) {

64
deps/v8/src/arm/codegen-arm.cc

@ -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);

7
deps/v8/src/codegen.h

@ -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; }

20
deps/v8/src/execution.cc

@ -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);

11
deps/v8/src/execution.h

@ -37,7 +37,8 @@ enum InterruptFlag {
INTERRUPT = 1 << 0,
DEBUGBREAK = 1 << 1,
DEBUGCOMMAND = 1 << 2,
PREEMPT = 1 << 3
PREEMPT = 1 << 3,
TERMINATE = 1 << 4
};
class Execution : public AllStatic {
@ -164,13 +165,15 @@ class StackGuard BASE_EMBEDDED {
static void Preempt();
static bool IsInterrupted();
static void Interrupt();
static void Continue(InterruptFlag after_what);
static bool IsTerminateExecution();
static void TerminateExecution();
#ifdef ENABLE_DEBUGGER_SUPPORT
static void DebugBreak();
static void DebugCommand();
static bool IsDebugBreak();
static void DebugBreak();
static bool IsDebugCommand();
static void DebugCommand();
#endif
static void Continue(InterruptFlag after_what);
private:
// You should hold the ExecutionAccess lock when calling this method.

36
deps/v8/src/global-handles.cc

@ -144,8 +144,8 @@ class GlobalHandles::Node : public Malloced {
// Returns the callback for this weak handle.
WeakReferenceCallback callback() { return callback_; }
void PostGarbageCollectionProcessing() {
if (state_ != Node::PENDING) return;
bool PostGarbageCollectionProcessing() {
if (state_ != Node::PENDING) return false;
LOG(HandleEvent("GlobalHandle::Processing", handle().location()));
void* par = parameter();
state_ = NEAR_DEATH;
@ -153,14 +153,19 @@ class GlobalHandles::Node : public Malloced {
// The callback function is resolved as late as possible to preserve old
// behavior.
WeakReferenceCallback func = callback();
if (func != NULL) {
v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle());
{
// Leaving V8.
VMState state(EXTERNAL);
func(object, par);
}
if (func == NULL) return false;
v8::Persistent<v8::Object> object = ToApi<v8::Object>(handle());
{
// Forbid reuse of destroyed nodes as they might be already deallocated.
// It's fine though to reuse nodes that were destroyed in weak callback
// as those cannot be deallocated until we are back from the callback.
set_first_free(NULL);
// Leaving V8.
VMState state(EXTERNAL);
func(object, par);
}
return true;
}
// Place the handle address first to avoid offset computation.
@ -271,15 +276,26 @@ void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) {
}
int post_gc_processing_count = 0;
void GlobalHandles::PostGarbageCollectionProcessing() {
// Process weak global handle callbacks. This must be done after the
// GC is completely done, because the callbacks may invoke arbitrary
// API functions.
// At the same time deallocate all DESTROYED nodes
ASSERT(Heap::gc_state() == Heap::NOT_IN_GC);
const int initial_post_gc_processing_count = ++post_gc_processing_count;
Node** p = &head_;
while (*p != NULL) {
(*p)->PostGarbageCollectionProcessing();
if ((*p)->PostGarbageCollectionProcessing()) {
if (initial_post_gc_processing_count != post_gc_processing_count) {
// Weak callback triggered another GC and another round of
// PostGarbageCollection processing. The current node might
// have been deleted in that round, so we need to bail out (or
// restart the processing).
break;
}
}
if ((*p)->state_ == Node::DESTROYED) {
// Delete the link.
Node* node = *p;

19
deps/v8/src/heap.cc

@ -73,7 +73,7 @@ int Heap::amount_of_external_allocated_memory_at_last_global_gc_ = 0;
int Heap::semispace_size_ = 512*KB;
int Heap::old_generation_size_ = 128*MB;
int Heap::initial_semispace_size_ = 128*KB;
#elseif defined(V8_TARGET_ARCH_X64)
#elif defined(V8_TARGET_ARCH_X64)
int Heap::semispace_size_ = 8*MB;
int Heap::old_generation_size_ = 1*GB;
int Heap::initial_semispace_size_ = 1*MB;
@ -315,11 +315,13 @@ void Heap::GarbageCollectionEpilogue() {
}
void Heap::CollectAllGarbage() {
void Heap::CollectAllGarbage(bool force_compaction) {
// Since we are ignoring the return value, the exact choice of space does
// not matter, so long as we do not specify NEW_SPACE, which would not
// cause a full GC.
MarkCompactCollector::SetForceCompaction(force_compaction);
CollectGarbage(0, OLD_POINTER_SPACE);
MarkCompactCollector::SetForceCompaction(false);
}
@ -485,7 +487,10 @@ void Heap::PerformGarbageCollection(AllocationSpace space,
void Heap::PostGarbageCollectionProcessing() {
// Process weak handles post gc.
GlobalHandles::PostGarbageCollectionProcessing();
{
DisableAssertNoAllocation allow_allocation;
GlobalHandles::PostGarbageCollectionProcessing();
}
// Update flat string readers.
FlatStringReader::PostGarbageCollectionProcessing();
}
@ -1412,6 +1417,9 @@ bool Heap::CreateInitialObjects() {
if (obj->IsFailure()) return false;
set_no_interceptor_result_sentinel(obj);
obj = CreateOddball(oddball_map(), "termination_exception", Smi::FromInt(-3));
if (obj->IsFailure()) return false;
set_termination_exception(obj);
// Allocate the empty string.
obj = AllocateRawAsciiString(0, TENURED);
@ -2084,8 +2092,9 @@ Object* Heap::AllocateInitialMap(JSFunction* fun) {
if (count > in_object_properties) {
count = in_object_properties;
}
DescriptorArray* descriptors = *Factory::NewDescriptorArray(count);
if (descriptors->IsFailure()) return descriptors;
Object* descriptors_obj = DescriptorArray::Allocate(count);
if (descriptors_obj->IsFailure()) return descriptors_obj;
DescriptorArray* descriptors = DescriptorArray::cast(descriptors_obj);
for (int i = 0; i < count; i++) {
String* name = fun->shared()->GetThisPropertyAssignmentName(i);
ASSERT(name->IsSymbol());

26
deps/v8/src/heap.h

@ -111,6 +111,7 @@ namespace internal {
V(Object, nan_value, NanValue) \
V(Object, undefined_value, UndefinedValue) \
V(Object, no_interceptor_result_sentinel, NoInterceptorResultSentinel) \
V(Object, termination_exception, TerminationException) \
V(Object, minus_zero_value, MinusZeroValue) \
V(Object, null_value, NullValue) \
V(Object, true_value, TrueValue) \
@ -626,8 +627,9 @@ class Heap : public AllStatic {
// Returns whether required_space bytes are available after the collection.
static bool CollectGarbage(int required_space, AllocationSpace space);
// Performs a full garbage collection.
static void CollectAllGarbage();
// Performs a full garbage collection. Force compaction if the
// parameter is true.
static void CollectAllGarbage(bool force_compaction = false);
// Performs a full garbage collection if a context has been disposed
// since the last time the check was performed.
@ -1386,6 +1388,20 @@ class AssertNoAllocation {
bool old_state_;
};
class DisableAssertNoAllocation {
public:
DisableAssertNoAllocation() {
old_state_ = Heap::allow_allocation(true);
}
~DisableAssertNoAllocation() {
Heap::allow_allocation(old_state_);
}
private:
bool old_state_;
};
#else // ndef DEBUG
class AssertNoAllocation {
@ -1394,6 +1410,12 @@ class AssertNoAllocation {
~AssertNoAllocation() { }
};
class DisableAssertNoAllocation {
public:
DisableAssertNoAllocation() { }
~DisableAssertNoAllocation() { }
};
#endif
#ifdef ENABLE_LOGGING_AND_PROFILING

54
deps/v8/src/ia32/codegen-ia32.cc

@ -7505,6 +7505,7 @@ void CEntryStub::GenerateThrowTOS(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,
@ -7568,10 +7569,9 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
__ test(eax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
__ j(zero, &retry, taken);
Label continue_exception;
// If the returned failure is EXCEPTION then promote Top::pending_exception().
__ cmp(eax, reinterpret_cast<int32_t>(Failure::Exception()));
__ j(not_equal, &continue_exception);
// Special handling of out of memory exceptions.
__ cmp(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
__ j(equal, throw_out_of_memory_exception);
// Retrieve the pending exception and clear the variable.
ExternalReference pending_exception_address(Top::k_pending_exception_address);
@ -7580,10 +7580,10 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
Operand::StaticVariable(ExternalReference::the_hole_value_location()));
__ mov(Operand::StaticVariable(pending_exception_address), edx);
__ bind(&continue_exception);
// Special handling of out of memory exception.
__ cmp(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
__ j(equal, throw_out_of_memory_exception);
// Special handling of termination exceptions which are uncatchable
// by javascript code.
__ cmp(eax, Factory::termination_exception());
__ j(equal, throw_termination_exception);
// Handle normal exception.
__ jmp(throw_normal_exception);
@ -7593,7 +7593,8 @@ void CEntryStub::GenerateCore(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);
@ -7618,17 +7619,19 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
ASSERT(StackHandlerConstants::kNextOffset == 0);
__ pop(Operand::StaticVariable(handler_address));
// Set external caught exception to false.
ExternalReference external_caught(Top::k_external_caught_exception_address);
__ mov(eax, false);
__ mov(Operand::StaticVariable(external_caught), eax);
if (type == OUT_OF_MEMORY) {
// Set external caught exception to false.
ExternalReference external_caught(Top::k_external_caught_exception_address);
__ mov(eax, false);
__ mov(Operand::StaticVariable(external_caught), eax);
// Set pending exception and eax to out of memory exception.
ExternalReference pending_exception(Top::k_pending_exception_address);
__ mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
__ mov(Operand::StaticVariable(pending_exception), eax);
// Set pending exception and eax to out of memory exception.
ExternalReference pending_exception(Top::k_pending_exception_address);
__ mov(eax, reinterpret_cast<int32_t>(Failure::OutOfMemoryException()));
__ mov(Operand::StaticVariable(pending_exception), eax);
}
// Clear the context pointer;
// Clear the context pointer.
__ xor_(esi, Operand(esi));
// Restore fp from handler and discard handler state.
@ -7667,11 +7670,14 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
// edi: number of arguments including receiver (C callee-saved)
// esi: argv pointer (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,
@ -7680,6 +7686,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,
@ -7690,14 +7697,17 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
__ mov(eax, Immediate(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);

3
deps/v8/src/mark-compact.cc

@ -39,6 +39,7 @@ namespace internal {
// -------------------------------------------------------------------------
// MarkCompactCollector
bool MarkCompactCollector::force_compaction_ = false;
bool MarkCompactCollector::compacting_collection_ = false;
int MarkCompactCollector::previous_marked_count_ = 0;
@ -110,7 +111,7 @@ void MarkCompactCollector::Prepare(GCTracer* tracer) {
#endif
ASSERT(!FLAG_always_compact || !FLAG_never_compact);
compacting_collection_ = FLAG_always_compact;
compacting_collection_ = FLAG_always_compact || force_compaction_;
// We compact the old generation if it gets too fragmented (ie, we could
// recover an expected amount of space by reclaiming the waste and free

10
deps/v8/src/mark-compact.h

@ -75,6 +75,12 @@ class MarkCompactCollector: public AllStatic {
// Type of functions to process non-live objects.
typedef void (*ProcessNonLiveFunction)(HeapObject* object);
// Set the global force_compaction flag, it must be called before Prepare
// to take effect.
static void SetForceCompaction(bool value) {
force_compaction_ = value;
}
// Prepares for GC by resetting relocation info in old and map spaces and
// choosing spaces to compact.
static void Prepare(GCTracer* tracer);
@ -117,6 +123,10 @@ class MarkCompactCollector: public AllStatic {
// The current stage of the collector.
static CollectorState state_;
#endif
// Global flag that forces a compaction.
static bool force_compaction_;
// Global flag indicating whether spaces were compacted on the last GC.
static bool compacting_collection_;

6
deps/v8/src/messages.cc

@ -147,14 +147,12 @@ Handle<String> MessageHandler::GetMessage(Handle<Object> data) {
Handle<String> fmt_str = Factory::LookupAsciiSymbol("FormatMessage");
Handle<JSFunction> fun =
Handle<JSFunction>(
JSFunction::cast(
Top::builtins()->GetProperty(*fmt_str)));
JSFunction::cast(Top::builtins()->GetProperty(*fmt_str)));
Object** argv[1] = { data.location() };
bool caught_exception;
Handle<Object> result =
Execution::TryCall(fun, Top::builtins(), 1, argv,
&caught_exception);
Execution::TryCall(fun, Top::builtins(), 1, argv, &caught_exception);
if (caught_exception || !result->IsString()) {
return Factory::LookupAsciiSymbol("<error>");

3
deps/v8/src/objects-debug.cc

@ -705,7 +705,8 @@ void Oddball::OddballVerify() {
} else {
ASSERT(number->IsSmi());
int value = Smi::cast(number)->value();
ASSERT(value == 0 || value == 1 || value == -1 || value == -2);
ASSERT(value == 0 || value == 1 || value == -1 ||
value == -2 || value == -3);
}
}

1
deps/v8/src/objects-inl.h

@ -788,6 +788,7 @@ Failure* Failure::Exception() {
return Construct(EXCEPTION);
}
Failure* Failure::OutOfMemoryException() {
return Construct(OUT_OF_MEMORY_EXCEPTION);
}

3
deps/v8/src/scanner.cc

@ -183,7 +183,8 @@ uc32 TwoByteStringUTF16Buffer::Advance() {
void TwoByteStringUTF16Buffer::PushBack(uc32 ch) {
pos_--;
ASSERT(pos_ >= 0 && raw_data_[pos_] == ch);
ASSERT(pos_ >= Scanner::kCharacterLookaheadBufferSize);
ASSERT(raw_data_[pos_ - Scanner::kCharacterLookaheadBufferSize] == ch);
}

4
deps/v8/src/scanner.h

@ -212,6 +212,8 @@ class Scanner {
static unibrow::Predicate<unibrow::LineTerminator, 128> kIsLineTerminator;
static unibrow::Predicate<unibrow::WhiteSpace, 128> kIsWhiteSpace;
static const int kCharacterLookaheadBufferSize = 1;
private:
CharacterStreamUTF16Buffer char_stream_buffer_;
TwoByteStringUTF16Buffer two_byte_string_buffer_;
@ -242,8 +244,6 @@ class Scanner {
bool has_line_terminator_before_next_;
bool is_pre_parsing_;
static const int kCharacterLookaheadBufferSize = 1;
// Literal buffer support
void StartLiteral();
void AddChar(uc32 ch);

4
deps/v8/src/spaces.cc

@ -1079,9 +1079,9 @@ void SemiSpace::TearDown() {
bool SemiSpace::Grow() {
// Commit 50% extra space but only up to maximum capacity.
// Double the semispace size but only up to maximum capacity.
int maximum_extra = maximum_capacity_ - capacity_;
int extra = Min(RoundUp(capacity_ / 2, OS::AllocateAlignment()),
int extra = Min(RoundUp(capacity_, OS::AllocateAlignment()),
maximum_extra);
if (!MemoryAllocator::CommitBlock(high(), extra, executable())) {
return false;

2
deps/v8/src/third_party/dtoa/dtoa.c

@ -1535,7 +1535,7 @@ strtod
double aadj, aadj1, adj, rv, rv0;
Long L;
ULong y, z;
Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
Bigint *bb = NULL, *bb1, *bd = NULL, *bd0, *bs = NULL, *delta = NULL;
#ifdef SET_INEXACT
int inexact, oldinexact;
#endif

61
deps/v8/src/top.cc

@ -98,6 +98,7 @@ void Top::InitializeThreadLocal() {
thread_local_.stack_is_cooked_ = false;
thread_local_.try_catch_handler_ = NULL;
thread_local_.context_ = NULL;
thread_local_.thread_id_ = ThreadManager::kInvalidId;
thread_local_.external_caught_exception_ = false;
thread_local_.failed_access_check_callback_ = NULL;
clear_pending_exception();
@ -598,6 +599,12 @@ Failure* Top::StackOverflow() {
}
Failure* Top::TerminateExecution() {
DoThrow(Heap::termination_exception(), NULL, NULL);
return Failure::Exception();
}
Failure* Top::Throw(Object* exception, MessageLocation* location) {
DoThrow(exception, location, NULL);
return Failure::Exception();
@ -694,7 +701,8 @@ void Top::ReportUncaughtException(Handle<Object> exception,
}
bool Top::ShouldReportException(bool* is_caught_externally) {
bool Top::ShouldReturnException(bool* is_caught_externally,
bool catchable_by_javascript) {
// Find the top-most try-catch handler.
StackHandler* handler =
StackHandler::FromAddress(Top::handler(Top::GetCurrentThread()));
@ -712,7 +720,8 @@ bool Top::ShouldReportException(bool* is_caught_externally) {
//
// See comments in RegisterTryCatchHandler for details.
*is_caught_externally = try_catch != NULL &&
(handler == NULL || handler == try_catch->js_handler_);
(handler == NULL || handler == try_catch->js_handler_ ||
!catchable_by_javascript);
if (*is_caught_externally) {
// Only report the exception if the external handler is verbose.
@ -735,12 +744,17 @@ void Top::DoThrow(Object* exception,
// Determine reporting and whether the exception is caught externally.
bool is_caught_externally = false;
bool is_out_of_memory = exception == Failure::OutOfMemoryException();
bool should_return_exception = ShouldReportException(&is_caught_externally);
bool report_exception = !is_out_of_memory && should_return_exception;
bool is_termination_exception = exception == Heap::termination_exception();
bool catchable_by_javascript = !is_termination_exception && !is_out_of_memory;
bool should_return_exception =
ShouldReturnException(&is_caught_externally, catchable_by_javascript);
bool report_exception = catchable_by_javascript && should_return_exception;
#ifdef ENABLE_DEBUGGER_SUPPORT
// Notify debugger of exception.
Debugger::OnException(exception_handle, report_exception);
if (catchable_by_javascript) {
Debugger::OnException(exception_handle, report_exception);
}
#endif
// Generate the message.
@ -791,14 +805,21 @@ void Top::ReportPendingMessages() {
// the global context. Note: We have to mark the global context here
// since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to
// set it.
bool external_caught = thread_local_.external_caught_exception_;
HandleScope scope;
if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) {
context()->mark_out_of_memory();
} else if (thread_local_.pending_exception_ ==
Heap::termination_exception()) {
if (external_caught) {
thread_local_.try_catch_handler_->can_continue_ = false;
thread_local_.try_catch_handler_->exception_ = Heap::null_value();
}
} else {
Handle<Object> exception(pending_exception());
bool external_caught = thread_local_.external_caught_exception_;
thread_local_.external_caught_exception_ = false;
if (external_caught) {
thread_local_.try_catch_handler_->can_continue_ = true;
thread_local_.try_catch_handler_->exception_ =
thread_local_.pending_exception_;
if (!thread_local_.pending_message_obj_->IsTheHole()) {
@ -834,16 +855,30 @@ void Top::TraceException(bool flag) {
}
bool Top::optional_reschedule_exception(bool is_bottom_call) {
bool Top::OptionalRescheduleException(bool is_bottom_call,
bool force_clear_catchable) {
// Allways reschedule out of memory exceptions.
if (!is_out_of_memory()) {
// Never reschedule the exception if this is the bottom call.
bool clear_exception = is_bottom_call;
bool is_termination_exception =
pending_exception() == Heap::termination_exception();
// Do not reschedule the exception if this is the bottom call or
// if we are asked to clear catchable exceptions. Termination
// exceptions are not catchable and are only cleared if this is
// the bottom call.
bool clear_exception = is_bottom_call ||
(force_clear_catchable && !is_termination_exception);
// If the exception is externally caught, clear it if there are no
// JavaScript frames on the way to the C++ frame that has the
// external handler.
if (thread_local_.external_caught_exception_) {
if (is_termination_exception) {
thread_local_.external_caught_exception_ = false;
if (is_bottom_call) {
clear_pending_exception();
return false;
}
} else if (thread_local_.external_caught_exception_) {
// If the exception is externally caught, clear it if there are no
// JavaScript frames on the way to the C++ frame that has the
// external handler.
ASSERT(thread_local_.try_catch_handler_ != NULL);
Address external_handler_address =
reinterpret_cast<Address>(thread_local_.try_catch_handler_);

12
deps/v8/src/top.h

@ -46,6 +46,7 @@ class ThreadLocalTop BASE_EMBEDDED {
// The context where the current execution method is created and for variable
// lookups.
Context* context_;
int thread_id_;
Object* pending_exception_;
bool has_pending_message_;
const char* pending_message_;
@ -118,6 +119,10 @@ class Top {
thread_local_.save_context_ = save;
}
// Access to current thread id.
static int thread_id() { return thread_local_.thread_id_; }
static void set_thread_id(int id) { thread_local_.thread_id_ = id; }
// Interface to pending exception.
static Object* pending_exception() {
ASSERT(has_pending_exception());
@ -152,7 +157,8 @@ class Top {
// exceptions. If an exception was thrown and not handled by an external
// handler the exception is scheduled to be rethrown when we return to running
// JavaScript code. If an exception is scheduled true is returned.
static bool optional_reschedule_exception(bool is_bottom_call);
static bool OptionalRescheduleException(bool is_bottom_call,
bool force_clear_catchable);
static bool* external_caught_exception_address() {
return &thread_local_.external_caught_exception_;
@ -246,7 +252,8 @@ class Top {
static void DoThrow(Object* exception,
MessageLocation* location,
const char* message);
static bool ShouldReportException(bool* is_caught_externally);
static bool ShouldReturnException(bool* is_caught_externally,
bool catchable_by_javascript);
static void ReportUncaughtException(Handle<Object> exception,
MessageLocation* location,
Handle<String> stack_trace);
@ -260,6 +267,7 @@ class Top {
// Out of resource exception helpers.
static Failure* StackOverflow();
static Failure* TerminateExecution();
// Administration
static void Initialize();

1
deps/v8/src/v8.cc

@ -156,6 +156,7 @@ uint32_t V8::Random() {
return (hi << 16) + (lo & 0xFFFF);
}
void V8::IdleNotification(bool is_high_priority) {
if (!FLAG_use_idle_notification) return;
// Ignore high priority instances of V8.

21
deps/v8/src/v8threads.cc

@ -151,6 +151,10 @@ bool ThreadManager::RestoreThread() {
from = RegExpStack::RestoreStack(from);
from = Bootstrapper::RestoreState(from);
Thread::SetThreadLocal(thread_state_key, NULL);
if (state->terminate_on_restore()) {
StackGuard::TerminateExecution();
state->set_terminate_on_restore(false);
}
state->set_id(kInvalidId);
state->Unlink();
state->LinkInto(ThreadState::FREE_LIST);
@ -188,6 +192,7 @@ ThreadState* ThreadState::in_use_anchor_ = new ThreadState();
ThreadState::ThreadState() : id_(ThreadManager::kInvalidId),
terminate_on_restore_(false),
next_(this), previous_(this) {
}
@ -317,7 +322,21 @@ int ThreadManager::CurrentId() {
void ThreadManager::AssignId() {
if (!Thread::HasThreadLocal(thread_id_key)) {
Thread::SetThreadLocalInt(thread_id_key, next_id_++);
ASSERT(Locker::IsLocked());
int thread_id = next_id_++;
Thread::SetThreadLocalInt(thread_id_key, thread_id);
Top::set_thread_id(thread_id);
}
}
void ThreadManager::TerminateExecution(int thread_id) {
for (ThreadState* state = ThreadState::FirstInUse();
state != NULL;
state = state->Next()) {
if (thread_id == state->id()) {
state->set_terminate_on_restore(true);
}
}
}

9
deps/v8/src/v8threads.h

@ -50,6 +50,12 @@ class ThreadState {
void set_id(int id) { id_ = id; }
int id() { return id_; }
// Should the thread be terminated when it is restored?
bool terminate_on_restore() { return terminate_on_restore_; }
void set_terminate_on_restore(bool terminate_on_restore) {
terminate_on_restore_ = terminate_on_restore;
}
// Get data area for archiving a thread.
char* data() { return data_; }
private:
@ -58,6 +64,7 @@ class ThreadState {
void AllocateSpace();
int id_;
bool terminate_on_restore_;
char* data_;
ThreadState* next_;
ThreadState* previous_;
@ -88,6 +95,8 @@ class ThreadManager : public AllStatic {
static int CurrentId();
static void AssignId();
static void TerminateExecution(int thread_id);
static const int kInvalidId = -1;
private:
static void EagerlyArchiveThread();

2
deps/v8/src/version.cc

@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 1
#define MINOR_VERSION 3
#define BUILD_NUMBER 5
#define BUILD_NUMBER 6
#define PATCH_LEVEL 0
#define CANDIDATE_VERSION false

64
deps/v8/src/x64/codegen-x64.cc

@ -6747,6 +6747,7 @@ void CEntryStub::GenerateThrowTOS(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,
@ -6819,11 +6820,10 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
__ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
__ j(zero, &retry);
Label continue_exception;
// If the returned failure is EXCEPTION then promote Top::pending_exception().
__ movq(kScratchRegister, Failure::Exception(), RelocInfo::NONE);
// Special handling of out of memory exceptions.
__ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE);
__ cmpq(rax, kScratchRegister);
__ j(not_equal, &continue_exception);
__ j(equal, throw_out_of_memory_exception);
// Retrieve the pending exception and clear the variable.
ExternalReference pending_exception_address(Top::k_pending_exception_address);
@ -6833,11 +6833,10 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
__ movq(rdx, Operand(rdx, 0));
__ movq(Operand(kScratchRegister, 0), rdx);
__ bind(&continue_exception);
// Special handling of out of memory exception.
__ movq(kScratchRegister, Failure::OutOfMemoryException(), RelocInfo::NONE);
__ cmpq(rax, kScratchRegister);
__ j(equal, throw_out_of_memory_exception);
// Special handling of termination exceptions which are uncatchable
// by javascript code.
__ Cmp(rax, Factory::termination_exception());
__ j(equal, throw_termination_exception);
// Handle normal exception.
__ jmp(throw_normal_exception);
@ -6847,7 +6846,8 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
}
void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm,
UncatchableExceptionType type) {
// Fetch top stack handler.
ExternalReference handler_address(Top::k_handler_address);
__ movq(kScratchRegister, handler_address);
@ -6857,30 +6857,32 @@ void CEntryStub::GenerateThrowOutOfMemory(MacroAssembler* masm) {
Label loop, done;
__ bind(&loop);
// Load the type of the current stack handler.
__ cmpq(Operand(rsp, StackHandlerConstants::kStateOffset),
Immediate(StackHandler::ENTRY));
const int kStateOffset = StackHandlerConstants::kStateOffset;
__ cmpq(Operand(rsp, kStateOffset), Immediate(StackHandler::ENTRY));
__ j(equal, &done);
// Fetch the next handler in the list.
ASSERT(StackHandlerConstants::kNextOffset == 0);
__ pop(rsp);
const int kNextOffset = StackHandlerConstants::kNextOffset;
__ movq(rsp, Operand(rsp, kNextOffset));
__ jmp(&loop);
__ bind(&done);
// Set the top handler address to next handler past the current ENTRY handler.
__ pop(rax);
__ store_rax(handler_address);
__ movq(kScratchRegister, handler_address);
__ pop(Operand(kScratchRegister, 0));
// Set external caught exception to false.
__ movq(rax, Immediate(false));
ExternalReference external_caught(Top::k_external_caught_exception_address);
__ store_rax(external_caught);
if (type == OUT_OF_MEMORY) {
// Set external caught exception to false.
ExternalReference external_caught(Top::k_external_caught_exception_address);
__ movq(rax, Immediate(false));
__ store_rax(external_caught);
// Set pending exception and rax to out of memory exception.
__ movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE);
ExternalReference pending_exception(Top::k_pending_exception_address);
__ store_rax(pending_exception);
// Set pending exception and rax to out of memory exception.
ExternalReference pending_exception(Top::k_pending_exception_address);
__ movq(rax, Failure::OutOfMemoryException(), RelocInfo::NONE);
__ store_rax(pending_exception);
}
// Clear the context pointer;
// Clear the context pointer.
__ xor_(rsi, rsi);
// Restore registers from handler.
@ -6956,12 +6958,14 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
// r14: number of arguments including receiver (C callee-saved).
// r15: argv pointer (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,
&throw_termination_exception,
&throw_out_of_memory_exception,
frame_type,
false,
@ -6970,6 +6974,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,
@ -6980,14 +6985,17 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
__ movq(rax, failure, RelocInfo::NONE);
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);

1
deps/v8/test/cctest/SConscript

@ -56,6 +56,7 @@ SOURCES = {
'test-spaces.cc',
'test-strings.cc',
'test-threads.cc',
'test-thread-termination.cc',
'test-utils.cc',
'test-version.cc'
],

78
deps/v8/test/cctest/test-api.cc

@ -2843,7 +2843,7 @@ TEST(ErrorReporting) {
static const char* js_code_causing_huge_string_flattening =
"var str = 'X';"
"for (var i = 0; i < 29; i++) {"
"for (var i = 0; i < 30; i++) {"
" str = str + str;"
"}"
"str.match(/X/);";
@ -6217,6 +6217,58 @@ TEST(DontLeakGlobalObjects) {
}
v8::Persistent<v8::Object> some_object;
v8::Persistent<v8::Object> bad_handle;
void NewPersistentHandleCallback(v8::Persistent<v8::Value>, void*) {
v8::HandleScope scope;
bad_handle = v8::Persistent<v8::Object>::New(some_object);
}
THREADED_TEST(NewPersistentHandleFromWeakCallback) {
LocalContext context;
v8::Persistent<v8::Object> handle1, handle2;
{
v8::HandleScope scope;
some_object = v8::Persistent<v8::Object>::New(v8::Object::New());
handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
}
// Note: order is implementation dependent alas: currently
// global handle nodes are processed by PostGarbageCollectionProcessing
// in reverse allocation order, so if second allocated handle is deleted,
// weak callback of the first handle would be able to 'reallocate' it.
handle1.MakeWeak(NULL, NewPersistentHandleCallback);
handle2.Dispose();
i::Heap::CollectAllGarbage();
}
v8::Persistent<v8::Object> to_be_disposed;
void DisposeAndForceGcCallback(v8::Persistent<v8::Value> handle, void*) {
to_be_disposed.Dispose();
i::Heap::CollectAllGarbage();
}
THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
LocalContext context;
v8::Persistent<v8::Object> handle1, handle2;
{
v8::HandleScope scope;
handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
}
handle1.MakeWeak(NULL, DisposeAndForceGcCallback);
to_be_disposed = handle2;
i::Heap::CollectAllGarbage();
}
THREADED_TEST(CheckForCrossContextObjectLiterals) {
v8::V8::Initialize();
@ -7121,6 +7173,30 @@ THREADED_TEST(MorphCompositeStringTest) {
}
TEST(CompileExternalTwoByteSource) {
v8::HandleScope scope;
LocalContext context;
// This is a very short list of sources, which currently is to check for a
// regression caused by r2703.
const char* ascii_sources[] = {
"0.5",
"-0.5", // This mainly testes PushBack in the Scanner.
"--0.5", // This mainly testes PushBack in the Scanner.
NULL
};
// Compile the sources as external two byte strings.
for (int i = 0; ascii_sources[i] != NULL; i++) {
uint16_t* two_byte_string = AsciiToTwoByteString(ascii_sources[i]);
UC16VectorResource uc16_resource(
i::Vector<const uint16_t>(two_byte_string, strlen(ascii_sources[i])));
v8::Local<v8::String> source = v8::String::NewExternal(&uc16_resource);
v8::Script::Compile(source);
}
}
class RegExpStringModificationTest {
public:
RegExpStringModificationTest()

195
deps/v8/test/cctest/test-thread-termination.cc

@ -0,0 +1,195 @@
// Copyright 2009 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 "v8.h"
#include "platform.h"
#include "cctest.h"
v8::internal::Semaphore* semaphore = NULL;
v8::Handle<v8::Value> Signal(const v8::Arguments& args) {
semaphore->Signal();
return v8::Undefined();
}
v8::Handle<v8::Value> TerminateCurrentThread(const v8::Arguments& args) {
v8::V8::TerminateExecution();
return v8::Undefined();
}
v8::Handle<v8::Value> Fail(const v8::Arguments& args) {
CHECK(false);
return v8::Undefined();
}
v8::Handle<v8::Value> Loop(const v8::Arguments& args) {
v8::Handle<v8::String> source =
v8::String::New("try { doloop(); fail(); } catch(e) { fail(); }");
v8::Script::Compile(source)->Run();
return v8::Undefined();
}
v8::Handle<v8::Value> DoLoop(const v8::Arguments& args) {
v8::TryCatch try_catch;
v8::Script::Compile(v8::String::New("function f() {"
" var term = true;"
" try {"
" while(true) {"
" if (term) terminate();"
" term = false;"
" }"
" fail();"
" } catch(e) {"
" fail();"
" }"
"}"
"f()"))->Run();
CHECK(try_catch.HasCaught());
CHECK(try_catch.Exception()->IsNull());
CHECK(try_catch.Message().IsEmpty());
CHECK(!try_catch.CanContinue());
return v8::Undefined();
}
v8::Handle<v8::ObjectTemplate> CreateGlobalTemplate(
v8::InvocationCallback terminate) {
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
global->Set(v8::String::New("terminate"),
v8::FunctionTemplate::New(terminate));
global->Set(v8::String::New("fail"), v8::FunctionTemplate::New(Fail));
global->Set(v8::String::New("loop"), v8::FunctionTemplate::New(Loop));
global->Set(v8::String::New("doloop"), v8::FunctionTemplate::New(DoLoop));
return global;
}
// Test that a single thread of JavaScript execution can terminate
// itself.
TEST(TerminateOnlyV8ThreadFromThreadItself) {
v8::HandleScope scope;
v8::Handle<v8::ObjectTemplate> global =
CreateGlobalTemplate(TerminateCurrentThread);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context);
// Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source =
v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
v8::Script::Compile(source)->Run();
// Test that we can run the code again after thread termination.
v8::Script::Compile(source)->Run();
context.Dispose();
}
class TerminatorThread : public v8::internal::Thread {
void Run() {
semaphore->Wait();
v8::V8::TerminateExecution();
}
};
// Test that a single thread of JavaScript execution can be terminated
// from the side by another thread.
TEST(TerminateOnlyV8ThreadFromOtherThread) {
semaphore = v8::internal::OS::CreateSemaphore(0);
TerminatorThread thread;
thread.Start();
v8::HandleScope scope;
v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context);
// Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source =
v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
v8::Script::Compile(source)->Run();
thread.Join();
delete semaphore;
semaphore = NULL;
context.Dispose();
}
class LoopingThread : public v8::internal::Thread {
public:
void Run() {
v8::Locker locker;
v8::HandleScope scope;
v8_thread_id_ = v8::V8::GetCurrentThreadId();
v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context);
// Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source =
v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
v8::Script::Compile(source)->Run();
context.Dispose();
}
int GetV8ThreadId() { return v8_thread_id_; }
private:
int v8_thread_id_;
};
// Test that multiple threads using V8 can be terminated from another
// thread when using Lockers and preemption.
TEST(TerminateMultipleV8Threads) {
{
v8::Locker locker;
v8::V8::Initialize();
v8::Locker::StartPreemption(1);
semaphore = v8::internal::OS::CreateSemaphore(0);
}
LoopingThread thread1;
thread1.Start();
LoopingThread thread2;
thread2.Start();
// Wait until both threads have signaled the semaphore.
semaphore->Wait();
semaphore->Wait();
{
v8::Locker locker;
v8::V8::TerminateExecution(thread1.GetV8ThreadId());
v8::V8::TerminateExecution(thread2.GetV8ThreadId());
}
thread1.Join();
thread2.Join();
delete semaphore;
semaphore = NULL;
}

2
deps/v8/test/cctest/test-threads.cc

@ -50,5 +50,3 @@ TEST(Preemption) {
script->Run();
}

6
deps/v8/test/mozilla/mozilla.status

@ -624,7 +624,6 @@ js1_5/extensions/regress-333541: FAIL_OK
js1_5/extensions/regress-335700: FAIL_OK
js1_5/extensions/regress-336409-1: FAIL_OK
js1_5/extensions/regress-336409-2: FAIL_OK
js1_5/extensions/regress-336410-1: FAIL_OK
js1_5/extensions/regress-336410-2: FAIL_OK
js1_5/extensions/regress-341956-01: FAIL_OK
js1_5/extensions/regress-341956-02: FAIL_OK
@ -706,6 +705,11 @@ js1_5/extensions/toLocaleFormat-02: FAIL_OK
js1_5/extensions/regress-330569: TIMEOUT
js1_5/extensions/regress-351448: TIMEOUT
js1_5/extensions/regress-342960: FAIL_OK || TIMEOUT if $mode == debug
# In the 64-bit version, this test takes longer to run out of memory
# than it does in the 32-bit version when attempting to generate a huge
# error message in debug mode.
js1_5/extensions/regress-336410-1: FAIL_OK || TIMEOUT if ($mode == debug && $arch == x64)
##################### DECOMPILATION TESTS #####################

22
deps/v8/tools/gyp/v8.gyp

@ -97,9 +97,15 @@
],
}],
],
'cflags_cc': [
'-fno-rtti',
],
}],
['OS=="mac"', {
'xcode_settings': {
'GCC_OPTIMIZATION_LEVEL': '3', # -O3
'GCC_STRICT_ALIASING': 'YES', # -fstrict-aliasing. Mainline gcc
# enables this at -O2 and above,
# but Apple gcc does not unless it
# is specified explicitly.
},
}],
['OS=="win"', {
'msvs_configuration_attributes': {
@ -128,10 +134,6 @@
],
},
},
'xcode_settings': {
'GCC_ENABLE_CPP_EXCEPTIONS': 'NO',
'GCC_ENABLE_CPP_RTTI': 'NO',
},
},
'targets': [
{
@ -387,7 +389,7 @@
'../../src/arm/assembler-arm.cc',
'../../src/arm/assembler-arm.h',
'../../src/arm/builtins-arm.cc',
'../../src/arm/cfg-arm.cc',
'../../src/arm/cfg-arm.cc',
'../../src/arm/codegen-arm.cc',
'../../src/arm/codegen-arm.h',
'../../src/arm/constants-arm.h',
@ -418,7 +420,7 @@
'../../src/ia32/assembler-ia32.cc',
'../../src/ia32/assembler-ia32.h',
'../../src/ia32/builtins-ia32.cc',
'../../src/ia32/cfg-ia32.cc',
'../../src/ia32/cfg-ia32.cc',
'../../src/ia32/codegen-ia32.cc',
'../../src/ia32/codegen-ia32.h',
'../../src/ia32/cpu-ia32.cc',
@ -451,7 +453,7 @@
'../../src/x64/assembler-x64.cc',
'../../src/x64/assembler-x64.h',
'../../src/x64/builtins-x64.cc',
'../../src/x64/cfg-x64.cc',
'../../src/x64/cfg-x64.cc',
'../../src/x64/codegen-x64.cc',
'../../src/x64/codegen-x64.h',
'../../src/x64/cpu-x64.cc',

Loading…
Cancel
Save