Removing redundant stub for runtime native calls.

Review URL: http://codereview.chromium.org/543207

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3745 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
serya@chromium.org 2010-01-29 12:41:11 +00:00
parent 8588518851
commit 9239bbdd91
21 changed files with 95 additions and 104 deletions

View File

@ -2286,7 +2286,8 @@ void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
Comment cmnt(masm_, "[ DebuggerStatament"); Comment cmnt(masm_, "[ DebuggerStatament");
CodeForStatementPosition(node); CodeForStatementPosition(node);
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
frame_->CallRuntime(Runtime::kDebugBreak, 0); DebugerStatementStub ces;
frame_->CallStub(&ces, 0);
#endif #endif
// Ignore the return value. // Ignore the return value.
ASSERT(frame_->height() == original_height); ASSERT(frame_->height() == original_height);

View File

@ -98,7 +98,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
__ mov(r0, Operand(0)); // no arguments __ mov(r0, Operand(0)); // no arguments
__ mov(r1, Operand(ExternalReference::debug_break())); __ mov(r1, Operand(ExternalReference::debug_break()));
CEntryDebugBreakStub ceb; CEntryStub ceb(1);
__ CallStub(&ceb); __ CallStub(&ceb);
// Restore the register values containing object pointers from the expression // Restore the register values containing object pointers from the expression

View File

@ -1035,9 +1035,13 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
return; return;
} }
Runtime::FunctionId function_id = // TODO(1236192): Most runtime routines don't need the number of
static_cast<Runtime::FunctionId>(f->stub_id); // arguments passed in because it is constant. At some point we
RuntimeStub stub(function_id, num_arguments); // should remove this need and make the runtime routine entry code
// smarter.
mov(r0, Operand(num_arguments));
mov(r1, Operand(ExternalReference(f)));
CEntryStub stub(1);
CallStub(&stub); CallStub(&stub);
} }

View File

@ -55,9 +55,9 @@ namespace internal {
V(CounterOp) \ V(CounterOp) \
V(ArgumentsAccess) \ V(ArgumentsAccess) \
V(RegExpExec) \ V(RegExpExec) \
V(Runtime) \
V(CEntry) \ V(CEntry) \
V(JSEntry) V(JSEntry) \
V(DebuggerStatement)
// List of code stubs only used on ARM platforms. // List of code stubs only used on ARM platforms.
#ifdef V8_TARGET_ARCH_ARM #ifdef V8_TARGET_ARCH_ARM

View File

@ -452,11 +452,6 @@ void CodeGenerator::CodeForSourcePosition(int pos) {
} }
const char* RuntimeStub::GetName() {
return Runtime::FunctionForId(id_)->stub_name;
}
const char* GenericUnaryOpStub::GetName() { const char* GenericUnaryOpStub::GetName() {
switch (op_) { switch (op_) {
case Token::SUB: case Token::SUB:
@ -474,14 +469,6 @@ const char* GenericUnaryOpStub::GetName() {
} }
void RuntimeStub::Generate(MacroAssembler* masm) {
Runtime::Function* f = Runtime::FunctionForId(id_);
masm->TailCallRuntime(ExternalReference(f),
num_arguments_,
f->result_size);
}
void ArgumentsAccessStub::Generate(MacroAssembler* masm) { void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
switch (type_) { switch (type_) {
case READ_LENGTH: GenerateReadLength(masm); break; case READ_LENGTH: GenerateReadLength(masm); break;
@ -507,4 +494,10 @@ void ApiGetterEntryStub::SetCustomCache(Code* value) {
} }
void DebugerStatementStub::Generate(MacroAssembler* masm) {
Runtime::Function* f = Runtime::FunctionForId(Runtime::kDebugBreak);
masm->TailCallRuntime(ExternalReference(f), 0, f->result_size);
}
} } // namespace v8::internal } } // namespace v8::internal

View File

@ -181,43 +181,6 @@ class DeferredCode: public ZoneObject {
DISALLOW_COPY_AND_ASSIGN(DeferredCode); DISALLOW_COPY_AND_ASSIGN(DeferredCode);
}; };
// RuntimeStub models code stubs calling entry points in the Runtime class.
class RuntimeStub : public CodeStub {
public:
explicit RuntimeStub(Runtime::FunctionId id, int num_arguments)
: id_(id), num_arguments_(num_arguments) { }
void Generate(MacroAssembler* masm);
// Disassembler support. It is useful to be able to print the name
// of the runtime function called through this stub.
static const char* GetNameFromMinorKey(int minor_key) {
return Runtime::FunctionForId(IdField::decode(minor_key))->stub_name;
}
private:
Runtime::FunctionId id_;
int num_arguments_;
class ArgumentField: public BitField<int, 0, 16> {};
class IdField: public BitField<Runtime::FunctionId, 16, kMinorBits - 16> {};
Major MajorKey() { return Runtime; }
int MinorKey() {
return IdField::encode(id_) | ArgumentField::encode(num_arguments_);
}
const char* GetName();
#ifdef DEBUG
void Print() {
PrintF("RuntimeStub (id %s)\n", Runtime::FunctionForId(id_)->name);
}
#endif
};
class StackCheckStub : public CodeStub { class StackCheckStub : public CodeStub {
public: public:
StackCheckStub() { } StackCheckStub() { }
@ -422,16 +385,18 @@ class ApiGetterEntryStub : public CodeStub {
}; };
class CEntryDebugBreakStub : public CEntryStub { // Mark the debugger statemet to be recognized bu debugger (by the MajorKey)
class DebugerStatementStub : public CodeStub {
public: public:
CEntryDebugBreakStub() : CEntryStub(1) { } DebugerStatementStub() { }
void Generate(MacroAssembler* masm) { GenerateBody(masm, true); } void Generate(MacroAssembler* masm);
private: private:
int MinorKey() { return 1; } Major MajorKey() { return DebuggerStatement; }
int MinorKey() { return 0; }
const char* GetName() { return "CEntryDebugBreakStub"; } const char* GetName() { return "DebugerStatementStub"; }
}; };

View File

@ -75,9 +75,6 @@ BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
BreakLocatorType type) { BreakLocatorType type) {
debug_info_ = debug_info; debug_info_ = debug_info;
type_ = type; type_ = type;
// Get the stub early to avoid possible GC during iterations. We may need
// this stub to detect debugger calls generated from debugger statements.
debug_break_stub_ = RuntimeStub(Runtime::kDebugBreak, 0).GetCode();
reloc_iterator_ = NULL; reloc_iterator_ = NULL;
reloc_iterator_original_ = NULL; reloc_iterator_original_ = NULL;
Reset(); // Initialize the rest of the member variables. Reset(); // Initialize the rest of the member variables.
@ -461,9 +458,7 @@ bool BreakLocationIterator::IsDebuggerStatement() {
Code* code = Code::GetCodeFromTargetAddress(target); Code* code = Code::GetCodeFromTargetAddress(target);
if (code->kind() == Code::STUB) { if (code->kind() == Code::STUB) {
CodeStub::Major major_key = code->major_key(); CodeStub::Major major_key = code->major_key();
if (major_key == CodeStub::Runtime) { return (major_key == CodeStub::DebuggerStatement);
return (*debug_break_stub_ == code);
}
} }
} }
return false; return false;

View File

@ -132,7 +132,6 @@ class BreakLocationIterator {
int position_; int position_;
int statement_position_; int statement_position_;
Handle<DebugInfo> debug_info_; Handle<DebugInfo> debug_info_;
Handle<Code> debug_break_stub_;
RelocIterator* reloc_iterator_; RelocIterator* reloc_iterator_;
RelocIterator* reloc_iterator_original_; RelocIterator* reloc_iterator_original_;

View File

@ -266,13 +266,7 @@ static int DecodeIt(FILE* f,
case CodeStub::CallFunction: case CodeStub::CallFunction:
out.AddFormatted("argc = %d", minor_key); out.AddFormatted("argc = %d", minor_key);
break; break;
case CodeStub::Runtime: { default:
const char* name =
RuntimeStub::GetNameFromMinorKey(minor_key);
out.AddFormatted("%s", name);
break;
}
default:
out.AddFormatted("minor: %d", minor_key); out.AddFormatted("minor: %d", minor_key);
} }
} }

View File

@ -998,7 +998,9 @@ void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
Comment cmnt(masm_, "[ DebuggerStatement"); Comment cmnt(masm_, "[ DebuggerStatement");
SetStatementPosition(stmt); SetStatementPosition(stmt);
__ CallRuntime(Runtime::kDebugBreak, 0);
DebugerStatementStub ces;
__ CallStub(&ces);
// Ignore the return value. // Ignore the return value.
#endif #endif
} }

View File

@ -1499,7 +1499,7 @@ void Heap::CreateRegExpCEntryStub() {
void Heap::CreateCEntryDebugBreakStub() { void Heap::CreateCEntryDebugBreakStub() {
CEntryDebugBreakStub stub; DebugerStatementStub stub;
set_c_entry_debug_break_code(*stub.GetCode()); set_c_entry_debug_break_code(*stub.GetCode());
} }
@ -1526,7 +1526,7 @@ void Heap::CreateFixedStubs() {
// { CEntryStub stub; // { CEntryStub stub;
// c_entry_code_ = *stub.GetCode(); // c_entry_code_ = *stub.GetCode();
// } // }
// { CEntryDebugBreakStub stub; // { DebugerStatementStub stub;
// c_entry_debug_break_code_ = *stub.GetCode(); // c_entry_debug_break_code_ = *stub.GetCode();
// } // }
// To workaround the problem, make separate functions without inlining. // To workaround the problem, make separate functions without inlining.

View File

@ -3901,7 +3901,9 @@ void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
// Spill everything, even constants, to the frame. // Spill everything, even constants, to the frame.
frame_->SpillAll(); frame_->SpillAll();
frame_->CallRuntime(Runtime::kDebugBreak, 0);
DebugerStatementStub ces;
frame_->CallStub(&ces, 0);
// Ignore the return value. // Ignore the return value.
#endif #endif
} }

View File

@ -94,7 +94,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
__ Set(eax, Immediate(0)); // no arguments __ Set(eax, Immediate(0)); // no arguments
__ mov(ebx, Immediate(ExternalReference::debug_break())); __ mov(ebx, Immediate(ExternalReference::debug_break()));
CEntryDebugBreakStub ceb; CEntryStub ceb(1);
__ CallStub(&ceb); __ CallStub(&ceb);
// Restore the register values containing object pointers from the expression // Restore the register values containing object pointers from the expression

View File

@ -1098,10 +1098,14 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
return; return;
} }
Runtime::FunctionId function_id = // TODO(1236192): Most runtime routines don't need the number of
static_cast<Runtime::FunctionId>(f->stub_id); // arguments passed in because it is constant. At some point we
RuntimeStub stub(function_id, num_arguments); // should remove this need and make the runtime routine entry code
CallStub(&stub); // smarter.
Set(eax, Immediate(num_arguments));
mov(ebx, Immediate(ExternalReference(f)));
CEntryStub ces(1);
CallStub(&ces);
} }
@ -1114,10 +1118,14 @@ Object* MacroAssembler::TryCallRuntime(Runtime::Function* f,
return Heap::undefined_value(); return Heap::undefined_value();
} }
Runtime::FunctionId function_id = // TODO(1236192): Most runtime routines don't need the number of
static_cast<Runtime::FunctionId>(f->stub_id); // arguments passed in because it is constant. At some point we
RuntimeStub stub(function_id, num_arguments); // should remove this need and make the runtime routine entry code
return TryCallStub(&stub); // smarter.
Set(eax, Immediate(num_arguments));
mov(ebx, Immediate(ExternalReference(f)));
CEntryStub ces(1);
return TryCallStub(&ces);
} }

View File

@ -331,7 +331,7 @@ class MacroAssembler: public Assembler {
// Eventually this should be used for all C calls. // Eventually this should be used for all C calls.
void CallRuntime(Runtime::Function* f, int num_arguments); void CallRuntime(Runtime::Function* f, int num_arguments);
// Call a runtime function, returning the RuntimeStub object called. // Call a runtime function, returning the CodeStub object called.
// Try to generate the stub code if necessary. Do not perform a GC // Try to generate the stub code if necessary. Do not perform a GC
// but instead return a retry after GC failure. // but instead return a retry after GC failure.
Object* TryCallRuntime(Runtime::Function* f, int num_arguments); Object* TryCallRuntime(Runtime::Function* f, int num_arguments);

View File

@ -8130,12 +8130,12 @@ static Object* Runtime_IS_VAR(Arguments args) {
// Implementation of Runtime // Implementation of Runtime
#define F(name, nargs, ressize) \ #define F(name, nargs, ressize) \
{ #name, "RuntimeStub_" #name, FUNCTION_ADDR(Runtime_##name), nargs, \ { #name, FUNCTION_ADDR(Runtime_##name), nargs, \
static_cast<int>(Runtime::k##name), ressize }, static_cast<int>(Runtime::k##name), ressize },
static Runtime::Function Runtime_functions[] = { static Runtime::Function Runtime_functions[] = {
RUNTIME_FUNCTION_LIST(F) RUNTIME_FUNCTION_LIST(F)
{ NULL, NULL, NULL, 0, -1, 0 } { NULL, NULL, 0, -1, 0 }
}; };
#undef F #undef F

View File

@ -373,9 +373,6 @@ class Runtime : public AllStatic {
// The JS name of the function. // The JS name of the function.
const char* name; const char* name;
// The name of the stub that calls the runtime function.
const char* stub_name;
// The C++ (native) entry point. // The C++ (native) entry point.
byte* entry; byte* entry;

View File

@ -2212,7 +2212,9 @@ void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
// Spill everything, even constants, to the frame. // Spill everything, even constants, to the frame.
frame_->SpillAll(); frame_->SpillAll();
frame_->CallRuntime(Runtime::kDebugBreak, 0);
DebugerStatementStub ces;
frame_->CallStub(&ces, 0);
// Ignore the return value. // Ignore the return value.
#endif #endif
} }
@ -7337,9 +7339,7 @@ int CEntryStub::MinorKey() {
#ifdef _WIN64 #ifdef _WIN64
// Simple results returned in rax (using default code). // Simple results returned in rax (using default code).
// Complex results must be written to address passed as first argument. // Complex results must be written to address passed as first argument.
// Use even numbers for minor keys, reserving the odd numbers for return (result_size_ < 2) ? 0 : 1;
// CEntryDebugBreakStub.
return (result_size_ < 2) ? 0 : result_size_ * 2;
#else #else
// Single results returned in rax (both AMD64 and Win64 calling conventions) // Single results returned in rax (both AMD64 and Win64 calling conventions)
// and a struct of two pointers in rax+rdx (AMD64 calling convention only) // and a struct of two pointers in rax+rdx (AMD64 calling convention only)

View File

@ -68,7 +68,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
__ xor_(rax, rax); // No arguments (argc == 0). __ xor_(rax, rax); // No arguments (argc == 0).
__ movq(rbx, ExternalReference::debug_break()); __ movq(rbx, ExternalReference::debug_break());
CEntryDebugBreakStub ceb; CEntryStub ceb(1);
__ CallStub(&ceb); __ CallStub(&ceb);
// Restore the register values containing object pointers from the expression // Restore the register values containing object pointers from the expression

View File

@ -344,10 +344,14 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
return; return;
} }
Runtime::FunctionId function_id = // TODO(1236192): Most runtime routines don't need the number of
static_cast<Runtime::FunctionId>(f->stub_id); // arguments passed in because it is constant. At some point we
RuntimeStub stub(function_id, num_arguments); // should remove this need and make the runtime routine entry code
CallStub(&stub); // smarter.
movq(rax, Immediate(num_arguments));
movq(rbx, ExternalReference(f));
CEntryStub ces(f->result_size);
CallStub(&ces);
} }

View File

@ -2047,6 +2047,33 @@ TEST(DebuggerStatement) {
} }
// Test setting a breakpoint on the debugger statement.
TEST(DebuggerStatementBreakpoint) {
break_point_hit_count = 0;
v8::HandleScope scope;
DebugLocalContext env;
v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
v8::Undefined());
v8::Script::Compile(v8::String::New("function foo(){debugger;}"))->Run();
v8::Local<v8::Function> foo =
v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
// The debugger statement triggers breakpint hit
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(1, break_point_hit_count);
int bp = SetBreakPoint(foo, 0);
// Set breakpoint does not duplicate hits
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(2, break_point_hit_count);
ClearBreakPoint(bp);
v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
// Thest that the evaluation of expressions when a break point is hit generates // Thest that the evaluation of expressions when a break point is hit generates
// the correct results. // the correct results.
TEST(DebugEvaluate) { TEST(DebugEvaluate) {