Index: src/x64/stub-cache-x64.cc |
=================================================================== |
--- src/x64/stub-cache-x64.cc (revision 5044) |
+++ src/x64/stub-cache-x64.cc (working copy) |
@@ -91,7 +91,7 @@ |
Register receiver, |
String* name, |
Register r0, |
- Register extra) { |
+ Register r1) { |
ASSERT(name->IsSymbol()); |
__ IncrementCounter(&Counters::negative_lookups, 1); |
__ IncrementCounter(&Counters::negative_lookups_miss, 1); |
@@ -140,10 +140,7 @@ |
for (int i = 0; i < kProbes; i++) { |
// r0 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 = r1; |
// Capacity is smi 2^n. |
__ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset)); |
__ decl(index); |
@@ -154,16 +151,12 @@ |
ASSERT(StringDictionary::kEntrySize == 3); |
__ lea(index, Operand(index, index, times_2, 0)); // index *= 3. |
- Register entity_name = extra.is(no_reg) ? properties : extra; |
+ Register entity_name = r1; |
// Having undefined at this place means the name is not contained. |
ASSERT_EQ(kSmiTagSize, 1); |
__ movq(entity_name, Operand(properties, index, times_pointer_size, |
kElementsStartOffset - kHeapObjectTag)); |
__ Cmp(entity_name, Factory::undefined_value()); |
- if (extra.is(no_reg)) { |
- // 'receiver' shares a register with 'entity_name'. |
- __ pop(receiver); |
- } |
// __ jmp(miss_label); |
if (i != kProbes - 1) { |
__ j(equal, &done); |
@@ -171,12 +164,6 @@ |
// Stop if found the property. |
__ Cmp(entity_name, Handle<String>(name)); |
__ j(equal, miss_label); |
- |
- if (extra.is(no_reg)) { |
- // Restore the properties if their register was occupied by the name. |
- __ movq(properties, |
- FieldOperand(receiver, JSObject::kPropertiesOffset)); |
- } |
} else { |
// Give up probing if still not found the undefined value. |
__ j(not_equal, miss_label); |
@@ -604,6 +591,7 @@ |
Register receiver, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
Label* miss) { |
ASSERT(holder->HasNamedInterceptor()); |
ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
@@ -619,6 +607,7 @@ |
receiver, |
scratch1, |
scratch2, |
+ scratch3, |
holder, |
lookup, |
name, |
@@ -630,6 +619,7 @@ |
receiver, |
scratch1, |
scratch2, |
+ scratch3, |
name, |
holder, |
miss); |
@@ -642,6 +632,7 @@ |
Register receiver, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
JSObject* interceptor_holder, |
LookupResult* lookup, |
String* name, |
@@ -681,7 +672,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|. |
@@ -697,7 +688,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 |
@@ -733,12 +724,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); |
__ EnterInternalFrame(); |
@@ -891,7 +883,7 @@ |
// Check that the maps haven't changed. |
CheckPrototypes(JSObject::cast(object), rdx, holder, |
- rbx, rax, name, depth, &miss, rdi); |
+ rbx, rax, rdi, name, depth, &miss); |
// Patch the receiver on the stack with the global proxy if |
// necessary. |
@@ -914,7 +906,7 @@ |
GenerateDirectLoadGlobalFunctionPrototype( |
masm(), Context::STRING_FUNCTION_INDEX, rax); |
CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
- rbx, rdx, name, &miss, rdi); |
+ rbx, rdx, rdi, name, &miss); |
} |
break; |
@@ -933,7 +925,7 @@ |
GenerateDirectLoadGlobalFunctionPrototype( |
masm(), Context::NUMBER_FUNCTION_INDEX, rax); |
CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
- rbx, rdx, name, &miss, rdi); |
+ rbx, rdx, rdi, name, &miss); |
} |
break; |
} |
@@ -954,7 +946,7 @@ |
GenerateDirectLoadGlobalFunctionPrototype( |
masm(), Context::BOOLEAN_FUNCTION_INDEX, rax); |
CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, |
- rbx, rdx, name, &miss, rdi); |
+ rbx, rdx, rdi, name, &miss); |
} |
break; |
} |
@@ -1009,8 +1001,8 @@ |
__ JumpIfSmi(rdx, &miss); |
// Do the right check and compute the holder register. |
- Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, |
- name, &miss, rdi); |
+ Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi, |
+ name, &miss); |
GenerateFastPropertyLoad(masm(), rdi, reg, holder, index); |
@@ -1073,9 +1065,9 @@ |
holder, |
rbx, |
rax, |
+ rdi, |
name, |
- &miss, |
- rdi); |
+ &miss); |
if (argc == 0) { |
// Noop, return the length. |
@@ -1228,7 +1220,7 @@ |
CheckPrototypes(JSObject::cast(object), rdx, |
holder, rbx, |
- rax, name, &miss, rdi); |
+ rax, rdi, name, &miss); |
// Get the elements array of the object. |
__ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); |
@@ -1335,6 +1327,7 @@ |
rdx, |
rbx, |
rdi, |
+ rax, |
&miss); |
// Restore receiver. |
@@ -1397,7 +1390,7 @@ |
} |
// Check that the maps haven't changed. |
- CheckPrototypes(object, rdx, holder, rbx, rax, name, &miss, rdi); |
+ CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, &miss); |
// Get the value from the cell. |
__ Move(rdi, Handle<JSGlobalPropertyCell>(cell)); |
@@ -1462,7 +1455,7 @@ |
Label miss; |
Failure* failure = Failure::InternalError(); |
- bool success = GenerateLoadCallback(object, holder, rax, rcx, rbx, rdx, |
+ bool success = GenerateLoadCallback(object, holder, rax, rcx, rbx, rdx, rdi, |
callback, name, &miss, &failure); |
if (!success) return failure; |
@@ -1485,7 +1478,7 @@ |
// ----------------------------------- |
Label miss; |
- GenerateLoadConstant(object, holder, rax, rbx, rdx, value, name, &miss); |
+ GenerateLoadConstant(object, holder, rax, rbx, rdx, rdi, value, name, &miss); |
__ bind(&miss); |
GenerateLoadMiss(masm(), Code::LOAD_IC); |
@@ -1510,7 +1503,7 @@ |
// Check the maps of the full prototype chain. Also check that |
// global property cells up to (but not including) the last object |
// in the prototype chain are empty. |
- CheckPrototypes(object, rax, last, rbx, rdx, name, &miss, rdi); |
+ CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss); |
// If the last object in the prototype chain is a global object, |
// check that the global property cell is empty. |
@@ -1547,7 +1540,7 @@ |
// ----------------------------------- |
Label miss; |
- GenerateLoadField(object, holder, rax, rbx, rdx, index, name, &miss); |
+ GenerateLoadField(object, holder, rax, rbx, rdx, rdi, index, name, &miss); |
__ bind(&miss); |
GenerateLoadMiss(masm(), Code::LOAD_IC); |
@@ -1578,6 +1571,7 @@ |
rcx, |
rdx, |
rbx, |
+ rdi, |
name, |
&miss); |
@@ -1609,7 +1603,7 @@ |
} |
// Check that the maps haven't changed. |
- CheckPrototypes(object, rax, holder, rbx, rdx, name, &miss, rdi); |
+ CheckPrototypes(object, rax, holder, rbx, rdx, rdi, name, &miss); |
// Get the value from the cell. |
__ Move(rbx, Handle<JSGlobalPropertyCell>(cell)); |
@@ -1655,7 +1649,7 @@ |
__ j(not_equal, &miss); |
Failure* failure = Failure::InternalError(); |
- bool success = GenerateLoadCallback(receiver, holder, rdx, rax, rbx, rcx, |
+ bool success = GenerateLoadCallback(receiver, holder, rdx, rax, rbx, rcx, rdi, |
callback, name, &miss, &failure); |
if (!success) return failure; |
@@ -1709,7 +1703,7 @@ |
__ Cmp(rax, Handle<String>(name)); |
__ j(not_equal, &miss); |
- GenerateLoadConstant(receiver, holder, rdx, rbx, rcx, |
+ GenerateLoadConstant(receiver, holder, rdx, rbx, rcx, rdi, |
value, name, &miss); |
__ bind(&miss); |
__ DecrementCounter(&Counters::keyed_load_constant_function, 1); |
@@ -1769,6 +1763,7 @@ |
rax, |
rcx, |
rbx, |
+ rdi, |
name, |
&miss); |
__ bind(&miss); |
@@ -1984,7 +1979,7 @@ |
__ Cmp(rax, Handle<String>(name)); |
__ j(not_equal, &miss); |
- GenerateLoadField(receiver, holder, rdx, rbx, rcx, index, name, &miss); |
+ GenerateLoadField(receiver, holder, rdx, rbx, rcx, rdi, index, name, &miss); |
__ bind(&miss); |
__ DecrementCounter(&Counters::keyed_load_field, 1); |
@@ -2063,6 +2058,7 @@ |
Register name_reg, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
String* name, |
Label* miss) { |
ASSERT(interceptor_holder->HasNamedInterceptor()); |
@@ -2090,7 +2086,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. |
@@ -2138,6 +2135,7 @@ |
lookup->holder(), |
scratch1, |
scratch2, |
+ scratch3, |
name, |
miss); |
} |
@@ -2177,7 +2175,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); |
__ pop(scratch2); // save old return address |
PushInterceptorArguments(masm(), receiver, holder_reg, |
name_reg, interceptor_holder); |
@@ -2196,6 +2195,7 @@ |
Register name_reg, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
AccessorInfo* callback, |
String* name, |
Label* miss, |
@@ -2206,7 +2206,7 @@ |
// Check that the maps haven't changed. |
Register reg = |
CheckPrototypes(object, receiver, holder, |
- scratch1, scratch2, name, miss); |
+ scratch1, scratch2, scratch3, name, miss); |
// Push the arguments on the JS stack of the caller. |
__ pop(scratch2); // remove return address |
@@ -2231,14 +2231,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. On the first |
// iteration, reg is an alias for object_reg, on later iterations, |
@@ -2280,31 +2281,31 @@ |
miss, |
reg, |
name, |
- scratch, |
- extra); |
- __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
+ scratch1, |
+ scratch2); |
+ __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
reg = holder_reg; // from now the object is in holder_reg |
- __ movq(reg, FieldOperand(scratch, Map::kPrototypeOffset)); |
+ __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
} else if (Heap::InNewSpace(prototype)) { |
// Get the map of the current object. |
- __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
- __ Cmp(scratch, Handle<Map>(current->map())); |
+ __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
+ __ Cmp(scratch1, Handle<Map>(current->map())); |
// Branch on the result of the map check. |
__ j(not_equal, miss); |
// Check access rights to the global object. This has to happen |
// 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. |
// We load the prototype from the map in the scratch register. |
- __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
+ __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
} |
// The prototype is in new space; we cannot store a reference |
// to it in the code. Load it from the map. |
reg = holder_reg; // from now the object is in holder_reg |
- __ movq(reg, FieldOperand(scratch, Map::kPrototypeOffset)); |
+ __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
} else { |
// Check the map of the current object. |
@@ -2316,7 +2317,7 @@ |
// 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); |
} |
// The prototype is in old space; load it directly. |
reg = holder_reg; // from now the object is in holder_reg |
@@ -2343,7 +2344,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 |
@@ -2355,7 +2356,7 @@ |
Object* cell = GenerateCheckPropertyCell(masm(), |
GlobalObject::cast(current), |
name, |
- scratch, |
+ scratch1, |
miss); |
if (cell->IsFailure()) { |
set_failure(Failure::cast(cell)); |
@@ -2375,6 +2376,7 @@ |
Register receiver, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
int index, |
String* name, |
Label* miss) { |
@@ -2384,7 +2386,7 @@ |
// Check the prototype chain. |
Register reg = |
CheckPrototypes(object, receiver, holder, |
- scratch1, scratch2, name, miss); |
+ scratch1, scratch2, scratch3, name, miss); |
// Get the value from the properties. |
GenerateFastPropertyLoad(masm(), rax, reg, holder, index); |
@@ -2397,6 +2399,7 @@ |
Register receiver, |
Register scratch1, |
Register scratch2, |
+ Register scratch3, |
Object* value, |
String* name, |
Label* miss) { |
@@ -2406,7 +2409,7 @@ |
// Check that the maps haven't changed. |
Register reg = |
CheckPrototypes(object, receiver, holder, |
- scratch1, scratch2, name, miss); |
+ scratch1, scratch2, scratch3, name, miss); |
// Return the constant value. |
__ Move(rax, Handle<Object>(value)); |