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
This commit is contained in:
parent
cd0980059d
commit
23cf62232f
@ -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()));
|
||||
Register dictionary = r0;
|
||||
ASSERT(!dictionary.is(ReceiverRegister()));
|
||||
ASSERT(!dictionary.is(NameRegister()));
|
||||
|
||||
Label miss, slow;
|
||||
Label slow;
|
||||
|
||||
GenerateNameDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss);
|
||||
|
||||
// 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);
|
||||
|
@ -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;
|
||||
Register dictionary = x0;
|
||||
ASSERT(!dictionary.is(ReceiverRegister()));
|
||||
ASSERT(!dictionary.is(NameRegister()));
|
||||
Label slow;
|
||||
|
||||
GenerateNameDictionaryReceiverCheck(masm, x1, x0, x3, x4, &miss);
|
||||
|
||||
// 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();
|
||||
|
@ -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()));
|
||||
Register dictionary = eax;
|
||||
ASSERT(!dictionary.is(ReceiverRegister()));
|
||||
ASSERT(!dictionary.is(NameRegister()));
|
||||
|
||||
Label miss, slow;
|
||||
Label slow;
|
||||
|
||||
GenerateNameDictionaryReceiverCheck(masm, edx, eax, ebx, &miss);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
@ -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;
|
||||
Register dictionary = rax;
|
||||
ASSERT(!dictionary.is(ReceiverRegister()));
|
||||
ASSERT(!dictionary.is(NameRegister()));
|
||||
|
||||
GenerateNameDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss);
|
||||
Label slow;
|
||||
|
||||
// rax: elements
|
||||
// Search the dictionary placing the result in rax.
|
||||
GenerateDictionaryLoad(masm, &slow, rax, rcx, rbx, rdi, rax);
|
||||
__ 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);
|
||||
|
Loading…
Reference in New Issue
Block a user