diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index 4440354b6d..c49ac89523 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -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::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 diff --git a/src/x64/virtual-frame-x64.cc b/src/x64/virtual-frame-x64.cc index bdff5a9341..b8b008c7a6 100644 --- a/src/x64/virtual-frame-x64.cc +++ b/src/x64/virtual-frame-x64.cc @@ -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, - 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, + 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 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 ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); return RawCallCodeObject(ic, mode); } -Result VirtualFrame::CallCommonStoreIC(Handle 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 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 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 ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); + return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); +} + + Result VirtualFrame::CallCallIC(RelocInfo::Mode mode, int arg_count, int loop_nesting) { diff --git a/src/x64/virtual-frame-x64.h b/src/x64/virtual-frame-x64.h index 05af957599..0479ff0c12 100644 --- a/src/x64/virtual-frame-x64.h +++ b/src/x64/virtual-frame-x64.h @@ -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 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 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 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 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,