Browse Source

Upgrade V8 to 2.1.2.6

v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
c98b0799bf
  1. 1
      deps/v8/SConstruct
  2. 16
      deps/v8/include/v8.h
  3. 23
      deps/v8/src/api.cc
  4. 5
      deps/v8/src/arm/codegen-arm.cc
  5. 2
      deps/v8/src/arm/codegen-arm.h
  6. 1
      deps/v8/src/arm/fast-codegen-arm.cc
  7. 1
      deps/v8/src/arm/full-codegen-arm.cc
  8. 1
      deps/v8/src/arm/jump-target-arm.cc
  9. 1
      deps/v8/src/arm/virtual-frame-arm.cc
  10. 14
      deps/v8/src/arm/virtual-frame-arm.h
  11. 4
      deps/v8/src/ast.h
  12. 3
      deps/v8/src/codegen-inl.h
  13. 1
      deps/v8/src/codegen.cc
  14. 1
      deps/v8/src/full-codegen.cc
  15. 27
      deps/v8/src/heap.cc
  16. 8
      deps/v8/src/heap.h
  17. 4
      deps/v8/src/ia32/codegen-ia32.cc
  18. 2
      deps/v8/src/ia32/codegen-ia32.h
  19. 1
      deps/v8/src/ia32/full-codegen-ia32.cc
  20. 1
      deps/v8/src/ia32/jump-target-ia32.cc
  21. 1
      deps/v8/src/ia32/register-allocator-ia32.cc
  22. 30
      deps/v8/src/ia32/stub-cache-ia32.cc
  23. 1
      deps/v8/src/ia32/virtual-frame-ia32.cc
  24. 16
      deps/v8/src/ia32/virtual-frame-ia32.h
  25. 14
      deps/v8/src/ic.cc
  26. 7
      deps/v8/src/jump-target-inl.h
  27. 3
      deps/v8/src/jump-target.cc
  28. 1
      deps/v8/src/register-allocator-inl.h
  29. 1
      deps/v8/src/register-allocator.cc
  30. 2
      deps/v8/src/version.cc
  31. 109
      deps/v8/src/virtual-frame-inl.h
  32. 68
      deps/v8/src/virtual-frame.cc
  33. 4
      deps/v8/src/x64/codegen-x64.cc
  34. 2
      deps/v8/src/x64/codegen-x64.h
  35. 1
      deps/v8/src/x64/fast-codegen-x64.cc
  36. 1
      deps/v8/src/x64/full-codegen-x64.cc
  37. 1
      deps/v8/src/x64/jump-target-x64.cc
  38. 1
      deps/v8/src/x64/register-allocator-x64.cc
  39. 1
      deps/v8/src/x64/virtual-frame-x64.cc
  40. 14
      deps/v8/src/x64/virtual-frame-x64.h
  41. 75
      deps/v8/test/cctest/test-api.cc
  42. 22
      deps/v8/test/cctest/test-thread-termination.cc
  43. 1
      deps/v8/tools/gyp/v8.gyp
  44. 4
      deps/v8/tools/visual_studio/v8_base.vcproj
  45. 4
      deps/v8/tools/visual_studio/v8_base_arm.vcproj
  46. 4
      deps/v8/tools/visual_studio/v8_base_x64.vcproj

1
deps/v8/SConstruct

@ -267,6 +267,7 @@ V8_EXTRA_FLAGS = {
'gcc': { 'gcc': {
'all': { 'all': {
'WARNINGFLAGS': ['-Wall', 'WARNINGFLAGS': ['-Wall',
'-Werror',
'-W', '-W',
'-Wno-unused-parameter', '-Wno-unused-parameter',
'-Wnon-virtual-dtor'] '-Wnon-virtual-dtor']

16
deps/v8/include/v8.h

@ -2441,6 +2441,16 @@ class V8EXPORT V8 {
*/ */
static void TerminateExecution(); static void TerminateExecution();
/**
* Is V8 terminating JavaScript execution.
*
* Returns true if JavaScript execution is currently terminating
* because of a call to TerminateExecution. In that case there are
* still JavaScript frames on the stack and the termination
* exception is still active.
*/
static bool IsExecutionTerminating();
/** /**
* Releases any resources used by v8 and stops any utility threads * Releases any resources used by v8 and stops any utility threads
* that may be running. Note that disposing v8 is permanent, it * that may be running. Note that disposing v8 is permanent, it
@ -2473,6 +2483,12 @@ class V8EXPORT V8 {
*/ */
static void LowMemoryNotification(); static void LowMemoryNotification();
/**
* Optional notification that a context has been disposed. V8 uses
* these notifications to guide the garbage collection heuristic.
*/
static void ContextDisposedNotification();
private: private:
V8(); V8();

23
deps/v8/src/api.cc

@ -438,7 +438,6 @@ bool V8::IsGlobalWeak(i::Object** obj) {
void V8::DisposeGlobal(i::Object** obj) { void V8::DisposeGlobal(i::Object** obj) {
LOG_API("DisposeGlobal"); LOG_API("DisposeGlobal");
if (!i::V8::IsRunning()) return; if (!i::V8::IsRunning()) return;
if ((*obj)->IsGlobalContext()) i::Heap::NotifyContextDisposed();
i::GlobalHandles::Destroy(obj); i::GlobalHandles::Destroy(obj);
} }
@ -2821,6 +2820,12 @@ void v8::V8::LowMemoryNotification() {
} }
void v8::V8::ContextDisposedNotification() {
if (!i::V8::IsRunning()) return;
i::Heap::NotifyContextDisposed();
}
const char* v8::V8::GetVersion() { const char* v8::V8::GetVersion() {
static v8::internal::EmbeddedVector<char, 128> buffer; static v8::internal::EmbeddedVector<char, 128> buffer;
v8::internal::Version::GetString(buffer); v8::internal::Version::GetString(buffer);
@ -2852,13 +2857,6 @@ Persistent<Context> v8::Context::New(
i::Handle<i::Context> env; i::Handle<i::Context> env;
{ {
ENTER_V8; ENTER_V8;
#if defined(ANDROID)
// On mobile device, full GC is expensive, leave it to the system to
// decide when should make a full GC.
#else
// Give the heap a chance to cleanup if we've disposed contexts.
i::Heap::CollectAllGarbageIfContextDisposed();
#endif
v8::Handle<ObjectTemplate> proxy_template = global_template; v8::Handle<ObjectTemplate> proxy_template = global_template;
i::Handle<i::FunctionTemplateInfo> proxy_constructor; i::Handle<i::FunctionTemplateInfo> proxy_constructor;
i::Handle<i::FunctionTemplateInfo> global_constructor; i::Handle<i::FunctionTemplateInfo> global_constructor;
@ -3561,6 +3559,15 @@ void V8::TerminateExecution() {
} }
bool V8::IsExecutionTerminating() {
if (!i::V8::IsRunning()) return false;
if (i::Top::has_scheduled_exception()) {
return i::Top::scheduled_exception() == i::Heap::termination_exception();
}
return false;
}
String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) { String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj) {
EnsureInitialized("v8::String::Utf8Value::Utf8Value()"); EnsureInitialized("v8::String::Utf8Value::Utf8Value()");
if (obj.IsEmpty()) { if (obj.IsEmpty()) {

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

@ -35,7 +35,7 @@
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "runtime.h" #include "runtime.h"
#include "scopes.h" #include "scopes.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -133,9 +133,6 @@ CodeGenerator::CodeGenerator(MacroAssembler* masm)
} }
Scope* CodeGenerator::scope() { return info_->function()->scope(); }
// Calling conventions: // Calling conventions:
// fp: caller's frame pointer // fp: caller's frame pointer
// sp: stack pointer // sp: stack pointer

2
deps/v8/src/arm/codegen-arm.h

@ -203,7 +203,7 @@ class CodeGenerator: public AstVisitor {
// Accessors // Accessors
inline bool is_eval(); inline bool is_eval();
Scope* scope(); inline Scope* scope();
// Generating deferred code. // Generating deferred code.
void ProcessDeferred(); void ProcessDeferred();

1
deps/v8/src/arm/fast-codegen-arm.cc

@ -29,6 +29,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "fast-codegen.h" #include "fast-codegen.h"
#include "scopes.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/arm/full-codegen-arm.cc

@ -32,6 +32,7 @@
#include "debug.h" #include "debug.h"
#include "full-codegen.h" #include "full-codegen.h"
#include "parser.h" #include "parser.h"
#include "scopes.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/arm/jump-target-arm.cc

@ -30,6 +30,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "jump-target-inl.h" #include "jump-target-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/arm/virtual-frame-arm.cc

@ -30,6 +30,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "scopes.h" #include "scopes.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

14
deps/v8/src/arm/virtual-frame-arm.h

@ -62,7 +62,7 @@ class VirtualFrame : public ZoneObject {
VirtualFrame(); VirtualFrame();
// Construct a virtual frame as a clone of an existing one. // Construct a virtual frame as a clone of an existing one.
explicit VirtualFrame(VirtualFrame* original); explicit inline VirtualFrame(VirtualFrame* original);
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
MacroAssembler* masm() { return cgen()->masm(); } MacroAssembler* masm() { return cgen()->masm(); }
@ -344,9 +344,9 @@ class VirtualFrame : public ZoneObject {
void EmitPushMultiple(int count, int src_regs); void EmitPushMultiple(int count, int src_regs);
// Push an element on the virtual frame. // Push an element on the virtual frame.
void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown); inline void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown);
void Push(Handle<Object> value); inline void Push(Handle<Object> value);
void Push(Smi* value) { Push(Handle<Object>(value)); } inline void Push(Smi* value);
// Pushing a result invalidates it (its contents become owned by the frame). // Pushing a result invalidates it (its contents become owned by the frame).
void Push(Result* result) { void Push(Result* result) {
@ -362,7 +362,7 @@ class VirtualFrame : public ZoneObject {
// Nip removes zero or more elements from immediately below the top // Nip removes zero or more elements from immediately below the top
// of the frame, leaving the previous top-of-frame value on top of // of the frame, leaving the previous top-of-frame value on top of
// the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x). // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
void Nip(int num_dropped); inline void Nip(int num_dropped);
private: private:
static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
@ -457,7 +457,7 @@ class VirtualFrame : public ZoneObject {
// Push a copy of a frame slot (typically a local or parameter) on top of // Push a copy of a frame slot (typically a local or parameter) on top of
// the frame. // the frame.
void PushFrameSlotAt(int index); inline void PushFrameSlotAt(int index);
// Push a the value of a frame slot (typically a local or parameter) on // Push a the value of a frame slot (typically a local or parameter) on
// top of the frame and invalidate the slot. // top of the frame and invalidate the slot.
@ -500,7 +500,7 @@ class VirtualFrame : public ZoneObject {
// Register counts are correctly updated. // Register counts are correctly updated.
int InvalidateFrameSlotAt(int index); int InvalidateFrameSlotAt(int index);
bool Equals(VirtualFrame* other); inline bool Equals(VirtualFrame* other);
// Classes that need raw access to the elements_ array. // Classes that need raw access to the elements_ array.
friend class DeferredCode; friend class DeferredCode;

4
deps/v8/src/ast.h

@ -931,10 +931,6 @@ class VariableProxy: public Expression {
return var()->is_global() || var()->rewrite()->IsLeaf(); return var()->is_global() || var()->rewrite()->IsLeaf();
} }
// Reading from a mutable variable is a side effect, but 'this' is
// immutable.
virtual bool IsTrivial() { return is_this(); }
bool IsVariable(Handle<String> n) { bool IsVariable(Handle<String> n) {
return !is_this() && name().is_identical_to(n); return !is_this() && name().is_identical_to(n);
} }

3
deps/v8/src/codegen-inl.h

@ -50,8 +50,11 @@ namespace v8 {
namespace internal { namespace internal {
Handle<Script> CodeGenerator::script() { return info_->script(); } Handle<Script> CodeGenerator::script() { return info_->script(); }
bool CodeGenerator::is_eval() { return info_->is_eval(); } bool CodeGenerator::is_eval() { return info_->is_eval(); }
Scope* CodeGenerator::scope() { return info_->function()->scope(); }
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_CODEGEN_INL_H_ #endif // V8_CODEGEN_INL_H_

1
deps/v8/src/codegen.cc

@ -39,6 +39,7 @@
#include "runtime.h" #include "runtime.h"
#include "scopeinfo.h" #include "scopeinfo.h"
#include "stub-cache.h" #include "stub-cache.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/full-codegen.cc

@ -30,6 +30,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "compiler.h" #include "compiler.h"
#include "full-codegen.h" #include "full-codegen.h"
#include "scopes.h"
#include "stub-cache.h" #include "stub-cache.h"
#include "debug.h" #include "debug.h"
#include "liveedit.h" #include "liveedit.h"

27
deps/v8/src/heap.cc

@ -115,7 +115,7 @@ int Heap::gc_count_ = 0;
int Heap::always_allocate_scope_depth_ = 0; int Heap::always_allocate_scope_depth_ = 0;
int Heap::linear_allocation_scope_depth_ = 0; int Heap::linear_allocation_scope_depth_ = 0;
bool Heap::context_disposed_pending_ = false; int Heap::contexts_disposed_ = 0;
#ifdef DEBUG #ifdef DEBUG
bool Heap::allocation_allowed_ = true; bool Heap::allocation_allowed_ = true;
@ -371,21 +371,8 @@ void Heap::CollectAllGarbage(bool force_compaction) {
} }
void Heap::CollectAllGarbageIfContextDisposed() {
// If the garbage collector interface is exposed through the global
// gc() function, we avoid being clever about forcing GCs when
// contexts are disposed and leave it to the embedder to make
// informed decisions about when to force a collection.
if (!FLAG_expose_gc && context_disposed_pending_) {
HistogramTimerScope scope(&Counters::gc_context);
CollectAllGarbage(false);
}
context_disposed_pending_ = false;
}
void Heap::NotifyContextDisposed() { void Heap::NotifyContextDisposed() {
context_disposed_pending_ = true; contexts_disposed_++;
} }
@ -620,7 +607,8 @@ void Heap::MarkCompact(GCTracer* tracer) {
Shrink(); Shrink();
Counters::objs_since_last_full.Set(0); Counters::objs_since_last_full.Set(0);
context_disposed_pending_ = false;
contexts_disposed_ = 0;
} }
@ -3072,6 +3060,13 @@ bool Heap::IdleNotification() {
static int number_idle_notifications = 0; static int number_idle_notifications = 0;
static int last_gc_count = gc_count_; static int last_gc_count = gc_count_;
if (!FLAG_expose_gc && (contexts_disposed_ > 0)) {
HistogramTimerScope scope(&Counters::gc_context);
CollectAllGarbage(false);
ASSERT(contexts_disposed_ == 0);
return false;
}
bool finished = false; bool finished = false;
if (last_gc_count == gc_count_) { if (last_gc_count == gc_count_) {

8
deps/v8/src/heap.h

@ -632,10 +632,6 @@ class Heap : public AllStatic {
// parameter is true. // parameter is true.
static void CollectAllGarbage(bool force_compaction); static void CollectAllGarbage(bool force_compaction);
// Performs a full garbage collection if a context has been disposed
// since the last time the check was performed.
static void CollectAllGarbageIfContextDisposed();
// Notify the heap that a context has been disposed. // Notify the heap that a context has been disposed.
static void NotifyContextDisposed(); static void NotifyContextDisposed();
@ -908,7 +904,9 @@ class Heap : public AllStatic {
static int always_allocate_scope_depth_; static int always_allocate_scope_depth_;
static int linear_allocation_scope_depth_; static int linear_allocation_scope_depth_;
static bool context_disposed_pending_;
// For keeping track of context disposals.
static int contexts_disposed_;
#if defined(V8_TARGET_ARCH_X64) #if defined(V8_TARGET_ARCH_X64)
static const int kMaxObjectSizeInNewSpace = 512*KB; static const int kMaxObjectSizeInNewSpace = 512*KB;

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

@ -39,6 +39,7 @@
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "runtime.h" #include "runtime.h"
#include "scopes.h" #include "scopes.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -116,9 +117,6 @@ CodeGenerator::CodeGenerator(MacroAssembler* masm)
} }
Scope* CodeGenerator::scope() { return info_->function()->scope(); }
// Calling conventions: // Calling conventions:
// ebp: caller's frame pointer // ebp: caller's frame pointer
// esp: stack pointer // esp: stack pointer

2
deps/v8/src/ia32/codegen-ia32.h

@ -343,7 +343,7 @@ class CodeGenerator: public AstVisitor {
// Accessors // Accessors
inline bool is_eval(); inline bool is_eval();
Scope* scope(); inline Scope* scope();
// Generating deferred code. // Generating deferred code.
void ProcessDeferred(); void ProcessDeferred();

1
deps/v8/src/ia32/full-codegen-ia32.cc

@ -32,6 +32,7 @@
#include "debug.h" #include "debug.h"
#include "full-codegen.h" #include "full-codegen.h"
#include "parser.h" #include "parser.h"
#include "scopes.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/ia32/jump-target-ia32.cc

@ -30,6 +30,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "jump-target-inl.h" #include "jump-target-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/ia32/register-allocator-ia32.cc

@ -29,6 +29,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

30
deps/v8/src/ia32/stub-cache-ia32.cc

@ -479,18 +479,15 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
// Holds information about possible function call optimizations. // Holds information about possible function call optimizations.
class CallOptimization BASE_EMBEDDED { class CallOptimization BASE_EMBEDDED {
public: public:
explicit CallOptimization(LookupResult* lookup) explicit CallOptimization(LookupResult* lookup) {
: constant_function_(NULL), if (!lookup->IsProperty() || !lookup->IsCacheable() ||
is_simple_api_call_(false), lookup->type() != CONSTANT_FUNCTION) {
expected_receiver_type_(NULL), Initialize(NULL);
api_call_info_(NULL) { } else {
if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
// We only optimize constant function calls. // We only optimize constant function calls.
if (lookup->type() != CONSTANT_FUNCTION) return;
Initialize(lookup->GetConstantFunction()); Initialize(lookup->GetConstantFunction());
} }
}
explicit CallOptimization(JSFunction* function) { explicit CallOptimization(JSFunction* function) {
Initialize(function); Initialize(function);
@ -537,11 +534,14 @@ class CallOptimization BASE_EMBEDDED {
private: private:
void Initialize(JSFunction* function) { void Initialize(JSFunction* function) {
if (!function->is_compiled()) return; constant_function_ = NULL;
constant_function_ = function;
is_simple_api_call_ = false; is_simple_api_call_ = false;
expected_receiver_type_ = NULL;
api_call_info_ = NULL;
if (function == NULL || !function->is_compiled()) return;
constant_function_ = function;
AnalyzePossibleApiFunction(function); AnalyzePossibleApiFunction(function);
} }
@ -1223,7 +1223,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
// -- ... // -- ...
// -- esp[(argc + 1) * 4] : receiver // -- esp[(argc + 1) * 4] : receiver
// ----------------------------------- // -----------------------------------
Label miss; Label miss_in_smi_check;
// Get the receiver from the stack. // Get the receiver from the stack.
const int argc = arguments().immediate(); const int argc = arguments().immediate();
@ -1232,7 +1232,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
// Check that the receiver isn't a smi. // Check that the receiver isn't a smi.
if (check != NUMBER_CHECK) { if (check != NUMBER_CHECK) {
__ test(edx, Immediate(kSmiTagMask)); __ test(edx, Immediate(kSmiTagMask));
__ j(zero, &miss, not_taken); __ j(zero, &miss_in_smi_check, not_taken);
} }
// Make sure that it's okay not to patch the on stack receiver // Make sure that it's okay not to patch the on stack receiver
@ -1241,6 +1241,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
CallOptimization optimization(function); CallOptimization optimization(function);
int depth = kInvalidProtoDepth; int depth = kInvalidProtoDepth;
Label miss;
switch (check) { switch (check) {
case RECEIVER_MAP_CHECK: case RECEIVER_MAP_CHECK:
@ -1359,6 +1360,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
if (depth != kInvalidProtoDepth) { if (depth != kInvalidProtoDepth) {
FreeSpaceForFastApiCall(masm(), eax); FreeSpaceForFastApiCall(masm(), eax);
} }
__ bind(&miss_in_smi_check);
Handle<Code> ic = ComputeCallMiss(arguments().immediate()); Handle<Code> ic = ComputeCallMiss(arguments().immediate());
__ jmp(ic, RelocInfo::CODE_TARGET); __ jmp(ic, RelocInfo::CODE_TARGET);

1
deps/v8/src/ia32/virtual-frame-ia32.cc

@ -30,6 +30,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "scopes.h" #include "scopes.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

16
deps/v8/src/ia32/virtual-frame-ia32.h

@ -76,7 +76,7 @@ class VirtualFrame: public ZoneObject {
VirtualFrame(); VirtualFrame();
// Construct a virtual frame as a clone of an existing one. // Construct a virtual frame as a clone of an existing one.
explicit VirtualFrame(VirtualFrame* original); explicit inline VirtualFrame(VirtualFrame* original);
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
@ -395,11 +395,9 @@ class VirtualFrame: public ZoneObject {
NumberInfo::Type info = NumberInfo::kUnknown); NumberInfo::Type info = NumberInfo::kUnknown);
// Push an element on the virtual frame. // Push an element on the virtual frame.
void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown); inline void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown);
void Push(Handle<Object> value); inline void Push(Handle<Object> value);
void Push(Smi* value) { inline void Push(Smi* value);
Push(Handle<Object> (value));
}
// Pushing a result invalidates it (its contents become owned by the // Pushing a result invalidates it (its contents become owned by the
// frame). // frame).
@ -422,7 +420,7 @@ class VirtualFrame: public ZoneObject {
// Nip removes zero or more elements from immediately below the top // Nip removes zero or more elements from immediately below the top
// of the frame, leaving the previous top-of-frame value on top of // of the frame, leaving the previous top-of-frame value on top of
// the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x). // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
void Nip(int num_dropped); inline void Nip(int num_dropped);
private: private:
static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
@ -530,7 +528,7 @@ class VirtualFrame: public ZoneObject {
// Push a copy of a frame slot (typically a local or parameter) on top of // Push a copy of a frame slot (typically a local or parameter) on top of
// the frame. // the frame.
void PushFrameSlotAt(int index); inline void PushFrameSlotAt(int index);
// Push a the value of a frame slot (typically a local or parameter) on // Push a the value of a frame slot (typically a local or parameter) on
// top of the frame and invalidate the slot. // top of the frame and invalidate the slot.
@ -581,7 +579,7 @@ class VirtualFrame: public ZoneObject {
// (via PrepareForCall). // (via PrepareForCall).
Result RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode); Result RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode);
bool Equals(VirtualFrame* other); inline bool Equals(VirtualFrame* other);
// Classes that need raw access to the elements_ array. // Classes that need raw access to the elements_ array.
friend class DeferredCode; friend class DeferredCode;

14
deps/v8/src/ic.cc

@ -1049,20 +1049,6 @@ Object* StoreIC::Store(State state,
return *value; return *value;
} }
// Use specialized code for setting the length of arrays.
if (receiver->IsJSArray()
&& name->Equals(Heap::length_symbol())
&& receiver->AllowsSetElementsLength()) {
#ifdef DEBUG
if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
#endif
Code* target = Builtins::builtin(Builtins::StoreIC_ArrayLength);
set_target(target);
StubCache::Set(*name, HeapObject::cast(*object)->map(), target);
return receiver->SetProperty(*name, *value, NONE);
}
// Lookup the property locally in the receiver. // Lookup the property locally in the receiver.
if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
LookupResult lookup; LookupResult lookup;

7
deps/v8/src/jump-target-inl.h

@ -28,6 +28,8 @@
#ifndef V8_JUMP_TARGET_INL_H_ #ifndef V8_JUMP_TARGET_INL_H_
#define V8_JUMP_TARGET_INL_H_ #define V8_JUMP_TARGET_INL_H_
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -36,14 +38,15 @@ CodeGenerator* JumpTarget::cgen() {
} }
void JumpTarget::InitializeEntryElement(int index, FrameElement* target) { void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
entry_frame_->elements_[index].clear_copied(); FrameElement* element = &entry_frame_->elements_[index];
element->clear_copied();
if (target->is_register()) { if (target->is_register()) {
entry_frame_->set_register_location(target->reg(), index); entry_frame_->set_register_location(target->reg(), index);
} else if (target->is_copy()) { } else if (target->is_copy()) {
entry_frame_->elements_[target->index()].set_copied(); entry_frame_->elements_[target->index()].set_copied();
} }
if (direction_ == BIDIRECTIONAL && !target->is_copy()) { if (direction_ == BIDIRECTIONAL && !target->is_copy()) {
entry_frame_->elements_[index].set_number_info(NumberInfo::kUnknown); element->set_number_info(NumberInfo::kUnknown);
} }
} }

3
deps/v8/src/jump-target.cc

@ -100,9 +100,8 @@ void JumpTarget::ComputeEntryFrame() {
// change our decision about undetermined or invalid elements. // change our decision about undetermined or invalid elements.
if (element == NULL || !element->is_valid()) break; if (element == NULL || !element->is_valid()) break;
element = element->Combine(&reaching_frames_[j]->elements_[i]);
FrameElement* other = &reaching_frames_[j]->elements_[i]; FrameElement* other = &reaching_frames_[j]->elements_[i];
element = element->Combine(other);
if (element != NULL && !element->is_copy()) { if (element != NULL && !element->is_copy()) {
ASSERT(other != NULL); ASSERT(other != NULL);
// We overwrite the number information of one of the incoming frames. // We overwrite the number information of one of the incoming frames.

1
deps/v8/src/register-allocator-inl.h

@ -30,7 +30,6 @@
#include "codegen.h" #include "codegen.h"
#include "register-allocator.h" #include "register-allocator.h"
#include "virtual-frame.h"
#if V8_TARGET_ARCH_IA32 #if V8_TARGET_ARCH_IA32
#include "ia32/register-allocator-ia32-inl.h" #include "ia32/register-allocator-ia32-inl.h"

1
deps/v8/src/register-allocator.cc

@ -29,6 +29,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

2
deps/v8/src/version.cc

@ -35,7 +35,7 @@
#define MAJOR_VERSION 2 #define MAJOR_VERSION 2
#define MINOR_VERSION 1 #define MINOR_VERSION 1
#define BUILD_NUMBER 2 #define BUILD_NUMBER 2
#define PATCH_LEVEL 0 #define PATCH_LEVEL 6
#define CANDIDATE_VERSION false #define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the // Define SONAME to have the SCons build the put a specific SONAME into the

109
deps/v8/src/virtual-frame-inl.h

@ -0,0 +1,109 @@
// Copyright 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.
#ifndef V8_VIRTUAL_FRAME_INL_H_
#define V8_VIRTUAL_FRAME_INL_H_
#include "virtual-frame.h"
namespace v8 {
namespace internal {
// When cloned, a frame is a deep copy of the original.
VirtualFrame::VirtualFrame(VirtualFrame* original)
: elements_(original->element_count()),
stack_pointer_(original->stack_pointer_) {
elements_.AddAll(original->elements_);
// Copy register locations from original.
memcpy(&register_locations_,
original->register_locations_,
sizeof(register_locations_));
}
void VirtualFrame::PushFrameSlotAt(int index) {
elements_.Add(CopyElementAt(index));
}
void VirtualFrame::Push(Register reg, NumberInfo::Type info) {
if (is_used(reg)) {
int index = register_location(reg);
FrameElement element = CopyElementAt(index, info);
elements_.Add(element);
} else {
Use(reg, element_count());
FrameElement element =
FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED, info);
elements_.Add(element);
}
}
void VirtualFrame::Push(Handle<Object> value) {
FrameElement element =
FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED);
elements_.Add(element);
}
void VirtualFrame::Push(Smi* value) {
Push(Handle<Object> (value));
}
void VirtualFrame::Nip(int num_dropped) {
ASSERT(num_dropped >= 0);
if (num_dropped == 0) return;
Result tos = Pop();
if (num_dropped > 1) {
Drop(num_dropped - 1);
}
SetElementAt(0, &tos);
}
bool VirtualFrame::Equals(VirtualFrame* other) {
#ifdef DEBUG
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (register_location(i) != other->register_location(i)) {
return false;
}
}
if (element_count() != other->element_count()) return false;
#endif
if (stack_pointer_ != other->stack_pointer_) return false;
for (int i = 0; i < element_count(); i++) {
if (!elements_[i].Equals(other->elements_[i])) return false;
}
return true;
}
} } // namespace v8::internal
#endif // V8_VIRTUAL_FRAME_INL_H_

68
deps/v8/src/virtual-frame.cc

@ -29,6 +29,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -36,18 +37,6 @@ namespace internal {
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// VirtualFrame implementation. // VirtualFrame implementation.
// When cloned, a frame is a deep copy of the original.
VirtualFrame::VirtualFrame(VirtualFrame* original)
: elements_(original->element_count()),
stack_pointer_(original->stack_pointer_) {
elements_.AddAll(original->elements_);
// Copy register locations from original.
memcpy(&register_locations_,
original->register_locations_,
sizeof(register_locations_));
}
// Create a duplicate of an existing valid frame element. // Create a duplicate of an existing valid frame element.
// We can pass an optional number type information that will override the // We can pass an optional number type information that will override the
// existing information about the backing element. The new information must // existing information about the backing element. The new information must
@ -338,61 +327,6 @@ void VirtualFrame::SetElementAt(int index, Result* value) {
} }
void VirtualFrame::PushFrameSlotAt(int index) {
elements_.Add(CopyElementAt(index));
}
void VirtualFrame::Push(Register reg, NumberInfo::Type info) {
if (is_used(reg)) {
int index = register_location(reg);
FrameElement element = CopyElementAt(index, info);
elements_.Add(element);
} else {
Use(reg, element_count());
FrameElement element =
FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED, info);
elements_.Add(element);
}
}
void VirtualFrame::Push(Handle<Object> value) {
FrameElement element =
FrameElement::ConstantElement(value, FrameElement::NOT_SYNCED);
elements_.Add(element);
}
void VirtualFrame::Nip(int num_dropped) {
ASSERT(num_dropped >= 0);
if (num_dropped == 0) return;
Result tos = Pop();
if (num_dropped > 1) {
Drop(num_dropped - 1);
}
SetElementAt(0, &tos);
}
bool VirtualFrame::Equals(VirtualFrame* other) {
#ifdef DEBUG
for (int i = 0; i < RegisterAllocator::kNumRegisters; i++) {
if (register_location(i) != other->register_location(i)) {
return false;
}
}
if (element_count() != other->element_count()) return false;
#endif
if (stack_pointer_ != other->stack_pointer_) return false;
for (int i = 0; i < element_count(); i++) {
if (!elements_[i].Equals(other->elements_[i])) return false;
}
return true;
}
// Specialization of List::ResizeAdd to non-inlined version for FrameElements. // Specialization of List::ResizeAdd to non-inlined version for FrameElements.
// The function ResizeAdd becomes a real function, whose implementation is the // The function ResizeAdd becomes a real function, whose implementation is the
// inlined ResizeAddInternal. // inlined ResizeAddInternal.

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

@ -36,6 +36,7 @@
#include "regexp-macro-assembler.h" #include "regexp-macro-assembler.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "scopes.h" #include "scopes.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -259,9 +260,6 @@ CodeGenerator::CodeGenerator(MacroAssembler* masm)
} }
Scope* CodeGenerator::scope() { return info_->function()->scope(); }
void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { void CodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
// Call the runtime to declare the globals. The inevitable call // Call the runtime to declare the globals. The inevitable call
// will sync frame elements to memory anyway, so we do it eagerly to // will sync frame elements to memory anyway, so we do it eagerly to

2
deps/v8/src/x64/codegen-x64.h

@ -343,7 +343,7 @@ class CodeGenerator: public AstVisitor {
// Accessors // Accessors
inline bool is_eval(); inline bool is_eval();
Scope* scope(); inline Scope* scope();
// Generating deferred code. // Generating deferred code.
void ProcessDeferred(); void ProcessDeferred();

1
deps/v8/src/x64/fast-codegen-x64.cc

@ -29,6 +29,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "fast-codegen.h" #include "fast-codegen.h"
#include "scopes.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/x64/full-codegen-x64.cc

@ -32,6 +32,7 @@
#include "debug.h" #include "debug.h"
#include "full-codegen.h" #include "full-codegen.h"
#include "parser.h" #include "parser.h"
#include "scopes.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/x64/jump-target-x64.cc

@ -30,6 +30,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "jump-target-inl.h" #include "jump-target-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/x64/register-allocator-x64.cc

@ -29,6 +29,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

1
deps/v8/src/x64/virtual-frame-x64.cc

@ -30,6 +30,7 @@
#include "codegen-inl.h" #include "codegen-inl.h"
#include "register-allocator-inl.h" #include "register-allocator-inl.h"
#include "scopes.h" #include "scopes.h"
#include "virtual-frame-inl.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

14
deps/v8/src/x64/virtual-frame-x64.h

@ -76,7 +76,7 @@ class VirtualFrame : public ZoneObject {
VirtualFrame(); VirtualFrame();
// Construct a virtual frame as a clone of an existing one. // Construct a virtual frame as a clone of an existing one.
explicit VirtualFrame(VirtualFrame* original); explicit inline VirtualFrame(VirtualFrame* original);
CodeGenerator* cgen() { return CodeGeneratorScope::Current(); } CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
MacroAssembler* masm() { return cgen()->masm(); } MacroAssembler* masm() { return cgen()->masm(); }
@ -395,9 +395,9 @@ class VirtualFrame : public ZoneObject {
void EmitPush(Handle<Object> value); void EmitPush(Handle<Object> value);
// Push an element on the virtual frame. // Push an element on the virtual frame.
void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown); inline void Push(Register reg, NumberInfo::Type info = NumberInfo::kUnknown);
void Push(Handle<Object> value); inline void Push(Handle<Object> value);
void Push(Smi* value) { Push(Handle<Object>(value)); } inline void Push(Smi* value);
// Pushing a result invalidates it (its contents become owned by the // Pushing a result invalidates it (its contents become owned by the
// frame). // frame).
@ -414,7 +414,7 @@ class VirtualFrame : public ZoneObject {
// Nip removes zero or more elements from immediately below the top // Nip removes zero or more elements from immediately below the top
// of the frame, leaving the previous top-of-frame value on top of // of the frame, leaving the previous top-of-frame value on top of
// the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x). // the frame. Nip(k) is equivalent to x = Pop(), Drop(k), Push(x).
void Nip(int num_dropped); inline void Nip(int num_dropped);
private: private:
static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset; static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
@ -506,7 +506,7 @@ class VirtualFrame : public ZoneObject {
// Push a copy of a frame slot (typically a local or parameter) on top of // Push a copy of a frame slot (typically a local or parameter) on top of
// the frame. // the frame.
void PushFrameSlotAt(int index); inline void PushFrameSlotAt(int index);
// Push a the value of a frame slot (typically a local or parameter) on // Push a the value of a frame slot (typically a local or parameter) on
// top of the frame and invalidate the slot. // top of the frame and invalidate the slot.
@ -557,7 +557,7 @@ class VirtualFrame : public ZoneObject {
// (via PrepareForCall). // (via PrepareForCall).
Result RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode); Result RawCallCodeObject(Handle<Code> code, RelocInfo::Mode rmode);
bool Equals(VirtualFrame* other); inline bool Equals(VirtualFrame* other);
// Classes that need raw access to the elements_ array. // Classes that need raw access to the elements_ array.
friend class DeferredCode; friend class DeferredCode;

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

@ -6433,6 +6433,45 @@ THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss2) {
CHECK_GE(interceptor_call_count, 50); CHECK_GE(interceptor_call_count, 50);
} }
THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_Miss3) {
int interceptor_call_count = 0;
v8::HandleScope scope;
v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
v8::Handle<v8::FunctionTemplate> method_templ =
v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
v8_str("method_data"),
v8::Signature::New(fun_templ));
v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
proto_templ->Set(v8_str("method"), method_templ);
v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
templ->SetNamedPropertyHandler(InterceptorCallICFastApi,
NULL, NULL, NULL, NULL,
v8::External::Wrap(&interceptor_call_count));
LocalContext context;
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::TryCatch try_catch;
v8::Handle<Value> value = CompileRun(
"o.foo = 17;"
"var receiver = {};"
"receiver.__proto__ = o;"
"var result = 0;"
"var saved_result = 0;"
"for (var i = 0; i < 100; i++) {"
" result = receiver.method(41);"
" if (i == 50) {"
" saved_result = result;"
" receiver = 333;"
" }"
"}");
CHECK(try_catch.HasCaught());
CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
try_catch.Exception()->ToString());
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
CHECK_GE(interceptor_call_count, 50);
}
THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) { THREADED_TEST(InterceptorCallICFastApi_SimpleSignature_TypeError) {
int interceptor_call_count = 0; int interceptor_call_count = 0;
v8::HandleScope scope; v8::HandleScope scope;
@ -6521,7 +6560,7 @@ THREADED_TEST(CallICFastApi_SimpleSignature) {
CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value()); CHECK_EQ(42, context->Global()->Get(v8_str("result"))->Int32Value());
} }
THREADED_TEST(CallICFastApi_SimpleSignature_Miss) { THREADED_TEST(CallICFastApi_SimpleSignature_Miss1) {
v8::HandleScope scope; v8::HandleScope scope;
v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New(); v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
v8::Handle<v8::FunctionTemplate> method_templ = v8::Handle<v8::FunctionTemplate> method_templ =
@ -6552,6 +6591,40 @@ THREADED_TEST(CallICFastApi_SimpleSignature_Miss) {
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value()); CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
} }
THREADED_TEST(CallICFastApi_SimpleSignature_Miss2) {
v8::HandleScope scope;
v8::Handle<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
v8::Handle<v8::FunctionTemplate> method_templ =
v8::FunctionTemplate::New(FastApiCallback_SimpleSignature,
v8_str("method_data"),
v8::Signature::New(fun_templ));
v8::Handle<v8::ObjectTemplate> proto_templ = fun_templ->PrototypeTemplate();
proto_templ->Set(v8_str("method"), method_templ);
v8::Handle<v8::ObjectTemplate> templ = fun_templ->InstanceTemplate();
LocalContext context;
v8::Handle<v8::Function> fun = fun_templ->GetFunction();
GenerateSomeGarbage();
context->Global()->Set(v8_str("o"), fun->NewInstance());
v8::TryCatch try_catch;
v8::Handle<Value> value = CompileRun(
"o.foo = 17;"
"var receiver = {};"
"receiver.__proto__ = o;"
"var result = 0;"
"var saved_result = 0;"
"for (var i = 0; i < 100; i++) {"
" result = receiver.method(41);"
" if (i == 50) {"
" saved_result = result;"
" receiver = 333;"
" }"
"}");
CHECK(try_catch.HasCaught());
CHECK_EQ(v8_str("TypeError: Object 333 has no method 'method'"),
try_catch.Exception()->ToString());
CHECK_EQ(42, context->Global()->Get(v8_str("saved_result"))->Int32Value());
}
static int interceptor_call_count = 0; static int interceptor_call_count = 0;

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

@ -40,6 +40,7 @@ v8::Handle<v8::Value> Signal(const v8::Arguments& args) {
v8::Handle<v8::Value> TerminateCurrentThread(const v8::Arguments& args) { v8::Handle<v8::Value> TerminateCurrentThread(const v8::Arguments& args) {
CHECK(!v8::V8::IsExecutionTerminating());
v8::V8::TerminateExecution(); v8::V8::TerminateExecution();
return v8::Undefined(); return v8::Undefined();
} }
@ -52,15 +53,19 @@ v8::Handle<v8::Value> Fail(const v8::Arguments& args) {
v8::Handle<v8::Value> Loop(const v8::Arguments& args) { v8::Handle<v8::Value> Loop(const v8::Arguments& args) {
CHECK(!v8::V8::IsExecutionTerminating());
v8::Handle<v8::String> source = v8::Handle<v8::String> source =
v8::String::New("try { doloop(); fail(); } catch(e) { fail(); }"); v8::String::New("try { doloop(); fail(); } catch(e) { fail(); }");
v8::Script::Compile(source)->Run(); v8::Handle<v8::Value> result = v8::Script::Compile(source)->Run();
CHECK(result.IsEmpty());
CHECK(v8::V8::IsExecutionTerminating());
return v8::Undefined(); return v8::Undefined();
} }
v8::Handle<v8::Value> DoLoop(const v8::Arguments& args) { v8::Handle<v8::Value> DoLoop(const v8::Arguments& args) {
v8::TryCatch try_catch; v8::TryCatch try_catch;
CHECK(!v8::V8::IsExecutionTerminating());
v8::Script::Compile(v8::String::New("function f() {" v8::Script::Compile(v8::String::New("function f() {"
" var term = true;" " var term = true;"
" try {" " try {"
@ -78,12 +83,14 @@ v8::Handle<v8::Value> DoLoop(const v8::Arguments& args) {
CHECK(try_catch.Exception()->IsNull()); CHECK(try_catch.Exception()->IsNull());
CHECK(try_catch.Message().IsEmpty()); CHECK(try_catch.Message().IsEmpty());
CHECK(!try_catch.CanContinue()); CHECK(!try_catch.CanContinue());
CHECK(v8::V8::IsExecutionTerminating());
return v8::Undefined(); return v8::Undefined();
} }
v8::Handle<v8::Value> DoLoopNoCall(const v8::Arguments& args) { v8::Handle<v8::Value> DoLoopNoCall(const v8::Arguments& args) {
v8::TryCatch try_catch; v8::TryCatch try_catch;
CHECK(!v8::V8::IsExecutionTerminating());
v8::Script::Compile(v8::String::New("var term = true;" v8::Script::Compile(v8::String::New("var term = true;"
"while(true) {" "while(true) {"
" if (term) terminate();" " if (term) terminate();"
@ -93,6 +100,7 @@ v8::Handle<v8::Value> DoLoopNoCall(const v8::Arguments& args) {
CHECK(try_catch.Exception()->IsNull()); CHECK(try_catch.Exception()->IsNull());
CHECK(try_catch.Message().IsEmpty()); CHECK(try_catch.Message().IsEmpty());
CHECK(!try_catch.CanContinue()); CHECK(!try_catch.CanContinue());
CHECK(v8::V8::IsExecutionTerminating());
return v8::Undefined(); return v8::Undefined();
} }
@ -118,11 +126,13 @@ TEST(TerminateOnlyV8ThreadFromThreadItself) {
CreateGlobalTemplate(TerminateCurrentThread, DoLoop); CreateGlobalTemplate(TerminateCurrentThread, DoLoop);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
CHECK(!v8::V8::IsExecutionTerminating());
// Run a loop that will be infinite if thread termination does not work. // Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source = v8::Handle<v8::String> source =
v8::String::New("try { loop(); fail(); } catch(e) { fail(); }"); v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
v8::Script::Compile(source)->Run(); v8::Script::Compile(source)->Run();
// Test that we can run the code again after thread termination. // Test that we can run the code again after thread termination.
CHECK(!v8::V8::IsExecutionTerminating());
v8::Script::Compile(source)->Run(); v8::Script::Compile(source)->Run();
context.Dispose(); context.Dispose();
} }
@ -136,10 +146,12 @@ TEST(TerminateOnlyV8ThreadFromThreadItselfNoLoop) {
CreateGlobalTemplate(TerminateCurrentThread, DoLoopNoCall); CreateGlobalTemplate(TerminateCurrentThread, DoLoopNoCall);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
CHECK(!v8::V8::IsExecutionTerminating());
// Run a loop that will be infinite if thread termination does not work. // Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source = v8::Handle<v8::String> source =
v8::String::New("try { loop(); fail(); } catch(e) { fail(); }"); v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
v8::Script::Compile(source)->Run(); v8::Script::Compile(source)->Run();
CHECK(!v8::V8::IsExecutionTerminating());
// Test that we can run the code again after thread termination. // Test that we can run the code again after thread termination.
v8::Script::Compile(source)->Run(); v8::Script::Compile(source)->Run();
context.Dispose(); context.Dispose();
@ -149,6 +161,7 @@ TEST(TerminateOnlyV8ThreadFromThreadItselfNoLoop) {
class TerminatorThread : public v8::internal::Thread { class TerminatorThread : public v8::internal::Thread {
void Run() { void Run() {
semaphore->Wait(); semaphore->Wait();
CHECK(!v8::V8::IsExecutionTerminating());
v8::V8::TerminateExecution(); v8::V8::TerminateExecution();
} }
}; };
@ -165,6 +178,7 @@ TEST(TerminateOnlyV8ThreadFromOtherThread) {
v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal, DoLoop); v8::Handle<v8::ObjectTemplate> global = CreateGlobalTemplate(Signal, DoLoop);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
CHECK(!v8::V8::IsExecutionTerminating());
// Run a loop that will be infinite if thread termination does not work. // Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source = v8::Handle<v8::String> source =
v8::String::New("try { loop(); fail(); } catch(e) { fail(); }"); v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
@ -187,6 +201,7 @@ class LoopingThread : public v8::internal::Thread {
CreateGlobalTemplate(Signal, DoLoop); CreateGlobalTemplate(Signal, DoLoop);
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
CHECK(!v8::V8::IsExecutionTerminating());
// Run a loop that will be infinite if thread termination does not work. // Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source = v8::Handle<v8::String> source =
v8::String::New("try { loop(); fail(); } catch(e) { fail(); }"); v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
@ -235,6 +250,7 @@ int call_count = 0;
v8::Handle<v8::Value> TerminateOrReturnObject(const v8::Arguments& args) { v8::Handle<v8::Value> TerminateOrReturnObject(const v8::Arguments& args) {
if (++call_count == 10) { if (++call_count == 10) {
CHECK(!v8::V8::IsExecutionTerminating());
v8::V8::TerminateExecution(); v8::V8::TerminateExecution();
return v8::Undefined(); return v8::Undefined();
} }
@ -246,6 +262,7 @@ v8::Handle<v8::Value> TerminateOrReturnObject(const v8::Arguments& args) {
v8::Handle<v8::Value> LoopGetProperty(const v8::Arguments& args) { v8::Handle<v8::Value> LoopGetProperty(const v8::Arguments& args) {
v8::TryCatch try_catch; v8::TryCatch try_catch;
CHECK(!v8::V8::IsExecutionTerminating());
v8::Script::Compile(v8::String::New("function f() {" v8::Script::Compile(v8::String::New("function f() {"
" try {" " try {"
" while(true) {" " while(true) {"
@ -261,6 +278,7 @@ v8::Handle<v8::Value> LoopGetProperty(const v8::Arguments& args) {
CHECK(try_catch.Exception()->IsNull()); CHECK(try_catch.Exception()->IsNull());
CHECK(try_catch.Message().IsEmpty()); CHECK(try_catch.Message().IsEmpty());
CHECK(!try_catch.CanContinue()); CHECK(!try_catch.CanContinue());
CHECK(v8::V8::IsExecutionTerminating());
return v8::Undefined(); return v8::Undefined();
} }
@ -278,12 +296,14 @@ TEST(TerminateLoadICException) {
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global); v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);
CHECK(!v8::V8::IsExecutionTerminating());
// Run a loop that will be infinite if thread termination does not work. // Run a loop that will be infinite if thread termination does not work.
v8::Handle<v8::String> source = v8::Handle<v8::String> source =
v8::String::New("try { loop(); fail(); } catch(e) { fail(); }"); v8::String::New("try { loop(); fail(); } catch(e) { fail(); }");
call_count = 0; call_count = 0;
v8::Script::Compile(source)->Run(); v8::Script::Compile(source)->Run();
// Test that we can run the code again after thread termination. // Test that we can run the code again after thread termination.
CHECK(!v8::V8::IsExecutionTerminating());
call_count = 0; call_count = 0;
v8::Script::Compile(source)->Run(); v8::Script::Compile(source)->Run();
context.Dispose(); context.Dispose();

1
deps/v8/tools/gyp/v8.gyp

@ -391,6 +391,7 @@
'../../src/variables.h', '../../src/variables.h',
'../../src/version.cc', '../../src/version.cc',
'../../src/version.h', '../../src/version.h',
'../../src/virtual-frame-inl.h',
'../../src/virtual-frame.h', '../../src/virtual-frame.h',
'../../src/virtual-frame.cc', '../../src/virtual-frame.cc',
'../../src/zone-inl.h', '../../src/zone-inl.h',

4
deps/v8/tools/visual_studio/v8_base.vcproj

@ -936,6 +936,10 @@
RelativePath="..\..\src\version.h" RelativePath="..\..\src\version.h"
> >
</File> </File>
<File
RelativePath="..\..\src\virtual-frame-inl.h"
>
</File>
<File <File
RelativePath="..\..\src\virtual-frame.h" RelativePath="..\..\src\virtual-frame.h"
> >

4
deps/v8/tools/visual_studio/v8_base_arm.vcproj

@ -948,6 +948,10 @@
RelativePath="..\..\src\version.h" RelativePath="..\..\src\version.h"
> >
</File> </File>
<File
RelativePath="..\..\src\virtual-frame-inl.h"
>
</File>
<File <File
RelativePath="..\..\src\virtual-frame.h" RelativePath="..\..\src\virtual-frame.h"
> >

4
deps/v8/tools/visual_studio/v8_base_x64.vcproj

@ -937,6 +937,10 @@
RelativePath="..\..\src\version.h" RelativePath="..\..\src\version.h"
> >
</File> </File>
<File
RelativePath="..\..\src\virtual-frame-inl.h"
>
</File>
<File <File
RelativePath="..\..\src\virtual-frame.h" RelativePath="..\..\src\virtual-frame.h"
> >

Loading…
Cancel
Save