From ce5adc76847edf10dc843f5c93485e393f0ca099 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Thu, 20 Oct 2011 10:31:42 +0200 Subject: Revert "Update V8" This reverts commit 1c4a5fcab76d1b769a4c0369d40dd0dd7c0e7495 Several of the qtdeclarative tests and examples are dying randomly with messages like this: > > # > # Fatal error in ../3rdparty/v8/src/objects-inl.h, line 2169 > # CHECK(object->IsJSFunction()) failed > # > > > ==== Stack trace ============================================ > > > ==== Details ================================================ > > ==== Key ============================================ > > ===================== > > Aborted (core dumped) Change-Id: Iebaa2497a6f6ef616ef4c3576c217d2a8a2c1ea5 Reviewed-by: Kent Hansen --- .../0008-Add-custom-object-compare-callback.patch | 489 +++++++++++++++++++++ 1 file changed, 489 insertions(+) create mode 100644 src/v8/0008-Add-custom-object-compare-callback.patch (limited to 'src/v8/0008-Add-custom-object-compare-callback.patch') diff --git a/src/v8/0008-Add-custom-object-compare-callback.patch b/src/v8/0008-Add-custom-object-compare-callback.patch new file mode 100644 index 0000000000..125668805e --- /dev/null +++ b/src/v8/0008-Add-custom-object-compare-callback.patch @@ -0,0 +1,489 @@ +From a7c491e6e533110a17fe9f7d47cf92a1b2263180 Mon Sep 17 00:00:00 2001 +From: Aaron Kennedy +Date: Mon, 27 Jun 2011 14:57:28 +1000 +Subject: [PATCH 08/16] Add custom object compare callback + +A global custom object comparison callback can be set with: + V8::SetUserObjectComparisonCallbackFunction() +When two JSObjects are compared (== or !=), if either one has +the MarkAsUseUserObjectComparison() bit set, the custom comparison +callback is invoked to do the actual comparison. + +This is useful when you have "value" objects that you want to +compare as equal, even though they are actually different JS object +instances. +--- + include/v8.h | 13 +++++++++++++ + src/api.cc | 19 +++++++++++++++++++ + src/arm/code-stubs-arm.cc | 42 ++++++++++++++++++++++++++++++++++++++++-- + src/factory.cc | 8 ++++++++ + src/ia32/code-stubs-ia32.cc | 40 ++++++++++++++++++++++++++++++++++++++++ + src/isolate.h | 8 ++++++++ + src/objects-inl.h | 15 +++++++++++++++ + src/objects.h | 10 +++++++++- + src/runtime.cc | 23 +++++++++++++++++++++++ + src/runtime.h | 1 + + src/top.cc | 5 +++++ + src/x64/code-stubs-x64.cc | 37 +++++++++++++++++++++++++++++++++++++ + 12 files changed, 218 insertions(+), 3 deletions(-) + +diff --git a/include/v8.h b/include/v8.h +index 99f4b9a..7544deb 100644 +--- a/include/v8.h ++++ b/include/v8.h +@@ -2366,6 +2366,12 @@ class V8EXPORT ObjectTemplate : public Template { + bool HasExternalResource(); + void SetHasExternalResource(bool value); + ++ /** ++ * Mark object instances of the template as using the user object ++ * comparison callback. ++ */ ++ void MarkAsUseUserObjectComparison(); ++ + private: + ObjectTemplate(); + static Local New(Handle constructor); +@@ -2566,6 +2572,10 @@ typedef void (*FailedAccessCheckCallback)(Local target, + AccessType type, + Local data); + ++// --- U s e r O b j e c t C o m p a r i s o n C a l l b a c k --- ++typedef bool (*UserObjectComparisonCallback)(Local lhs, ++ Local rhs); ++ + // --- G a r b a g e C o l l e c t i o n C a l l b a c k s + + /** +@@ -2816,6 +2826,9 @@ class V8EXPORT V8 { + /** Callback function for reporting failed access checks.*/ + static void SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback); + ++ /** Callback for user object comparisons */ ++ static void SetUserObjectComparisonCallbackFunction(UserObjectComparisonCallback); ++ + /** + * Enables the host application to receive a notification before a + * garbage collection. Allocations are not allowed in the +diff --git a/src/api.cc b/src/api.cc +index ff74efb..2436031 100644 +--- a/src/api.cc ++++ b/src/api.cc +@@ -1321,6 +1321,16 @@ void ObjectTemplate::SetHasExternalResource(bool value) + } + } + ++void ObjectTemplate::MarkAsUseUserObjectComparison() ++{ ++ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ++ if (IsDeadCheck(isolate, "v8::ObjectTemplate::MarkAsUseUserObjectComparison()")) { ++ return; ++ } ++ ENTER_V8(isolate); ++ EnsureConstructor(this); ++ Utils::OpenHandle(this)->set_use_user_object_comparison(i::Smi::FromInt(1)); ++} + + // --- S c r i p t D a t a --- + +@@ -4632,6 +4642,15 @@ void V8::SetFailedAccessCheckCallbackFunction( + isolate->SetFailedAccessCheckCallback(callback); + } + ++void V8::SetUserObjectComparisonCallbackFunction( ++ UserObjectComparisonCallback callback) { ++ i::Isolate* isolate = i::Isolate::Current(); ++ if (IsDeadCheck(isolate, "v8::V8::SetUserObjectComparisonCallbackFunction()")) { ++ return; ++ } ++ isolate->SetUserObjectComparisonCallback(callback); ++} ++ + void V8::AddObjectGroup(Persistent* objects, + size_t length, + RetainedObjectInfo* info) { +diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc +index a2626bf..749c9be 100644 +--- a/src/arm/code-stubs-arm.cc ++++ b/src/arm/code-stubs-arm.cc +@@ -1563,6 +1563,36 @@ void CompareStub::Generate(MacroAssembler* masm) { + // NOTICE! This code is only reached after a smi-fast-case check, so + // it is certain that at least one operand isn't a smi. + ++ { ++ Label not_user_equal, user_equal; ++ __ and_(r2, r1, Operand(r0)); ++ __ tst(r2, Operand(kSmiTagMask)); ++ __ b(eq, ¬_user_equal); ++ ++ __ CompareObjectType(r0, r2, r4, JS_OBJECT_TYPE); ++ __ b(ne, ¬_user_equal); ++ ++ __ CompareObjectType(r1, r3, r4, JS_OBJECT_TYPE); ++ __ b(ne, ¬_user_equal); ++ ++ __ ldrb(r2, FieldMemOperand(r2, Map::kBitField3Offset)); ++ __ and_(r2, r2, Operand(1 << Map::kUseUserObjectComparison)); ++ __ cmp(r2, Operand(1 << Map::kUseUserObjectComparison)); ++ __ b(eq, &user_equal); ++ ++ __ ldrb(r3, FieldMemOperand(r3, Map::kBitField3Offset)); ++ __ and_(r3, r3, Operand(1 << Map::kUseUserObjectComparison)); ++ __ cmp(r3, Operand(1 << Map::kUseUserObjectComparison)); ++ __ b(ne, ¬_user_equal); ++ ++ __ bind(&user_equal); ++ ++ __ Push(r0, r1); ++ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1); ++ ++ __ bind(¬_user_equal); ++ } ++ + // Handle the case where the objects are identical. Either returns the answer + // or goes to slow. Only falls through if the objects were not identical. + EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_); +@@ -5802,10 +5832,18 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) { + __ tst(r2, Operand(kSmiTagMask)); + __ b(eq, &miss); + +- __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE); ++ __ CompareObjectType(r0, r2, r3, JS_OBJECT_TYPE); + __ b(ne, &miss); +- __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE); ++ __ ldrb(r2, FieldMemOperand(r2, Map::kBitField3Offset)); ++ __ and_(r2, r2, Operand(1 << Map::kUseUserObjectComparison)); ++ __ cmp(r2, Operand(1 << Map::kUseUserObjectComparison)); ++ __ b(eq, &miss); ++ __ CompareObjectType(r1, r2, r3, JS_OBJECT_TYPE); + __ b(ne, &miss); ++ __ ldrb(r2, FieldMemOperand(r2, Map::kBitField3Offset)); ++ __ and_(r2, r2, Operand(1 << Map::kUseUserObjectComparison)); ++ __ cmp(r2, Operand(1 << Map::kUseUserObjectComparison)); ++ __ b(eq, &miss); + + ASSERT(GetCondition() == eq); + __ sub(r0, r0, Operand(r1)); +diff --git a/src/factory.cc b/src/factory.cc +index d530a75..6f8c7de 100644 +--- a/src/factory.cc ++++ b/src/factory.cc +@@ -998,6 +998,7 @@ Handle Factory::CreateApiFunction( + + int internal_field_count = 0; + bool has_external_resource = false; ++ bool use_user_object_comparison = false; + + if (!obj->instance_template()->IsUndefined()) { + Handle instance_template = +@@ -1007,6 +1008,8 @@ Handle Factory::CreateApiFunction( + Smi::cast(instance_template->internal_field_count())->value(); + has_external_resource = + !instance_template->has_external_resource()->IsUndefined(); ++ use_user_object_comparison = ++ !instance_template->use_user_object_comparison()->IsUndefined(); + } + + int instance_size = kPointerSize * internal_field_count; +@@ -1051,6 +1054,11 @@ Handle Factory::CreateApiFunction( + map->set_has_external_resource(true); + } + ++ // Mark as using user object comparison if needed ++ if (use_user_object_comparison) { ++ map->set_use_user_object_comparison(true); ++ } ++ + // Mark as undetectable if needed. + if (obj->undetectable()) { + map->set_is_undetectable(); +diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc +index afa599e..0964ab9 100644 +--- a/src/ia32/code-stubs-ia32.cc ++++ b/src/ia32/code-stubs-ia32.cc +@@ -3447,6 +3447,40 @@ void CompareStub::Generate(MacroAssembler* masm) { + __ Assert(not_zero, "Unexpected smi operands."); + } + ++ { ++ NearLabel not_user_equal, user_equal; ++ __ test(eax, Immediate(kSmiTagMask)); ++ __ j(zero, ¬_user_equal); ++ __ test(edx, Immediate(kSmiTagMask)); ++ __ j(zero, ¬_user_equal); ++ ++ __ CmpObjectType(eax, JS_OBJECT_TYPE, ebx); ++ __ j(not_equal, ¬_user_equal); ++ ++ __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); ++ __ j(not_equal, ¬_user_equal); ++ ++ __ test_b(FieldOperand(ebx, Map::kBitField3Offset), ++ 1 << Map::kUseUserObjectComparison); ++ __ j(not_zero, &user_equal); ++ __ test_b(FieldOperand(ecx, Map::kBitField3Offset), ++ 1 << Map::kUseUserObjectComparison); ++ __ j(not_zero, &user_equal); ++ ++ __ jmp(¬_user_equal); ++ ++ __ bind(&user_equal); ++ ++ __ pop(ebx); // Return address. ++ __ push(eax); ++ __ push(edx); ++ __ push(ebx); ++ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1); ++ ++ __ bind(¬_user_equal); ++ } ++ ++ + // NOTICE! This code is only reached after a smi-fast-case check, so + // it is certain that at least one operand isn't a smi. + +@@ -5592,8 +5626,14 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) { + + __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); + __ j(not_equal, &miss, not_taken); ++ __ test_b(FieldOperand(ecx, Map::kBitField3Offset), ++ 1 << Map::kUseUserObjectComparison); ++ __ j(not_zero, &miss); + __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); + __ j(not_equal, &miss, not_taken); ++ __ test_b(FieldOperand(ecx, Map::kBitField3Offset), ++ 1 << Map::kUseUserObjectComparison); ++ __ j(not_zero, &miss); + + ASSERT(GetCondition() == equal); + __ sub(eax, Operand(edx)); +diff --git a/src/isolate.h b/src/isolate.h +index 35ffcb4..8130397 100644 +--- a/src/isolate.h ++++ b/src/isolate.h +@@ -267,6 +267,9 @@ class ThreadLocalTop BASE_EMBEDDED { + // Call back function to report unsafe JS accesses. + v8::FailedAccessCheckCallback failed_access_check_callback_; + ++ // Call back function for user object comparisons ++ v8::UserObjectComparisonCallback user_object_comparison_callback_; ++ + private: + void InitializeInternal(); + +@@ -699,6 +702,11 @@ class Isolate { + void SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback); + void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type); + ++ void SetUserObjectComparisonCallback(v8::UserObjectComparisonCallback callback); ++ inline v8::UserObjectComparisonCallback UserObjectComparisonCallback() { ++ return thread_local_top()->user_object_comparison_callback_; ++ } ++ + // Exception throwing support. The caller should use the result + // of Throw() as its return value. + Failure* Throw(Object* exception, MessageLocation* location = NULL); +diff --git a/src/objects-inl.h b/src/objects-inl.h +index 1c7f83e..1765441 100644 +--- a/src/objects-inl.h ++++ b/src/objects-inl.h +@@ -2552,6 +2552,19 @@ bool Map::has_external_resource() + } + + ++void Map::set_use_user_object_comparison(bool value) { ++ if (value) { ++ set_bit_field3(bit_field3() | (1 << kUseUserObjectComparison)); ++ } else { ++ set_bit_field3(bit_field3() & ~(1 << kUseUserObjectComparison)); ++ } ++} ++ ++bool Map::use_user_object_comparison() { ++ return ((1 << kUseUserObjectComparison) & bit_field3()) != 0; ++} ++ ++ + void Map::set_named_interceptor_is_fallback(bool value) + { + if (value) { +@@ -3050,6 +3063,8 @@ ACCESSORS(ObjectTemplateInfo, internal_field_count, Object, + kInternalFieldCountOffset) + ACCESSORS(ObjectTemplateInfo, has_external_resource, Object, + kHasExternalResourceOffset) ++ACCESSORS(ObjectTemplateInfo, use_user_object_comparison, Object, ++ kUseUserObjectComparisonOffset) + + ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset) + ACCESSORS(SignatureInfo, args, Object, kArgsOffset) +diff --git a/src/objects.h b/src/objects.h +index edbc47a..e75e9f1 100644 +--- a/src/objects.h ++++ b/src/objects.h +@@ -3724,6 +3724,11 @@ class Map: public HeapObject { + inline void set_has_external_resource(bool value); + inline bool has_external_resource(); + ++ ++ // Tells whether the user object comparison callback should be used for ++ // comparisons involving this object ++ inline void set_use_user_object_comparison(bool value); ++ inline bool use_user_object_comparison(); + + // Whether the named interceptor is a fallback interceptor or not + inline void set_named_interceptor_is_fallback(bool value); +@@ -3922,6 +3927,7 @@ class Map: public HeapObject { + // Bit positions for bit field 3 + static const int kNamedInterceptorIsFallback = 0; + static const int kHasExternalResource = 1; ++ static const int kUseUserObjectComparison = 2; + + // Layout of the default cache. It holds alternating name and code objects. + static const int kCodeCacheEntrySize = 2; +@@ -6442,6 +6448,7 @@ class ObjectTemplateInfo: public TemplateInfo { + DECL_ACCESSORS(constructor, Object) + DECL_ACCESSORS(internal_field_count, Object) + DECL_ACCESSORS(has_external_resource, Object) ++ DECL_ACCESSORS(use_user_object_comparison, Object) + + static inline ObjectTemplateInfo* cast(Object* obj); + +@@ -6459,7 +6466,8 @@ class ObjectTemplateInfo: public TemplateInfo { + static const int kInternalFieldCountOffset = + kConstructorOffset + kPointerSize; + static const int kHasExternalResourceOffset = kInternalFieldCountOffset + kPointerSize; +- static const int kSize = kHasExternalResourceOffset + kPointerSize; ++ static const int kUseUserObjectComparisonOffset = kHasExternalResourceOffset + kPointerSize; ++ static const int kSize = kUseUserObjectComparisonOffset + kPointerSize; + }; + + +diff --git a/src/runtime.cc b/src/runtime.cc +index c13f92d..b50de80 100644 +--- a/src/runtime.cc ++++ b/src/runtime.cc +@@ -6279,6 +6279,29 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) { + } + + ++RUNTIME_FUNCTION(MaybeObject*, Runtime_UserObjectEquals) { ++ NoHandleAllocation ha; ++ ASSERT(args.length() == 2); ++ ++ CONVERT_CHECKED(JSObject, lhs, args[1]); ++ CONVERT_CHECKED(JSObject, rhs, args[0]); ++ ++ bool result; ++ ++ v8::UserObjectComparisonCallback callback = isolate->UserObjectComparisonCallback(); ++ if (callback) { ++ HandleScope scope(isolate); ++ Handle lhs_handle(lhs); ++ Handle rhs_handle(rhs); ++ result = callback(v8::Utils::ToLocal(lhs_handle), v8::Utils::ToLocal(rhs_handle)); ++ } else { ++ result = (lhs == rhs); ++ } ++ ++ return Smi::FromInt(result?0:1); ++} ++ ++ + RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) { + NoHandleAllocation ha; + ASSERT(args.length() == 3); +diff --git a/src/runtime.h b/src/runtime.h +index 5e97173..0d754f9 100644 +--- a/src/runtime.h ++++ b/src/runtime.h +@@ -146,6 +146,7 @@ namespace internal { + /* Comparisons */ \ + F(NumberEquals, 2, 1) \ + F(StringEquals, 2, 1) \ ++ F(UserObjectEquals, 2, 1) \ + \ + F(NumberCompare, 3, 1) \ + F(SmiLexicographicCompare, 2, 1) \ +diff --git a/src/top.cc b/src/top.cc +index e078ee9..c345383 100644 +--- a/src/top.cc ++++ b/src/top.cc +@@ -68,6 +68,7 @@ void ThreadLocalTop::InitializeInternal() { + thread_id_ = ThreadId::Invalid(); + external_caught_exception_ = false; + failed_access_check_callback_ = NULL; ++ user_object_comparison_callback_ = NULL; + save_context_ = NULL; + catcher_ = NULL; + } +@@ -387,6 +388,10 @@ void Isolate::SetFailedAccessCheckCallback( + thread_local_top()->failed_access_check_callback_ = callback; + } + ++void Isolate::SetUserObjectComparisonCallback( ++ v8::UserObjectComparisonCallback callback) { ++ thread_local_top()->user_object_comparison_callback_ = callback; ++} + + void Isolate::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) { + if (!thread_local_top()->failed_access_check_callback_) return; +diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc +index d923494..10b9b56 100644 +--- a/src/x64/code-stubs-x64.cc ++++ b/src/x64/code-stubs-x64.cc +@@ -2443,6 +2443,37 @@ void CompareStub::Generate(MacroAssembler* masm) { + __ bind(&ok); + } + ++ { ++ NearLabel not_user_equal, user_equal; ++ __ JumpIfSmi(rax, ¬_user_equal); ++ __ JumpIfSmi(rdx, ¬_user_equal); ++ ++ __ CmpObjectType(rax, JS_OBJECT_TYPE, rbx); ++ __ j(not_equal, ¬_user_equal); ++ ++ __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); ++ __ j(not_equal, ¬_user_equal); ++ ++ __ testb(FieldOperand(rbx, Map::kBitField3Offset), ++ Immediate(1 << Map::kUseUserObjectComparison)); ++ __ j(not_zero, &user_equal); ++ __ testb(FieldOperand(rcx, Map::kBitField3Offset), ++ Immediate(1 << Map::kUseUserObjectComparison)); ++ __ j(not_zero, &user_equal); ++ ++ __ jmp(¬_user_equal); ++ ++ __ bind(&user_equal); ++ ++ __ pop(rbx); // Return address. ++ __ push(rax); ++ __ push(rdx); ++ __ push(rbx); ++ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1); ++ ++ __ bind(¬_user_equal); ++ } ++ + // The compare stub returns a positive, negative, or zero 64-bit integer + // value in rax, corresponding to result of comparing the two inputs. + // NOTICE! This code is only reached after a smi-fast-case check, so +@@ -4471,8 +4502,14 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) { + + __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); + __ j(not_equal, &miss, not_taken); ++ __ testb(FieldOperand(rcx, Map::kBitField3Offset), ++ Immediate(1 << Map::kUseUserObjectComparison)); ++ __ j(not_zero, &miss); + __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); + __ j(not_equal, &miss, not_taken); ++ __ testb(FieldOperand(rcx, Map::kBitField3Offset), ++ Immediate(1 << Map::kUseUserObjectComparison)); ++ __ j(not_zero, &miss); + + ASSERT(GetCondition() == equal); + __ subq(rax, rdx); +-- +1.7.4.4 + -- cgit v1.2.3