StoreIC interface changed on ia32 to take receiver in edx, not on stack.
Review URL: http://codereview.chromium.org/555162 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3750 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
f40ecb18c3
commit
866eac3057
@ -4472,8 +4472,6 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
|
||||
Load(property->value());
|
||||
frame_->Push(key);
|
||||
Result ignored = frame_->CallStoreIC();
|
||||
// Drop the duplicated receiver and ignore the result.
|
||||
frame_->Drop();
|
||||
break;
|
||||
}
|
||||
// Fall through
|
||||
@ -6715,7 +6713,7 @@ void Reference::SetValue(InitState init_state) {
|
||||
cgen_->frame()->Push(GetName());
|
||||
Result answer = cgen_->frame()->CallStoreIC();
|
||||
cgen_->frame()->Push(&answer);
|
||||
cgen_->UnloadReference(this);
|
||||
set_unloaded();
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -917,10 +917,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
if (key->handle()->IsSymbol()) {
|
||||
VisitForValue(value, kAccumulator);
|
||||
__ mov(ecx, Immediate(key->handle()));
|
||||
__ mov(edx, Operand(esp, 0));
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
|
||||
__ call(ic, RelocInfo::CODE_TARGET);
|
||||
__ nop();
|
||||
// StoreIC leaves the receiver on the stack.
|
||||
break;
|
||||
}
|
||||
// Fall through.
|
||||
@ -1046,12 +1046,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
|
||||
// assignment. Right-hand-side value is passed in eax, variable name in
|
||||
// ecx, and the global object on the stack.
|
||||
__ mov(ecx, var->name());
|
||||
__ push(CodeGenerator::GlobalObject());
|
||||
__ mov(edx, CodeGenerator::GlobalObject());
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
|
||||
__ call(ic, RelocInfo::CODE_TARGET);
|
||||
__ nop();
|
||||
// Overwrite the receiver on the stack with the result if needed.
|
||||
DropAndApply(1, context, eax);
|
||||
Apply(context, eax);
|
||||
|
||||
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
|
||||
__ push(result_register()); // Value.
|
||||
@ -1111,6 +1110,11 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
// Record source code position before IC call.
|
||||
SetSourcePosition(expr->position());
|
||||
__ mov(ecx, prop->key()->AsLiteral()->handle());
|
||||
if (expr->ends_initialization_block()) {
|
||||
__ mov(edx, Operand(esp, 0));
|
||||
} else {
|
||||
__ pop(edx);
|
||||
}
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
|
||||
__ call(ic, RelocInfo::CODE_TARGET);
|
||||
__ nop();
|
||||
@ -1121,9 +1125,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
|
||||
__ push(Operand(esp, kPointerSize)); // Receiver is under value.
|
||||
__ CallRuntime(Runtime::kToFastProperties, 1);
|
||||
__ pop(eax);
|
||||
DropAndApply(1, context_, eax);
|
||||
} else {
|
||||
Apply(context_, eax);
|
||||
}
|
||||
|
||||
DropAndApply(1, context_, eax);
|
||||
}
|
||||
|
||||
|
||||
@ -1642,18 +1647,18 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
|
||||
break;
|
||||
case NAMED_PROPERTY: {
|
||||
__ mov(ecx, prop->key()->AsLiteral()->handle());
|
||||
__ pop(edx);
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
|
||||
__ call(ic, RelocInfo::CODE_TARGET);
|
||||
// This nop signals to the IC that there is no inlined code at the call
|
||||
// site for it to patch.
|
||||
__ nop();
|
||||
if (expr->is_postfix()) {
|
||||
__ Drop(1); // Result is on the stack under the receiver.
|
||||
if (context_ != Expression::kEffect) {
|
||||
ApplyTOS(context_);
|
||||
}
|
||||
} else {
|
||||
DropAndApply(1, context_, eax);
|
||||
Apply(context_, eax);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1379,12 +1379,10 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : value
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
|
||||
// Get the receiver from the stack and probe the stub cache.
|
||||
__ mov(edx, Operand(esp, 4));
|
||||
Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
|
||||
NOT_IN_LOOP,
|
||||
MONOMORPHIC);
|
||||
@ -1399,12 +1397,12 @@ void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : value
|
||||
// -- ecx : transition map
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
|
||||
__ pop(ebx);
|
||||
__ push(Operand(esp, 0)); // receiver
|
||||
__ push(edx); // receiver
|
||||
__ push(ecx); // transition map
|
||||
__ push(eax); // value
|
||||
__ push(ebx); // return address
|
||||
@ -1419,12 +1417,12 @@ void StoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : value
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
|
||||
__ pop(ebx);
|
||||
__ push(Operand(esp, 0));
|
||||
__ push(edx);
|
||||
__ push(ecx);
|
||||
__ push(eax);
|
||||
__ push(ebx);
|
||||
|
@ -1255,21 +1255,18 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object,
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : value
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
// Get the object from the stack.
|
||||
__ mov(ebx, Operand(esp, 1 * kPointerSize));
|
||||
|
||||
// Generate store field code. Trashes the name register.
|
||||
GenerateStoreField(masm(),
|
||||
Builtins::StoreIC_ExtendStorage,
|
||||
object,
|
||||
index,
|
||||
transition,
|
||||
ebx, ecx, edx,
|
||||
edx, ecx, ebx,
|
||||
&miss);
|
||||
|
||||
// Handle store cache miss.
|
||||
@ -1289,26 +1286,23 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : value
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
// Get the object from the stack.
|
||||
__ mov(ebx, Operand(esp, 1 * kPointerSize));
|
||||
|
||||
// Check that the object isn't a smi.
|
||||
__ test(ebx, Immediate(kSmiTagMask));
|
||||
__ test(edx, Immediate(kSmiTagMask));
|
||||
__ j(zero, &miss, not_taken);
|
||||
|
||||
// Check that the map of the object hasn't changed.
|
||||
__ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
|
||||
__ cmp(FieldOperand(edx, HeapObject::kMapOffset),
|
||||
Immediate(Handle<Map>(object->map())));
|
||||
__ j(not_equal, &miss, not_taken);
|
||||
|
||||
// Perform global security token check if needed.
|
||||
if (object->IsJSGlobalProxy()) {
|
||||
__ CheckAccessGlobalProxy(ebx, edx, &miss);
|
||||
__ CheckAccessGlobalProxy(edx, ebx, &miss);
|
||||
}
|
||||
|
||||
// Stub never generated for non-global objects that require access
|
||||
@ -1316,7 +1310,7 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
|
||||
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
|
||||
|
||||
__ pop(ebx); // remove the return address
|
||||
__ push(Operand(esp, 0)); // receiver
|
||||
__ push(edx); // receiver
|
||||
__ push(Immediate(Handle<AccessorInfo>(callback))); // callback info
|
||||
__ push(ecx); // name
|
||||
__ push(eax); // value
|
||||
@ -1342,26 +1336,23 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : value
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
// Get the object from the stack.
|
||||
__ mov(ebx, Operand(esp, 1 * kPointerSize));
|
||||
|
||||
// Check that the object isn't a smi.
|
||||
__ test(ebx, Immediate(kSmiTagMask));
|
||||
__ test(edx, Immediate(kSmiTagMask));
|
||||
__ j(zero, &miss, not_taken);
|
||||
|
||||
// Check that the map of the object hasn't changed.
|
||||
__ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
|
||||
__ cmp(FieldOperand(edx, HeapObject::kMapOffset),
|
||||
Immediate(Handle<Map>(receiver->map())));
|
||||
__ j(not_equal, &miss, not_taken);
|
||||
|
||||
// Perform global security token check if needed.
|
||||
if (receiver->IsJSGlobalProxy()) {
|
||||
__ CheckAccessGlobalProxy(ebx, edx, &miss);
|
||||
__ CheckAccessGlobalProxy(edx, ebx, &miss);
|
||||
}
|
||||
|
||||
// Stub never generated for non-global objects that require access
|
||||
@ -1369,7 +1360,7 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
|
||||
ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
|
||||
|
||||
__ pop(ebx); // remove the return address
|
||||
__ push(Operand(esp, 0)); // receiver
|
||||
__ push(edx); // receiver
|
||||
__ push(ecx); // name
|
||||
__ push(eax); // value
|
||||
__ push(ebx); // restore return address
|
||||
@ -1395,14 +1386,13 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
|
||||
// ----------- S t a t e -------------
|
||||
// -- eax : value
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -- esp[4] : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
// Check that the map of the global has not changed.
|
||||
__ mov(ebx, Operand(esp, kPointerSize));
|
||||
__ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
|
||||
__ cmp(FieldOperand(edx, HeapObject::kMapOffset),
|
||||
Immediate(Handle<Map>(object->map())));
|
||||
__ j(not_equal, &miss, not_taken);
|
||||
|
||||
|
@ -899,31 +899,45 @@ Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) {
|
||||
|
||||
Result VirtualFrame::CallStoreIC() {
|
||||
// Name, value, and receiver are on top of the frame. The IC
|
||||
// expects name in ecx, value in eax, and receiver on the stack. It
|
||||
// does not drop the receiver.
|
||||
// expects name in ecx, value in eax, and receiver in edx.
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
|
||||
Result name = Pop();
|
||||
Result value = Pop();
|
||||
PrepareForCall(1, 0); // One stack arg, not callee-dropped.
|
||||
Result receiver = Pop();
|
||||
PrepareForCall(0, 0);
|
||||
|
||||
if (value.is_register() && value.reg().is(ecx)) {
|
||||
if (name.is_register() && name.reg().is(eax)) {
|
||||
// Wrong registers.
|
||||
__ xchg(eax, ecx);
|
||||
} else {
|
||||
// Register eax is free for value, which frees ecx for name.
|
||||
value.ToRegister(eax);
|
||||
// Optimized for case in which name is a constant value.
|
||||
if (name.is_register() && (name.reg().is(edx) || name.reg().is(eax))) {
|
||||
if (!is_used(ecx)) {
|
||||
name.ToRegister(ecx);
|
||||
} else if (!is_used(ebx)) {
|
||||
name.ToRegister(ebx);
|
||||
} else {
|
||||
ASSERT(!is_used(edi)); // Only three results are live, so edi is free.
|
||||
name.ToRegister(edi);
|
||||
}
|
||||
}
|
||||
// Now name is not in edx or eax, so we can fix them, then move name to ecx.
|
||||
if (value.is_register() && value.reg().is(edx)) {
|
||||
if (receiver.is_register() && receiver.reg().is(eax)) {
|
||||
// Wrong registers.
|
||||
__ xchg(eax, edx);
|
||||
} else {
|
||||
// Register eax is free for value, which frees edx for receiver.
|
||||
value.ToRegister(eax);
|
||||
receiver.ToRegister(edx);
|
||||
}
|
||||
} else {
|
||||
// Register ecx is free for name, which guarantees eax is free for
|
||||
// Register edx is free for receiver, which guarantees eax is free for
|
||||
// value.
|
||||
name.ToRegister(ecx);
|
||||
receiver.ToRegister(edx);
|
||||
value.ToRegister(eax);
|
||||
}
|
||||
|
||||
// Receiver and value are in the right place, so ecx is free for name.
|
||||
name.ToRegister(ecx);
|
||||
name.Unuse();
|
||||
value.Unuse();
|
||||
receiver.Unuse();
|
||||
return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user