Index: src/arm/stub-cache-arm.cc |
=================================================================== |
--- src/arm/stub-cache-arm.cc (revision 5044) |
+++ src/arm/stub-cache-arm.cc (working copy) |
@@ -92,13 +92,11 @@ |
Label* miss_label, |
Register receiver, |
String* name, |
- Register r0, |
- Register extra) { |
+ Register scratch0, |
+ Register scratch1) { |
ASSERT(name->IsSymbol()); |
- if (!extra.is(no_reg)) { |
- __ IncrementCounter(&Counters::negative_lookups, 1, r0, extra); |
- __ IncrementCounter(&Counters::negative_lookups_miss, 1, r0, extra); |
- } |
+ __ IncrementCounter(&Counters::negative_lookups, 1, scratch0, scratch1); |
+ __ IncrementCounter(&Counters::negative_lookups_miss, 1, scratch0, scratch1); |
Label done; |
@@ -106,38 +104,25 @@ |
(1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
// Bail out if the receiver has a named interceptor or requires access checks. |
- Register map = extra.is(no_reg) ? r0 : extra; |
+ Register map = scratch1; |
__ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
- __ ldrb(r0, FieldMemOperand(map, Map::kBitFieldOffset)); |
- __ tst(r0, Operand(kInterceptorOrAccessCheckNeededMask)); |
+ __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); |
+ __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); |
__ b(ne, miss_label); |
// Check that receiver is a JSObject. |
- if (extra.is(no_reg)) { |
- __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
- } |
- __ ldrb(r0, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
- __ cmp(r0, Operand(FIRST_JS_OBJECT_TYPE)); |
+ __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); |
+ __ cmp(scratch0, Operand(FIRST_JS_OBJECT_TYPE)); |
__ b(lt, miss_label); |
// Load properties array. |
- Register properties = r0; |
+ Register properties = scratch0; |
__ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
// Check that the properties array is a dictionary. |
- if (!extra.is(no_reg)) { |
- __ ldr(extra, FieldMemOperand(properties, HeapObject::kMapOffset)); |
- Register tmp = properties; |
- __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); |
- __ cmp(extra, tmp); |
- } else { |
- Register tmp1 = receiver; |
- Register tmp2 = properties; |
- __ push(tmp1); |
- __ ldr(tmp1, FieldMemOperand(properties, HeapObject::kMapOffset)); |
- __ LoadRoot(tmp2, Heap::kHashTableMapRootIndex); |
- __ cmp(tmp1, tmp2); |
- __ pop(tmp1); |
- } |
+ __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); |
+ Register tmp = properties; |
+ __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); |
+ __ cmp(map, tmp); |
__ b(ne, miss_label); |
// Restore the temporarily used register. |
@@ -161,12 +146,9 @@ |
// property. It's true even if some slots represent deleted properties |
// (their names are the null value). |
for (int i = 0; i < kProbes; i++) { |
- // r0 points to properties hash. |
+ // scratch0 points to properties hash. |
// Compute the masked index: (hash + i + i * i) & mask. |
- if (extra.is(no_reg)) { |
- __ push(receiver); |
- } |
- Register index = extra.is(no_reg) ? receiver : extra; |
+ Register index = scratch1; |
// Capacity is smi 2^n. |
__ ldr(index, FieldMemOperand(properties, kCapacityOffset)); |
__ sub(index, index, Operand(1)); |
@@ -177,20 +159,16 @@ |
ASSERT(StringDictionary::kEntrySize == 3); |
__ add(index, index, Operand(index, LSL, 1)); // index *= 3. |
- Register entity_name = extra.is(no_reg) ? properties : extra; |
+ Register entity_name = scratch1; |
// Having undefined at this place means the name is not contained. |
ASSERT_EQ(kSmiTagSize, 1); |
- Register tmp = extra.is(no_reg) ? receiver : properties; |
+ Register tmp = properties; |
__ add(tmp, properties, Operand(index, LSL, 1)); |
__ ldr(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); |
ASSERT(!tmp.is(entity_name)); |
__ LoadRoot(tmp, Heap::kUndefinedValueRootIndex); |
__ cmp(entity_name, tmp); |
- if (extra.is(no_reg)) { |
- // 'receiver' shares a register with 'entity_name'. |
- __ pop(receiver); |
- } |
if (i != kProbes - 1) { |
__ b(eq, &done); |
@@ -207,9 +185,7 @@ |
} |
} |
__ bind(&done); |
- if (!extra.is(no_reg)) { |
- __ DecrementCounter(&Counters::negative_lookups_miss, 1, r0, extra); |
- } |
+ __ DecrementCounter(&Counters::negative_lookups_miss, 1, scratch0, scratch1); |
} |
@@ -647,6 +623,7 @@ |
Register receiver, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
Label* miss) { |
ASSERT(holder->HasNamedInterceptor()); |
ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
@@ -662,6 +639,7 @@ |
receiver, |
scratch1, |
scratch2, |
+ scratch3, |
holder, |
lookup, |
name, |
@@ -673,6 +651,7 @@ |
receiver, |
scratch1, |
scratch2, |
+ scratch3, |
name, |
holder, |
miss); |
@@ -685,6 +664,7 @@ |
Register receiver, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
JSObject* interceptor_holder, |
LookupResult* lookup, |
String* name, |
@@ -726,7 +706,7 @@ |
Register holder = |
stub_compiler_->CheckPrototypes(object, receiver, |
interceptor_holder, scratch1, |
- scratch2, name, depth1, miss); |
+ scratch2, scratch3, name, depth1, miss); |
// Invoke an interceptor and if it provides a value, |
// branch to |regular_invoke|. |
@@ -742,7 +722,7 @@ |
if (interceptor_holder != lookup->holder()) { |
stub_compiler_->CheckPrototypes(interceptor_holder, receiver, |
lookup->holder(), scratch1, |
- scratch2, name, depth2, miss); |
+ scratch2, scratch3, name, depth2, miss); |
} else { |
// CheckPrototypes has a side effect of fetching a 'holder' |
// for API (object which is instanceof for the signature). It's |
@@ -778,12 +758,13 @@ |
Register receiver, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
String* name, |
JSObject* interceptor_holder, |
Label* miss_label) { |
Register holder = |
stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
- scratch1, scratch2, name, |
+ scratch1, scratch2, scratch3, name, |
miss_label); |
// Call a runtime function to load the interceptor property. |
@@ -868,14 +849,15 @@ |
Register object_reg, |
JSObject* holder, |
Register holder_reg, |
- Register scratch, |
+ Register scratch1, |
+ Register scratch2, |
String* name, |
int save_at_depth, |
- Label* miss, |
- Register extra) { |
- // Make sure there's no overlap between scratch and the other |
- // registers. |
- ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg)); |
+ Label* miss) { |
+ // Make sure there's no overlap between holder and object registers. |
+ ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
+ ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
+ && !scratch2.is(scratch1)); |
// Keep track of the current object in register reg. |
Register reg = object_reg; |
@@ -915,15 +897,15 @@ |
miss, |
reg, |
name, |
- scratch, |
- extra); |
- __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
+ scratch1, |
+ scratch2); |
+ __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
reg = holder_reg; // from now the object is in holder_reg |
- __ ldr(reg, FieldMemOperand(scratch, Map::kPrototypeOffset)); |
+ __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
} else { |
// Get the map of the current object. |
- __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
- __ cmp(scratch, Operand(Handle<Map>(current->map()))); |
+ __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
+ __ cmp(scratch1, Operand(Handle<Map>(current->map()))); |
// Branch on the result of the map check. |
__ b(ne, miss); |
@@ -932,18 +914,18 @@ |
// after the map check so that we know that the object is |
// actually a global object. |
if (current->IsJSGlobalProxy()) { |
- __ CheckAccessGlobalProxy(reg, scratch, miss); |
+ __ CheckAccessGlobalProxy(reg, scratch1, miss); |
// Restore scratch register to be the map of the object. In the |
// new space case below, we load the prototype from the map in |
// the scratch register. |
- __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
+ __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
} |
reg = holder_reg; // from now the object is in holder_reg |
if (Heap::InNewSpace(prototype)) { |
// The prototype is in new space; we cannot store a reference |
// to it in the code. Load it from the map. |
- __ ldr(reg, FieldMemOperand(scratch, Map::kPrototypeOffset)); |
+ __ ldr(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); |
} else { |
// The prototype is in old space; load it directly. |
__ mov(reg, Operand(Handle<JSObject>(prototype))); |
@@ -959,8 +941,8 @@ |
} |
// Check the holder map. |
- __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
- __ cmp(scratch, Operand(Handle<Map>(current->map()))); |
+ __ ldr(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); |
+ __ cmp(scratch1, Operand(Handle<Map>(current->map()))); |
__ b(ne, miss); |
// Log the check depth. |
@@ -971,7 +953,7 @@ |
ASSERT(current == holder); |
ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); |
if (current->IsJSGlobalProxy()) { |
- __ CheckAccessGlobalProxy(reg, scratch, miss); |
+ __ CheckAccessGlobalProxy(reg, scratch1, miss); |
} |
// If we've skipped any global objects, it's not enough to verify |
@@ -983,7 +965,7 @@ |
Object* cell = GenerateCheckPropertyCell(masm(), |
GlobalObject::cast(current), |
name, |
- scratch, |
+ scratch1, |
miss); |
if (cell->IsFailure()) { |
set_failure(Failure::cast(cell)); |
@@ -1003,6 +985,7 @@ |
Register receiver, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
int index, |
String* name, |
Label* miss) { |
@@ -1012,7 +995,8 @@ |
// Check that the maps haven't changed. |
Register reg = |
- CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss); |
+ CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, |
+ name, miss); |
GenerateFastPropertyLoad(masm(), r0, reg, holder, index); |
__ Ret(); |
} |
@@ -1023,6 +1007,7 @@ |
Register receiver, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
Object* value, |
String* name, |
Label* miss) { |
@@ -1032,7 +1017,8 @@ |
// Check that the maps haven't changed. |
Register reg = |
- CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss); |
+ CheckPrototypes(object, receiver, holder, |
+ scratch1, scratch2, scratch3, name, miss); |
// Return the constant value. |
__ mov(r0, Operand(Handle<Object>(value))); |
@@ -1046,6 +1032,7 @@ |
Register name_reg, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
AccessorInfo* callback, |
String* name, |
Label* miss, |
@@ -1056,7 +1043,8 @@ |
// Check that the maps haven't changed. |
Register reg = |
- CheckPrototypes(object, receiver, holder, scratch1, scratch2, name, miss); |
+ CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, |
+ name, miss); |
// Push the arguments on the JS stack of the caller. |
__ push(receiver); // Receiver. |
@@ -1081,6 +1069,7 @@ |
Register name_reg, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
String* name, |
Label* miss) { |
ASSERT(interceptor_holder->HasNamedInterceptor()); |
@@ -1108,7 +1097,8 @@ |
// property from further up the prototype chain if the call fails. |
// Check that the maps haven't changed. |
Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, |
- scratch1, scratch2, name, miss); |
+ scratch1, scratch2, scratch3, |
+ name, miss); |
ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); |
// Save necessary data before invoking an interceptor. |
@@ -1157,6 +1147,7 @@ |
lookup->holder(), |
scratch1, |
scratch2, |
+ scratch3, |
name, |
miss); |
} |
@@ -1202,7 +1193,8 @@ |
// Call the runtime system to load the interceptor. |
// Check that the maps haven't changed. |
Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, |
- scratch1, scratch2, name, miss); |
+ scratch1, scratch2, scratch3, |
+ name, miss); |
PushInterceptorArguments(masm(), receiver, holder_reg, |
name_reg, interceptor_holder); |
@@ -1280,7 +1272,7 @@ |
__ b(eq, &miss); |
// Do the right check and compute the holder register. |
- Register reg = CheckPrototypes(object, r0, holder, r1, r3, name, &miss, r4); |
+ Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss); |
GenerateFastPropertyLoad(masm(), r1, reg, holder, index); |
GenerateCallFunction(masm(), object, arguments(), &miss); |
@@ -1325,7 +1317,7 @@ |
__ b(eq, &miss); |
// Check that the maps haven't changed. |
- CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss, r4); |
+ CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, r4, name, &miss); |
if (object->IsGlobalObject()) { |
__ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
@@ -1376,7 +1368,7 @@ |
__ b(eq, &miss); |
// Check that the maps haven't changed. |
- CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, name, &miss, r4); |
+ CheckPrototypes(JSObject::cast(object), r1, holder, r3, r0, r4, name, &miss); |
if (object->IsGlobalObject()) { |
__ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); |
@@ -1473,8 +1465,8 @@ |
} |
// Check that the maps haven't changed. |
- CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, name, |
- depth, &miss, r4); |
+ CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, |
+ depth, &miss); |
// Patch the receiver on the stack with the global proxy if |
// necessary. |
@@ -1497,7 +1489,7 @@ |
GenerateDirectLoadGlobalFunctionPrototype( |
masm(), Context::STRING_FUNCTION_INDEX, r0); |
CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
- r1, name, &miss, r4); |
+ r1, r4, name, &miss); |
} |
break; |
@@ -1517,7 +1509,7 @@ |
GenerateDirectLoadGlobalFunctionPrototype( |
masm(), Context::NUMBER_FUNCTION_INDEX, r0); |
CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
- r1, name, &miss, r4); |
+ r1, r4, name, &miss); |
} |
break; |
} |
@@ -1540,7 +1532,7 @@ |
GenerateDirectLoadGlobalFunctionPrototype( |
masm(), Context::BOOLEAN_FUNCTION_INDEX, r0); |
CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, |
- r1, name, &miss, r4); |
+ r1, r4, name, &miss); |
} |
break; |
} |
@@ -1599,6 +1591,7 @@ |
r1, |
r3, |
r4, |
+ r0, |
&miss); |
// Move returned value, the function to call, to r1. |
@@ -1645,7 +1638,7 @@ |
} |
// Check that the maps haven't changed. |
- CheckPrototypes(object, r0, holder, r3, r1, name, &miss, r4); |
+ CheckPrototypes(object, r0, holder, r3, r1, r4, name, &miss); |
// Get the value from the cell. |
__ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); |
@@ -1869,7 +1862,7 @@ |
__ b(eq, &miss); |
// Check the maps of the full prototype chain. |
- CheckPrototypes(object, r0, last, r3, r1, name, &miss, r4); |
+ CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss); |
// If the last object in the prototype chain is a global object, |
// check that the global property cell is empty. |
@@ -1906,7 +1899,7 @@ |
// ----------------------------------- |
Label miss; |
- GenerateLoadField(object, holder, r0, r3, r1, index, name, &miss); |
+ GenerateLoadField(object, holder, r0, r3, r1, r4, index, name, &miss); |
__ bind(&miss); |
GenerateLoadMiss(masm(), Code::LOAD_IC); |
@@ -1927,7 +1920,7 @@ |
Label miss; |
Failure* failure = Failure::InternalError(); |
- bool success = GenerateLoadCallback(object, holder, r0, r2, r3, r1, |
+ bool success = GenerateLoadCallback(object, holder, r0, r2, r3, r1, r4, |
callback, name, &miss, &failure); |
if (!success) return failure; |
@@ -1950,7 +1943,7 @@ |
// ----------------------------------- |
Label miss; |
- GenerateLoadConstant(object, holder, r0, r3, r1, value, name, &miss); |
+ GenerateLoadConstant(object, holder, r0, r3, r1, r4, value, name, &miss); |
__ bind(&miss); |
GenerateLoadMiss(masm(), Code::LOAD_IC); |
@@ -1978,6 +1971,7 @@ |
r2, |
r3, |
r1, |
+ r4, |
name, |
&miss); |
__ bind(&miss); |
@@ -2009,7 +2003,7 @@ |
} |
// Check that the map of the global has not changed. |
- CheckPrototypes(object, r0, holder, r3, r4, name, &miss, r1); |
+ CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss); |
// Get the value from the cell. |
__ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); |
@@ -2050,7 +2044,7 @@ |
__ cmp(r0, Operand(Handle<String>(name))); |
__ b(ne, &miss); |
- GenerateLoadField(receiver, holder, r1, r2, r3, index, name, &miss); |
+ GenerateLoadField(receiver, holder, r1, r2, r3, r4, index, name, &miss); |
__ bind(&miss); |
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
@@ -2074,7 +2068,7 @@ |
__ b(ne, &miss); |
Failure* failure = Failure::InternalError(); |
- bool success = GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, |
+ bool success = GenerateLoadCallback(receiver, holder, r1, r0, r2, r3, r4, |
callback, name, &miss, &failure); |
if (!success) return failure; |
@@ -2100,7 +2094,7 @@ |
__ cmp(r0, Operand(Handle<String>(name))); |
__ b(ne, &miss); |
- GenerateLoadConstant(receiver, holder, r1, r2, r3, value, name, &miss); |
+ GenerateLoadConstant(receiver, holder, r1, r2, r3, r4, value, name, &miss); |
__ bind(&miss); |
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
@@ -2132,6 +2126,7 @@ |
r0, |
r2, |
r3, |
+ r4, |
name, |
&miss); |
__ bind(&miss); |