Commit e98e7c9f authored by plind44@gmail.com's avatar plind44@gmail.com

MIPS: Lazily save double registers for HCallRuntime instructions within Hydrogen code stubs.

Port r17044 (94843cc)

Original commit message:
Right now we eagerly save all allocatable double registers upon
entry to every Hydrogen code stub that uses HCallRuntime, and
restore them when we return. Since the HCallRuntime is on the
fallback path for code stubs, this is both a waste of time and
stack space in almost every case.

This patch adds a flag to the HCallRuntime, which controls whether
the instruction saves the double register itself (using the save
doubles flag for the CEntryStub), or whether its up the surrounding
code to handle the clobbering of double registers.

BUG=
R=plind44@gmail.com

Review URL: https://codereview.chromium.org/25567002

Patch from Balazs Kilvady <kilvadyb@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17057 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 05c62c2e
...@@ -712,13 +712,15 @@ void LCodeGen::CallCodeGeneric(Handle<Code> code, ...@@ -712,13 +712,15 @@ void LCodeGen::CallCodeGeneric(Handle<Code> code,
void LCodeGen::CallRuntime(const Runtime::Function* function, void LCodeGen::CallRuntime(const Runtime::Function* function,
int num_arguments, int num_arguments,
LInstruction* instr) { LInstruction* instr,
SaveFPRegsMode save_doubles) {
ASSERT(instr != NULL); ASSERT(instr != NULL);
LPointerMap* pointers = instr->pointer_map(); LPointerMap* pointers = instr->pointer_map();
ASSERT(pointers != NULL); ASSERT(pointers != NULL);
RecordPosition(pointers->position()); RecordPosition(pointers->position());
__ CallRuntime(function, num_arguments); __ CallRuntime(function, num_arguments, save_doubles);
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
} }
......
...@@ -245,7 +245,8 @@ class LCodeGen V8_FINAL BASE_EMBEDDED { ...@@ -245,7 +245,8 @@ class LCodeGen V8_FINAL BASE_EMBEDDED {
void CallRuntime(const Runtime::Function* function, void CallRuntime(const Runtime::Function* function,
int num_arguments, int num_arguments,
LInstruction* instr); LInstruction* instr,
SaveFPRegsMode save_doubles = kDontSaveFPRegs);
void CallRuntime(Runtime::FunctionId id, void CallRuntime(Runtime::FunctionId id,
int num_arguments, int num_arguments,
......
...@@ -867,6 +867,10 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) { ...@@ -867,6 +867,10 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
LInstruction* instr = current->CompileToLithium(this); LInstruction* instr = current->CompileToLithium(this);
if (instr != NULL) { if (instr != NULL) {
// Associate the hydrogen instruction first, since we may need it for
// the ClobbersRegisters() or ClobbersDoubleRegisters() calls below.
instr->set_hydrogen_value(current);
#if DEBUG #if DEBUG
// Make sure that the lithium instruction has either no fixed register // Make sure that the lithium instruction has either no fixed register
// constraints in temps or the result OR no uses that are only used at // constraints in temps or the result OR no uses that are only used at
...@@ -903,7 +907,6 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) { ...@@ -903,7 +907,6 @@ void LChunkBuilder::VisitInstruction(HInstruction* current) {
if (FLAG_stress_environments && !instr->HasEnvironment()) { if (FLAG_stress_environments && !instr->HasEnvironment()) {
instr = AssignEnvironment(instr); instr = AssignEnvironment(instr);
} }
instr->set_hydrogen_value(current);
chunk_->AddInstruction(instr, current_block_); chunk_->AddInstruction(instr, current_block_);
} }
current_instruction_ = old_current; current_instruction_ = old_current;
......
...@@ -274,7 +274,7 @@ class LInstruction : public ZoneObject { ...@@ -274,7 +274,7 @@ class LInstruction : public ZoneObject {
// Interface to the register allocator and iterators. // Interface to the register allocator and iterators.
bool ClobbersTemps() const { return IsCall(); } bool ClobbersTemps() const { return IsCall(); }
bool ClobbersRegisters() const { return IsCall(); } bool ClobbersRegisters() const { return IsCall(); }
bool ClobbersDoubleRegisters() const { return IsCall(); } virtual bool ClobbersDoubleRegisters() const { return IsCall(); }
// Interface to the register allocator and iterators. // Interface to the register allocator and iterators.
bool IsMarkedAsCall() const { return IsCall(); } bool IsMarkedAsCall() const { return IsCall(); }
...@@ -1963,8 +1963,13 @@ class LCallRuntime V8_FINAL : public LTemplateInstruction<1, 0, 0> { ...@@ -1963,8 +1963,13 @@ class LCallRuntime V8_FINAL : public LTemplateInstruction<1, 0, 0> {
DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime") DECLARE_CONCRETE_INSTRUCTION(CallRuntime, "call-runtime")
DECLARE_HYDROGEN_ACCESSOR(CallRuntime) DECLARE_HYDROGEN_ACCESSOR(CallRuntime)
virtual bool ClobbersDoubleRegisters() const V8_OVERRIDE {
return save_doubles() == kDontSaveFPRegs;
}
const Runtime::Function* function() const { return hydrogen()->function(); } const Runtime::Function* function() const { return hydrogen()->function(); }
int arity() const { return hydrogen()->argument_count(); } int arity() const { return hydrogen()->argument_count(); }
SaveFPRegsMode save_doubles() const { return hydrogen()->save_doubles(); }
}; };
......
...@@ -4136,7 +4136,8 @@ void MacroAssembler::SubuAndCheckForOverflow(Register dst, ...@@ -4136,7 +4136,8 @@ void MacroAssembler::SubuAndCheckForOverflow(Register dst,
void MacroAssembler::CallRuntime(const Runtime::Function* f, void MacroAssembler::CallRuntime(const Runtime::Function* f,
int num_arguments) { int num_arguments,
SaveFPRegsMode save_doubles) {
// All parameters are on the stack. v0 has the return value after call. // All parameters are on the stack. v0 has the return value after call.
// If the expected number of arguments of the runtime function is // If the expected number of arguments of the runtime function is
...@@ -4153,25 +4154,11 @@ void MacroAssembler::CallRuntime(const Runtime::Function* f, ...@@ -4153,25 +4154,11 @@ void MacroAssembler::CallRuntime(const Runtime::Function* f,
// smarter. // smarter.
PrepareCEntryArgs(num_arguments); PrepareCEntryArgs(num_arguments);
PrepareCEntryFunction(ExternalReference(f, isolate())); PrepareCEntryFunction(ExternalReference(f, isolate()));
CEntryStub stub(1); CEntryStub stub(1, save_doubles);
CallStub(&stub);
}
void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
const Runtime::Function* function = Runtime::FunctionForId(id);
PrepareCEntryArgs(function->nargs);
PrepareCEntryFunction(ExternalReference(function, isolate()));
CEntryStub stub(1, kSaveFPRegs);
CallStub(&stub); CallStub(&stub);
} }
void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) {
CallRuntime(Runtime::FunctionForId(fid), num_arguments);
}
void MacroAssembler::CallExternalReference(const ExternalReference& ext, void MacroAssembler::CallExternalReference(const ExternalReference& ext,
int num_arguments, int num_arguments,
BranchDelaySlot bd) { BranchDelaySlot bd) {
......
...@@ -1201,11 +1201,18 @@ class MacroAssembler: public Assembler { ...@@ -1201,11 +1201,18 @@ class MacroAssembler: public Assembler {
void CallJSExitStub(CodeStub* stub); void CallJSExitStub(CodeStub* stub);
// Call a runtime routine. // Call a runtime routine.
void CallRuntime(const Runtime::Function* f, int num_arguments); void CallRuntime(const Runtime::Function* f,
void CallRuntimeSaveDoubles(Runtime::FunctionId id); int num_arguments,
SaveFPRegsMode save_doubles = kDontSaveFPRegs);
void CallRuntimeSaveDoubles(Runtime::FunctionId id) {
const Runtime::Function* function = Runtime::FunctionForId(id);
CallRuntime(function, function->nargs, kSaveFPRegs);
}
// Convenience function: Same as above, but takes the fid instead. // Convenience function: Same as above, but takes the fid instead.
void CallRuntime(Runtime::FunctionId fid, int num_arguments); void CallRuntime(Runtime::FunctionId id, int num_arguments) {
CallRuntime(Runtime::FunctionForId(id), num_arguments);
}
// Convenience function: call an external reference. // Convenience function: call an external reference.
void CallExternalReference(const ExternalReference& ext, void CallExternalReference(const ExternalReference& ext,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment