From 23cf62232f455d867496927e424316018594bd91 Mon Sep 17 00:00:00 2001 From: "jkummerow@chromium.org" Date: Tue, 15 Jul 2014 08:07:25 +0000 Subject: [PATCH] Drop unnecessary receiver validity checks from {Load,Store}IC_Normal. Since these builtins are used as handlers after a map check/dispatch, they don't need to check the receiver again. R=verwaest@chromium.org Review URL: https://codereview.chromium.org/390053002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22391 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/ic-arm.cc | 70 +++++++---------------------------------------- src/arm64/ic-arm64.cc | 71 ++++++------------------------------------------ src/ia32/ic-ia32.cc | 75 +++++++++------------------------------------------ src/x64/ic-x64.cc | 75 +++++++++------------------------------------------ 4 files changed, 44 insertions(+), 247 deletions(-) diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc index 0a16ba5..5db538d 100644 --- a/src/arm/ic-arm.cc +++ b/src/arm/ic-arm.cc @@ -39,48 +39,6 @@ static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, } -// Generated code falls through if the receiver is a regular non-global -// JS object with slow properties and no interceptors. -static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm, - Register receiver, - Register elements, - Register t0, - Register t1, - Label* miss) { - // Register usage: - // receiver: holds the receiver on entry and is unchanged. - // elements: holds the property dictionary on fall through. - // Scratch registers: - // t0: used to holds the receiver map. - // t1: used to holds the receiver instance type, receiver bit mask and - // elements map. - - // Check that the receiver isn't a smi. - __ JumpIfSmi(receiver, miss); - - // Check that the receiver is a valid JS object. - __ CompareObjectType(receiver, t0, t1, FIRST_SPEC_OBJECT_TYPE); - __ b(lt, miss); - - // If this assert fails, we have to check upper bound too. - STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); - - GenerateGlobalInstanceTypeCheck(masm, t1, miss); - - // Check that the global object does not require access checks. - __ ldrb(t1, FieldMemOperand(t0, Map::kBitFieldOffset)); - __ tst(t1, Operand((1 << Map::kIsAccessCheckNeeded) | - (1 << Map::kHasNamedInterceptor))); - __ b(ne, miss); - - __ ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); - __ ldr(t1, FieldMemOperand(elements, HeapObject::kMapOffset)); - __ LoadRoot(ip, Heap::kHashTableMapRootIndex); - __ cmp(t1, ip); - __ b(ne, miss); -} - - // Helper function used from LoadIC GenerateNormal. // // elements: Property dictionary. It is not clobbered if a jump to the miss @@ -328,29 +286,20 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { void LoadIC::GenerateNormal(MacroAssembler* masm) { - // ----------- S t a t e ------------- - // -- r2 : name - // -- lr : return address - // -- r1 : receiver - // ----------------------------------- - ASSERT(r1.is(ReceiverRegister())); - ASSERT(r2.is(NameRegister())); - - Label miss, slow; + Register dictionary = r0; + ASSERT(!dictionary.is(ReceiverRegister())); + ASSERT(!dictionary.is(NameRegister())); - GenerateNameDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss); + Label slow; - // r0: elements - GenerateDictionaryLoad(masm, &slow, r0, r2, r0, r3, r4); + __ ldr(dictionary, + FieldMemOperand(ReceiverRegister(), JSObject::kPropertiesOffset)); + GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), r0, r3, r4); __ Ret(); // Dictionary load failed, go slow (but don't miss). __ bind(&slow); GenerateRuntimeGetProperty(masm); - - // Cache miss: Jump to runtime. - __ bind(&miss); - GenerateMiss(masm); } @@ -1162,13 +1111,14 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) { Register receiver = ReceiverRegister(); Register name = NameRegister(); Register value = ValueRegister(); + Register dictionary = r3; ASSERT(receiver.is(r1)); ASSERT(name.is(r2)); ASSERT(value.is(r0)); - GenerateNameDictionaryReceiverCheck(masm, receiver, r3, r4, r5, &miss); + __ ldr(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); - GenerateDictionaryStore(masm, &miss, r3, name, value, r4, r5); + GenerateDictionaryStore(masm, &miss, dictionary, name, value, r4, r5); Counters* counters = masm->isolate()->counters(); __ IncrementCounter(counters->store_normal_hit(), 1, r4, r5); diff --git a/src/arm64/ic-arm64.cc b/src/arm64/ic-arm64.cc index 1607e5f..bde701c 100644 --- a/src/arm64/ic-arm64.cc +++ b/src/arm64/ic-arm64.cc @@ -34,51 +34,6 @@ static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, } -// Generated code falls through if the receiver is a regular non-global -// JS object with slow properties and no interceptors. -// -// "receiver" holds the receiver on entry and is unchanged. -// "elements" holds the property dictionary on fall through. -static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm, - Register receiver, - Register elements, - Register scratch0, - Register scratch1, - Label* miss) { - ASSERT(!AreAliased(receiver, elements, scratch0, scratch1)); - - // Check that the receiver isn't a smi. - __ JumpIfSmi(receiver, miss); - - // Check that the receiver is a valid JS object. - // Let t be the object instance type, we want: - // FIRST_SPEC_OBJECT_TYPE <= t <= LAST_SPEC_OBJECT_TYPE. - // Since LAST_SPEC_OBJECT_TYPE is the last possible instance type we only - // check the lower bound. - STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); - - __ JumpIfObjectType(receiver, scratch0, scratch1, FIRST_SPEC_OBJECT_TYPE, - miss, lt); - - // scratch0 now contains the map of the receiver and scratch1 the object type. - Register map = scratch0; - Register type = scratch1; - - // Check if the receiver is a global JS object. - GenerateGlobalInstanceTypeCheck(masm, type, miss); - - // Check that the object does not require access checks. - __ Ldrb(scratch1, FieldMemOperand(map, Map::kBitFieldOffset)); - __ Tbnz(scratch1, Map::kIsAccessCheckNeeded, miss); - __ Tbnz(scratch1, Map::kHasNamedInterceptor, miss); - - // Check that the properties dictionary is valid. - __ Ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); - __ Ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset)); - __ JumpIfNotRoot(scratch1, Heap::kHashTableMapRootIndex, miss); -} - - // Helper function used from LoadIC GenerateNormal. // // elements: Property dictionary. It is not clobbered if a jump to the miss @@ -424,28 +379,19 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { void LoadIC::GenerateNormal(MacroAssembler* masm) { - // ----------- S t a t e ------------- - // -- x2 : name - // -- lr : return address - // -- x1 : receiver - // ----------------------------------- - ASSERT(x1.is(ReceiverRegister())); - ASSERT(x2.is(NameRegister())); - Label miss, slow; - - GenerateNameDictionaryReceiverCheck(masm, x1, x0, x3, x4, &miss); + Register dictionary = x0; + ASSERT(!dictionary.is(ReceiverRegister())); + ASSERT(!dictionary.is(NameRegister())); + Label slow; - // x0 now holds the property dictionary. - GenerateDictionaryLoad(masm, &slow, x0, x2, x0, x3, x4); + __ Ldr(dictionary, + FieldMemOperand(ReceiverRegister(), JSObject::kPropertiesOffset)); + GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), x0, x3, x4); __ Ret(); // Dictionary load failed, go slow (but don't miss). __ Bind(&slow); GenerateRuntimeGetProperty(masm); - - // Cache miss: Jump to runtime. - __ Bind(&miss); - GenerateMiss(masm); } @@ -1203,8 +1149,7 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) { Register dictionary = x3; ASSERT(!AreAliased(value, receiver, name, x3, x4, x5)); - GenerateNameDictionaryReceiverCheck( - masm, receiver, dictionary, x4, x5, &miss); + __ Ldr(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); GenerateDictionaryStore(masm, &miss, dictionary, name, value, x4, x5); Counters* counters = masm->isolate()->counters(); diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc index 24419f3..bfec291 100644 --- a/src/ia32/ic-ia32.cc +++ b/src/ia32/ic-ia32.cc @@ -35,45 +35,6 @@ static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, } -// Generated code falls through if the receiver is a regular non-global -// JS object with slow properties and no interceptors. -static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm, - Register receiver, - Register r0, - Register r1, - Label* miss) { - // Register usage: - // receiver: holds the receiver on entry and is unchanged. - // r0: used to hold receiver instance type. - // Holds the property dictionary on fall through. - // r1: used to hold receivers map. - - // Check that the receiver isn't a smi. - __ JumpIfSmi(receiver, miss); - - // Check that the receiver is a valid JS object. - __ mov(r1, FieldOperand(receiver, HeapObject::kMapOffset)); - __ movzx_b(r0, FieldOperand(r1, Map::kInstanceTypeOffset)); - __ cmp(r0, FIRST_SPEC_OBJECT_TYPE); - __ j(below, miss); - - // If this assert fails, we have to check upper bound too. - STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); - - GenerateGlobalInstanceTypeCheck(masm, r0, miss); - - // Check for non-global object that requires access check. - __ test_b(FieldOperand(r1, Map::kBitFieldOffset), - (1 << Map::kIsAccessCheckNeeded) | - (1 << Map::kHasNamedInterceptor)); - __ j(not_zero, miss); - - __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); - __ CheckMap(r0, masm->isolate()->factory()->hash_table_map(), miss, - DONT_DO_SMI_CHECK); -} - - // Helper function used to load a property from a dictionary backing // storage. This function may fail to load a property even though it is // in the dictionary, so code at miss_label must always call a backup @@ -942,30 +903,21 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { void LoadIC::GenerateNormal(MacroAssembler* masm) { - // ----------- S t a t e ------------- - // -- ecx : name - // -- edx : receiver - // -- esp[0] : return address - // ----------------------------------- - ASSERT(edx.is(ReceiverRegister())); - ASSERT(ecx.is(NameRegister())); - - Label miss, slow; + Register dictionary = eax; + ASSERT(!dictionary.is(ReceiverRegister())); + ASSERT(!dictionary.is(NameRegister())); - GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss); + Label slow; - // eax: elements - // Search the dictionary placing the result in eax. - GenerateDictionaryLoad(masm, &slow, eax, ecx, edi, ebx, eax); + __ mov(dictionary, + FieldOperand(ReceiverRegister(), JSObject::kPropertiesOffset)); + GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), edi, ebx, + eax); __ ret(0); // Dictionary load failed, go slow (but don't miss). __ bind(&slow); GenerateRuntimeGetProperty(masm); - - // Cache miss: Jump to runtime. - __ bind(&miss); - GenerateMiss(masm); } @@ -1094,19 +1046,20 @@ void StoreIC::GenerateMiss(MacroAssembler* masm) { void StoreIC::GenerateNormal(MacroAssembler* masm) { - // Return address is on the stack. - Label miss, restore_miss; + Label restore_miss; Register receiver = ReceiverRegister(); Register name = NameRegister(); Register value = ValueRegister(); + Register dictionary = ebx; - GenerateNameDictionaryReceiverCheck(masm, receiver, ebx, edi, &miss); + __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); // A lot of registers are needed for storing to slow case // objects. Push and restore receiver but rely on // GenerateDictionaryStore preserving the value and name. __ push(receiver); - GenerateDictionaryStore(masm, &restore_miss, ebx, name, value, receiver, edi); + GenerateDictionaryStore(masm, &restore_miss, dictionary, name, value, + receiver, edi); __ Drop(1); Counters* counters = masm->isolate()->counters(); __ IncrementCounter(counters->store_normal_hit(), 1); @@ -1114,8 +1067,6 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) { __ bind(&restore_miss); __ pop(receiver); - - __ bind(&miss); __ IncrementCounter(counters->store_normal_miss(), 1); GenerateMiss(masm); } diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc index ead1d99..62585af 100644 --- a/src/x64/ic-x64.cc +++ b/src/x64/ic-x64.cc @@ -35,46 +35,6 @@ static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, } -// Generated code falls through if the receiver is a regular non-global -// JS object with slow properties and no interceptors. -static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm, - Register receiver, - Register r0, - Register r1, - Label* miss) { - // Register usage: - // receiver: holds the receiver on entry and is unchanged. - // r0: used to hold receiver instance type. - // Holds the property dictionary on fall through. - // r1: used to hold receivers map. - - __ JumpIfSmi(receiver, miss); - - // Check that the receiver is a valid JS object. - __ movp(r1, FieldOperand(receiver, HeapObject::kMapOffset)); - __ movb(r0, FieldOperand(r1, Map::kInstanceTypeOffset)); - __ cmpb(r0, Immediate(FIRST_SPEC_OBJECT_TYPE)); - __ j(below, miss); - - // If this assert fails, we have to check upper bound too. - STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); - - GenerateGlobalInstanceTypeCheck(masm, r0, miss); - - // Check for non-global object that requires access check. - __ testb(FieldOperand(r1, Map::kBitFieldOffset), - Immediate((1 << Map::kIsAccessCheckNeeded) | - (1 << Map::kHasNamedInterceptor))); - __ j(not_zero, miss); - - __ movp(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); - __ CompareRoot(FieldOperand(r0, HeapObject::kMapOffset), - Heap::kHashTableMapRootIndex); - __ j(not_equal, miss); -} - - - // Helper function used to load a property from a dictionary backing storage. // This function may return false negatives, so miss_label // must always call a backup property load that is complete. @@ -959,29 +919,21 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { void LoadIC::GenerateNormal(MacroAssembler* masm) { - // ----------- S t a t e ------------- - // -- rdx : receiver - // -- rcx : name - // -- rsp[0] : return address - // ----------------------------------- - ASSERT(rdx.is(ReceiverRegister())); - ASSERT(rcx.is(NameRegister())); - Label miss, slow; - - GenerateNameDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss); - - // rax: elements - // Search the dictionary placing the result in rax. - GenerateDictionaryLoad(masm, &slow, rax, rcx, rbx, rdi, rax); + Register dictionary = rax; + ASSERT(!dictionary.is(ReceiverRegister())); + ASSERT(!dictionary.is(NameRegister())); + + Label slow; + + __ movp(dictionary, + FieldOperand(ReceiverRegister(), JSObject::kPropertiesOffset)); + GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), rbx, rdi, + rax); __ ret(0); // Dictionary load failed, go slow (but don't miss). __ bind(&slow); GenerateRuntimeGetProperty(masm); - - // Cache miss: Jump to runtime. - __ bind(&miss); - GenerateMiss(masm); } @@ -1125,16 +1077,15 @@ void StoreIC::GenerateMiss(MacroAssembler* masm) { void StoreIC::GenerateNormal(MacroAssembler* masm) { - // Return address is on the stack. Register receiver = ReceiverRegister(); Register name = NameRegister(); Register value = ValueRegister(); + Register dictionary = rbx; Label miss; - GenerateNameDictionaryReceiverCheck(masm, receiver, rbx, rdi, &miss); - - GenerateDictionaryStore(masm, &miss, rbx, name, value, r8, r9); + __ movp(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); + GenerateDictionaryStore(masm, &miss, dictionary, name, value, r8, r9); Counters* counters = masm->isolate()->counters(); __ IncrementCounter(counters->store_normal_hit(), 1); __ ret(0); -- 2.7.4