diff options
Diffstat (limited to 'src/v8/0006-Add-custom-object-compare-callback.patch')
-rw-r--r-- | src/v8/0006-Add-custom-object-compare-callback.patch | 548 |
1 files changed, 0 insertions, 548 deletions
diff --git a/src/v8/0006-Add-custom-object-compare-callback.patch b/src/v8/0006-Add-custom-object-compare-callback.patch deleted file mode 100644 index 51c933580f..0000000000 --- a/src/v8/0006-Add-custom-object-compare-callback.patch +++ /dev/null @@ -1,548 +0,0 @@ -From 59b3da4073971aa725eea8f303f37948dc3bb376 Mon Sep 17 00:00:00 2001 -From: Aaron Kennedy <aaron.kennedy@nokia.com> -Date: Thu, 27 Oct 2011 13:40:00 +0100 -Subject: [PATCH 06/12] 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 | 22 ++++++++++++++++++++++ - src/arm/code-stubs-arm.cc | 43 +++++++++++++++++++++++++++++++++++++++++-- - src/factory.cc | 8 ++++++++ - src/ia32/code-stubs-ia32.cc | 39 +++++++++++++++++++++++++++++++++++++++ - src/isolate.cc | 7 +++++++ - src/isolate.h | 8 ++++++++ - src/objects-inl.h | 21 ++++++++++++++++++--- - src/objects.cc | 8 ++++---- - src/objects.h | 12 ++++++++++-- - src/runtime.cc | 23 +++++++++++++++++++++++ - src/runtime.h | 1 + - src/x64/code-stubs-x64.cc | 37 +++++++++++++++++++++++++++++++++++++ - 13 files changed, 231 insertions(+), 11 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index c094d08..6baf2b2 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -2501,6 +2501,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<ObjectTemplate> New(Handle<FunctionTemplate> constructor); -@@ -2720,6 +2726,10 @@ typedef void (*FailedAccessCheckCallback)(Local<Object> target, - AccessType type, - Local<Value> data); - -+// --- User Object Comparisoa nCallback --- -+typedef bool (*UserObjectComparisonCallback)(Local<Object> lhs, -+ Local<Object> rhs); -+ - // --- AllowCodeGenerationFromStrings callbacks --- - - /** -@@ -3046,6 +3056,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 54df40d..974d702 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -1464,6 +1464,17 @@ 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 --- - - -@@ -5113,6 +5124,17 @@ 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<Value>* objects, - size_t length, - RetainedObjectInfo* info) { -diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc -index f5be938..1e1aebd 100644 ---- a/src/arm/code-stubs-arm.cc -+++ b/src/arm/code-stubs-arm.cc -@@ -1569,6 +1569,37 @@ 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::kBitField2Offset)); -+ __ and_(r2, r2, Operand(1 << Map::kUseUserObjectComparison)); -+ __ cmp(r2, Operand(1 << Map::kUseUserObjectComparison)); -+ __ b(eq, &user_equal); -+ -+ __ ldrb(r3, FieldMemOperand(r3, Map::kBitField2Offset)); -+ __ 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_); -@@ -6615,10 +6646,18 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) { - __ and_(r2, r1, Operand(r0)); - __ JumpIfSmi(r2, &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::kBitField2Offset)); -+ __ 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::kBitField2Offset)); -+ __ 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 8c96944..76ca69d 100644 ---- a/src/factory.cc -+++ b/src/factory.cc -@@ -1153,6 +1153,7 @@ Handle<JSFunction> Factory::CreateApiFunction( - - int internal_field_count = 0; - bool has_external_resource = false; -+ bool use_user_object_comparison = false; - - if (!obj->instance_template()->IsUndefined()) { - Handle<ObjectTemplateInfo> instance_template = -@@ -1162,6 +1163,8 @@ Handle<JSFunction> 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; -@@ -1206,6 +1209,11 @@ Handle<JSFunction> 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 8a94a06..e73753e 100644 ---- a/src/ia32/code-stubs-ia32.cc -+++ b/src/ia32/code-stubs-ia32.cc -@@ -4020,6 +4020,39 @@ 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; -+ __ 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::kBitField2Offset), -+ 1 << Map::kUseUserObjectComparison); -+ __ j(not_zero, &user_equal); -+ __ test_b(FieldOperand(ecx, Map::kBitField2Offset), -+ 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); -+ } -+ - // Identical objects can be compared fast, but there are some tricky cases - // for NaN and undefined. - { -@@ -6497,8 +6530,14 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) { - - __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); - __ j(not_equal, &miss, Label::kNear); -+ __ test_b(FieldOperand(ecx, Map::kBitField2Offset), -+ 1 << Map::kUseUserObjectComparison); -+ __ j(not_zero, &miss, Label::kNear); - __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); - __ j(not_equal, &miss, Label::kNear); -+ __ test_b(FieldOperand(ecx, Map::kBitField2Offset), -+ 1 << Map::kUseUserObjectComparison); -+ __ j(not_zero, &miss, Label::kNear); - - ASSERT(GetCondition() == equal); - __ sub(eax, edx); -diff --git a/src/isolate.cc b/src/isolate.cc -index a073af9..36c1dfd 100644 ---- a/src/isolate.cc -+++ b/src/isolate.cc -@@ -96,6 +96,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; - top_lookup_result_ = NULL; -@@ -729,6 +730,12 @@ 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/isolate.h b/src/isolate.h -index 5453bf2..9919e83 100644 ---- a/src/isolate.h -+++ b/src/isolate.h -@@ -258,6 +258,9 @@ class ThreadLocalTop BASE_EMBEDDED { - // Head of the list of live LookupResults. - LookupResult* top_lookup_result_; - -+ // Call back function for user object comparisons -+ v8::UserObjectComparisonCallback user_object_comparison_callback_; -+ - // Whether out of memory exceptions should be ignored. - bool ignore_out_of_memory_; - -@@ -703,6 +706,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 2e83fb7..13d7591 100644 ---- a/src/objects-inl.h -+++ b/src/objects-inl.h -@@ -2749,14 +2749,14 @@ bool Map::is_extensible() { - - void Map::set_attached_to_shared_function_info(bool value) { - if (value) { -- set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo)); -+ set_bit_field3(bit_field3() | (1 << kAttachedToSharedFunctionInfo)); - } else { -- set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo)); -+ set_bit_field3(bit_field3() & ~(1 << kAttachedToSharedFunctionInfo)); - } - } - - bool Map::attached_to_shared_function_info() { -- return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0; -+ return ((1 << kAttachedToSharedFunctionInfo) & bit_field3()) != 0; - } - - -@@ -2786,6 +2786,19 @@ bool Map::has_external_resource() - } - - -+void Map::set_use_user_object_comparison(bool value) { -+ if (value) { -+ set_bit_field2(bit_field2() | (1 << kUseUserObjectComparison)); -+ } else { -+ set_bit_field2(bit_field2() & ~(1 << kUseUserObjectComparison)); -+ } -+} -+ -+bool Map::use_user_object_comparison() { -+ return ((1 << kUseUserObjectComparison) & bit_field2()) != 0; -+} -+ -+ - void Map::set_named_interceptor_is_fallback(bool value) - { - if (value) { -@@ -3334,6 +3347,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.cc b/src/objects.cc -index f5b6bee..6a4eff9 100644 ---- a/src/objects.cc -+++ b/src/objects.cc -@@ -7686,8 +7686,8 @@ void SharedFunctionInfo::DetachInitialMap() { - Map* map = reinterpret_cast<Map*>(initial_map()); - - // Make the map remember to restore the link if it survives the GC. -- map->set_bit_field2( -- map->bit_field2() | (1 << Map::kAttachedToSharedFunctionInfo)); -+ map->set_bit_field3( -+ map->bit_field3() | (1 << Map::kAttachedToSharedFunctionInfo)); - - // Undo state changes made by StartInobjectTracking (except the - // construction_count). This way if the initial map does not survive the GC -@@ -7707,8 +7707,8 @@ void SharedFunctionInfo::DetachInitialMap() { - - // Called from GC, hence reinterpret_cast and unchecked accessors. - void SharedFunctionInfo::AttachInitialMap(Map* map) { -- map->set_bit_field2( -- map->bit_field2() & ~(1 << Map::kAttachedToSharedFunctionInfo)); -+ map->set_bit_field3( -+ map->bit_field3() & ~(1 << Map::kAttachedToSharedFunctionInfo)); - - // Resume inobject slack tracking. - set_initial_map(map); -diff --git a/src/objects.h b/src/objects.h -index b71eaac..3137437 100644 ---- a/src/objects.h -+++ b/src/objects.h -@@ -4258,6 +4258,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(); -+ - // [prototype]: implicit prototype object. - DECL_ACCESSORS(prototype, Object) - -@@ -4505,7 +4510,7 @@ class Map: public HeapObject { - static const int kIsExtensible = 0; - static const int kFunctionWithPrototype = 1; - static const int kStringWrapperSafeForDefaultValueOf = 2; -- static const int kAttachedToSharedFunctionInfo = 3; -+ static const int kUseUserObjectComparison = 3; - // No bits can be used after kElementsKindFirstBit, they are all reserved for - // storing ElementKind. - static const int kElementsKindShift = 4; -@@ -4524,6 +4529,7 @@ class Map: public HeapObject { - static const int kIsShared = 0; - static const int kNamedInterceptorIsFallback = 1; - static const int kHasInstanceCallHandler = 2; -+ static const int kAttachedToSharedFunctionInfo = 3; - - // Layout of the default cache. It holds alternating name and code objects. - static const int kCodeCacheEntrySize = 2; -@@ -7556,6 +7562,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); - -@@ -7573,7 +7580,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 b64e66b..8010169 100644 ---- a/src/runtime.cc -+++ b/src/runtime.cc -@@ -7095,6 +7095,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<JSObject> lhs_handle(lhs); -+ Handle<JSObject> 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 aada06d..cd36da9 100644 ---- a/src/runtime.h -+++ b/src/runtime.h -@@ -157,6 +157,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/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc -index f30221f..ff8337f 100644 ---- a/src/x64/code-stubs-x64.cc -+++ b/src/x64/code-stubs-x64.cc -@@ -3088,6 +3088,37 @@ 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; -+ __ 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::kBitField2Offset), -+ Immediate(1 << Map::kUseUserObjectComparison)); -+ __ j(not_zero, &user_equal); -+ __ testb(FieldOperand(rcx, Map::kBitField2Offset), -+ 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); -+ } -+ - // Two identical objects are equal unless they are both NaN or undefined. - { - Label not_identical; -@@ -5421,8 +5452,14 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) { - - __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); - __ j(not_equal, &miss, Label::kNear); -+ __ testb(FieldOperand(rcx, Map::kBitField2Offset), -+ Immediate(1 << Map::kUseUserObjectComparison)); -+ __ j(not_zero, &miss, Label::kNear); - __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); - __ j(not_equal, &miss, Label::kNear); -+ __ testb(FieldOperand(rcx, Map::kBitField2Offset), -+ Immediate(1 << Map::kUseUserObjectComparison)); -+ __ j(not_zero, &miss, Label::kNear); - - ASSERT(GetCondition() == equal); - __ subq(rax, rdx); --- -1.7.7.3 - |