diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2011-10-11 15:06:25 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-11-10 13:22:13 +0100 |
commit | bcd16f9453e543ba819385d87bd7061a4caeb325 (patch) | |
tree | 4296919fa02e8188be3b28ca7fa4ab548693be33 /src/v8/0006-Add-custom-object-compare-callback.patch | |
parent | 95d7abb694d5d21acf0a15dcbf3feb4514bd2ab4 (diff) |
Update V8
Change-Id: Ic239ef1e55bed06260e4a04cc2199f64c2d30059
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
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, 548 insertions, 0 deletions
diff --git a/src/v8/0006-Add-custom-object-compare-callback.patch b/src/v8/0006-Add-custom-object-compare-callback.patch new file mode 100644 index 0000000000..cd779ad94e --- /dev/null +++ b/src/v8/0006-Add-custom-object-compare-callback.patch @@ -0,0 +1,548 @@ +From 15e2b05fae59aa4ed7c0974ba296ec8893c4d7f2 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/11] 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 73e7f8b..9dcacac 100644 +--- a/src/objects.h ++++ b/src/objects.h +@@ -4255,6 +4255,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) + +@@ -4502,7 +4507,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; +@@ -4521,6 +4526,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; +@@ -7553,6 +7559,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); + +@@ -7570,7 +7577,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 5746c20..542e62b 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.4.4 + |