Remove VirtualFrame::CallStoreIC(void) and CallCommonStoreIC from virtual-frame-x64.cc. Make implementations of CallStoreIC(key, is_contextual) and CallKeyedStoreIC() the same on x64 and ia32. Make ia32 and x64 implementations more alike by moving some functions and changing comments.
Review URL: http://codereview.chromium.org/3060002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5113 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
9174700dca
commit
8105e9baa3
@ -4840,8 +4840,13 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
|
||||
// Duplicate the object as the IC receiver.
|
||||
frame_->Dup();
|
||||
Load(property->value());
|
||||
frame_->Push(key);
|
||||
Result ignored = frame_->CallStoreIC();
|
||||
Result dummy = frame_->CallStoreIC(Handle<String>::cast(key), false);
|
||||
// A test eax instruction following the store IC call would
|
||||
// indicate the presence of an inlined version of the
|
||||
// store. Add a nop to indicate that there is no such
|
||||
// inlined version.
|
||||
__ nop();
|
||||
dummy.Unuse();
|
||||
break;
|
||||
}
|
||||
// Fall through
|
||||
|
@ -997,31 +997,9 @@ void VirtualFrame::SyncRange(int begin, int end) {
|
||||
}
|
||||
|
||||
|
||||
Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
|
||||
InvokeFlag flag,
|
||||
int arg_count) {
|
||||
PrepareForCall(arg_count, arg_count);
|
||||
ASSERT(cgen()->HasValidEntryRegisters());
|
||||
__ InvokeBuiltin(id, flag);
|
||||
Result result = cgen()->allocator()->Allocate(rax);
|
||||
ASSERT(result.is_valid());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Virtual frame stub and IC calling functions.
|
||||
|
||||
Result VirtualFrame::RawCallCodeObject(Handle<Code> code,
|
||||
RelocInfo::Mode rmode) {
|
||||
ASSERT(cgen()->HasValidEntryRegisters());
|
||||
__ Call(code, rmode);
|
||||
Result result = cgen()->allocator()->Allocate(rax);
|
||||
ASSERT(result.is_valid());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) {
|
||||
PrepareForCall(arg_count, arg_count);
|
||||
ASSERT(cgen()->HasValidEntryRegisters());
|
||||
@ -1053,6 +1031,28 @@ void VirtualFrame::DebugBreak() {
|
||||
#endif
|
||||
|
||||
|
||||
Result VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
|
||||
InvokeFlag flag,
|
||||
int arg_count) {
|
||||
PrepareForCall(arg_count, arg_count);
|
||||
ASSERT(cgen()->HasValidEntryRegisters());
|
||||
__ InvokeBuiltin(id, flag);
|
||||
Result result = cgen()->allocator()->Allocate(rax);
|
||||
ASSERT(result.is_valid());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Result VirtualFrame::RawCallCodeObject(Handle<Code> code,
|
||||
RelocInfo::Mode rmode) {
|
||||
ASSERT(cgen()->HasValidEntryRegisters());
|
||||
__ Call(code, rmode);
|
||||
Result result = cgen()->allocator()->Allocate(rax);
|
||||
ASSERT(result.is_valid());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// This function assumes that the only results that could be in a_reg or b_reg
|
||||
// are a and b. Other results can be live, but must not be in a_reg or b_reg.
|
||||
void VirtualFrame::MoveResultsToRegisters(Result* a,
|
||||
@ -1107,67 +1107,17 @@ Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) {
|
||||
|
||||
|
||||
Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) {
|
||||
// Key and receiver are on top of the frame. The IC expects them on
|
||||
// the stack. It does not drop them.
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
|
||||
Result name = Pop();
|
||||
// Key and receiver are on top of the frame. Put them in rax and rdx.
|
||||
Result key = Pop();
|
||||
Result receiver = Pop();
|
||||
PrepareForCall(0, 0);
|
||||
MoveResultsToRegisters(&name, &receiver, rax, rdx);
|
||||
MoveResultsToRegisters(&key, &receiver, rax, rdx);
|
||||
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
|
||||
return RawCallCodeObject(ic, mode);
|
||||
}
|
||||
|
||||
|
||||
Result VirtualFrame::CallCommonStoreIC(Handle<Code> ic,
|
||||
Result* value,
|
||||
Result* key,
|
||||
Result* receiver) {
|
||||
// The IC expects value in rax, key in rcx, and receiver in rdx.
|
||||
PrepareForCall(0, 0);
|
||||
// If one of the three registers is free, or a value is already
|
||||
// in the correct register, move the remaining two values using
|
||||
// MoveResultsToRegisters().
|
||||
if (!cgen()->allocator()->is_used(rax) ||
|
||||
(value->is_register() && value->reg().is(rax))) {
|
||||
if (!cgen()->allocator()->is_used(rax)) {
|
||||
value->ToRegister(rax);
|
||||
}
|
||||
MoveResultsToRegisters(key, receiver, rcx, rdx);
|
||||
value->Unuse();
|
||||
} else if (!cgen()->allocator()->is_used(rcx) ||
|
||||
(key->is_register() && key->reg().is(rcx))) {
|
||||
if (!cgen()->allocator()->is_used(rcx)) {
|
||||
key->ToRegister(rcx);
|
||||
}
|
||||
MoveResultsToRegisters(value, receiver, rax, rdx);
|
||||
key->Unuse();
|
||||
} else if (!cgen()->allocator()->is_used(rdx) ||
|
||||
(receiver->is_register() && receiver->reg().is(rdx))) {
|
||||
if (!cgen()->allocator()->is_used(rdx)) {
|
||||
receiver->ToRegister(rdx);
|
||||
}
|
||||
MoveResultsToRegisters(key, value, rcx, rax);
|
||||
receiver->Unuse();
|
||||
} else {
|
||||
// Otherwise, no register is free, and no value is in the correct place.
|
||||
// We have one of the two circular permutations of eax, ecx, edx.
|
||||
ASSERT(value->is_register());
|
||||
if (value->reg().is(rcx)) {
|
||||
__ xchg(rax, rdx);
|
||||
__ xchg(rax, rcx);
|
||||
} else {
|
||||
__ xchg(rax, rcx);
|
||||
__ xchg(rax, rdx);
|
||||
}
|
||||
value->Unuse();
|
||||
key->Unuse();
|
||||
receiver->Unuse();
|
||||
}
|
||||
|
||||
return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
Result VirtualFrame::CallStoreIC(Handle<String> name, bool is_contextual) {
|
||||
// Value and (if not contextual) receiver are on top of the frame.
|
||||
// The IC expects name in rcx, value in rax, and receiver in rdx.
|
||||
@ -1188,6 +1138,55 @@ Result VirtualFrame::CallStoreIC(Handle<String> name, bool is_contextual) {
|
||||
}
|
||||
|
||||
|
||||
Result VirtualFrame::CallKeyedStoreIC() {
|
||||
// Value, key, and receiver are on the top of the frame. The IC
|
||||
// expects value in rax, key in rcx, and receiver in rdx.
|
||||
Result value = Pop();
|
||||
Result key = Pop();
|
||||
Result receiver = Pop();
|
||||
PrepareForCall(0, 0);
|
||||
if (!cgen()->allocator()->is_used(rax) ||
|
||||
(value.is_register() && value.reg().is(rax))) {
|
||||
if (!cgen()->allocator()->is_used(rax)) {
|
||||
value.ToRegister(rax);
|
||||
}
|
||||
MoveResultsToRegisters(&key, &receiver, rcx, rdx);
|
||||
value.Unuse();
|
||||
} else if (!cgen()->allocator()->is_used(rcx) ||
|
||||
(key.is_register() && key.reg().is(rcx))) {
|
||||
if (!cgen()->allocator()->is_used(rcx)) {
|
||||
key.ToRegister(rcx);
|
||||
}
|
||||
MoveResultsToRegisters(&value, &receiver, rax, rdx);
|
||||
key.Unuse();
|
||||
} else if (!cgen()->allocator()->is_used(rdx) ||
|
||||
(receiver.is_register() && receiver.reg().is(rdx))) {
|
||||
if (!cgen()->allocator()->is_used(rdx)) {
|
||||
receiver.ToRegister(rdx);
|
||||
}
|
||||
MoveResultsToRegisters(&key, &value, rcx, rax);
|
||||
receiver.Unuse();
|
||||
} else {
|
||||
// All three registers are used, and no value is in the correct place.
|
||||
// We have one of the two circular permutations of rax, rcx, rdx.
|
||||
ASSERT(value.is_register());
|
||||
if (value.reg().is(rcx)) {
|
||||
__ xchg(rax, rdx);
|
||||
__ xchg(rax, rcx);
|
||||
} else {
|
||||
__ xchg(rax, rcx);
|
||||
__ xchg(rax, rdx);
|
||||
}
|
||||
value.Unuse();
|
||||
key.Unuse();
|
||||
receiver.Unuse();
|
||||
}
|
||||
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
|
||||
return RawCallCodeObject(ic, RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
Result VirtualFrame::CallCallIC(RelocInfo::Mode mode,
|
||||
int arg_count,
|
||||
int loop_nesting) {
|
||||
|
@ -329,50 +329,27 @@ class VirtualFrame : public ZoneObject {
|
||||
int arg_count);
|
||||
|
||||
// Call load IC. Name and receiver are found on top of the frame.
|
||||
// Receiver is not dropped.
|
||||
// Both are dropped.
|
||||
Result CallLoadIC(RelocInfo::Mode mode);
|
||||
|
||||
// Call keyed load IC. Key and receiver are found on top of the
|
||||
// frame. They are not dropped.
|
||||
// frame. Both are dropped.
|
||||
Result CallKeyedLoadIC(RelocInfo::Mode mode);
|
||||
|
||||
|
||||
// Calling a store IC and a keyed store IC differ only by which ic is called
|
||||
// and by the order of the three arguments on the frame.
|
||||
Result CallCommonStoreIC(Handle<Code> ic,
|
||||
Result* value,
|
||||
Result* key,
|
||||
Result* receiver);
|
||||
|
||||
// Call store IC. Name, value, and receiver are found on top
|
||||
// of the frame. All are dropped.
|
||||
Result CallStoreIC() {
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
|
||||
Result name = Pop();
|
||||
Result value = Pop();
|
||||
Result receiver = Pop();
|
||||
return CallCommonStoreIC(ic, &value, &name, &receiver);
|
||||
}
|
||||
|
||||
// Call store IC. If the load is contextual, value is found on top of the
|
||||
// frame. If not, value and receiver are on the frame. Both are dropped.
|
||||
Result CallStoreIC(Handle<String> name, bool is_contextual);
|
||||
|
||||
// Call keyed store IC. Value, key, and receiver are found on top
|
||||
// of the frame. All are dropped.
|
||||
Result CallKeyedStoreIC() {
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
|
||||
Result value = Pop();
|
||||
Result key = Pop();
|
||||
Result receiver = Pop();
|
||||
return CallCommonStoreIC(ic, &value, &key, &receiver);
|
||||
}
|
||||
// of the frame. All three are dropped.
|
||||
Result CallKeyedStoreIC();
|
||||
|
||||
// Call call IC. Function name, arguments, and receiver are found on top
|
||||
// of the frame and dropped by the call.
|
||||
// The argument count does not include the receiver.
|
||||
Result CallCallIC(RelocInfo::Mode mode, int arg_count, int loop_nesting);
|
||||
|
||||
// Call keyed call IC. Same calling convention as CallCallIC.
|
||||
Result CallKeyedCallIC(RelocInfo::Mode mode, int arg_count, int loop_nesting);
|
||||
|
||||
// Allocate and call JS function as constructor. Arguments,
|
||||
|
Loading…
Reference in New Issue
Block a user