Removing redundant stub for runtime native calls.
authorserya@chromium.org <serya@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 29 Jan 2010 12:41:11 +0000 (12:41 +0000)
committerserya@chromium.org <serya@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 29 Jan 2010 12:41:11 +0000 (12:41 +0000)
Review URL: http://codereview.chromium.org/543207

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3745 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

21 files changed:
src/arm/codegen-arm.cc
src/arm/debug-arm.cc
src/arm/macro-assembler-arm.cc
src/code-stubs.h
src/codegen.cc
src/codegen.h
src/debug.cc
src/debug.h
src/disassembler.cc
src/full-codegen.cc
src/heap.cc
src/ia32/codegen-ia32.cc
src/ia32/debug-ia32.cc
src/ia32/macro-assembler-ia32.cc
src/ia32/macro-assembler-ia32.h
src/runtime.cc
src/runtime.h
src/x64/codegen-x64.cc
src/x64/debug-x64.cc
src/x64/macro-assembler-x64.cc
test/cctest/test-debug.cc

index e4977bab805aa463f1c0572135d486f5f07f45a1..c9222be7765bb3395090e79561ceb6193ea09456 100644 (file)
@@ -2286,7 +2286,8 @@ void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
   Comment cmnt(masm_, "[ DebuggerStatament");
   CodeForStatementPosition(node);
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  frame_->CallRuntime(Runtime::kDebugBreak, 0);
+  DebugerStatementStub ces;
+  frame_->CallStub(&ces, 0);
 #endif
   // Ignore the return value.
   ASSERT(frame_->height() == original_height);
index fc9808d5295498253ce489bf945698f09b5bb0c0..2a0689fb3bd03c6361d3770b4ada83d675cbc496 100644 (file)
@@ -98,7 +98,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
   __ mov(r0, Operand(0));  // no arguments
   __ mov(r1, Operand(ExternalReference::debug_break()));
 
-  CEntryDebugBreakStub ceb;
+  CEntryStub ceb(1);
   __ CallStub(&ceb);
 
   // Restore the register values containing object pointers from the expression
index 6c3bbbb847af2179a3b42e6b4b89eb3007ccbdbd..09aebf07fd0a6fec36f12a4ef533c666b3c2fe20 100644 (file)
@@ -1035,9 +1035,13 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
     return;
   }
 
-  Runtime::FunctionId function_id =
-      static_cast<Runtime::FunctionId>(f->stub_id);
-  RuntimeStub stub(function_id, num_arguments);
+  // TODO(1236192): Most runtime routines don't need the number of
+  // arguments passed in because it is constant. At some point we
+  // 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);
 }
 
index 052c1cafac3814f7019fecfa505369680f5f9bd7..16267f64e0e6c05f1213817fab5125d86f98b09f 100644 (file)
@@ -55,9 +55,9 @@ namespace internal {
   V(CounterOp)                           \
   V(ArgumentsAccess)                     \
   V(RegExpExec)                          \
-  V(Runtime)                             \
   V(CEntry)                              \
-  V(JSEntry)
+  V(JSEntry)                             \
+  V(DebuggerStatement)
 
 // List of code stubs only used on ARM platforms.
 #ifdef V8_TARGET_ARCH_ARM
index ba88d7318c2bd82a8c3be011fd75416a0d09ee69..90fc6753ad24849579faa788ba2cfcd7b7eba755 100644 (file)
@@ -452,11 +452,6 @@ void CodeGenerator::CodeForSourcePosition(int pos) {
 }
 
 
-const char* RuntimeStub::GetName() {
-  return Runtime::FunctionForId(id_)->stub_name;
-}
-
-
 const char* GenericUnaryOpStub::GetName() {
   switch (op_) {
     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) {
   switch (type_) {
     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
index 76cc4914e7bd028323463611c4a98d8fa02ac010..08b2e11ec148111954598e50dd0454b704713aca 100644 (file)
@@ -181,43 +181,6 @@ class DeferredCode: public ZoneObject {
   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 {
  public:
   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:
-  CEntryDebugBreakStub() : CEntryStub(1) { }
+  DebugerStatementStub() { }
 
-  void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
+  void Generate(MacroAssembler* masm);
 
  private:
-  int MinorKey() { return 1; }
+  Major MajorKey() { return DebuggerStatement; }
+  int MinorKey() { return 0; }
 
-  const char* GetName() { return "CEntryDebugBreakStub"; }
+  const char* GetName() { return "DebugerStatementStub"; }
 };
 
 
index e66c30d5bb2955303a23443cea41ff2c25e6bcda..fb9b23eb5152fd424997e92cc656e6d35a064edf 100644 (file)
@@ -75,9 +75,6 @@ BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
                                              BreakLocatorType type) {
   debug_info_ = debug_info;
   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_original_ = NULL;
   Reset();  // Initialize the rest of the member variables.
@@ -461,9 +458,7 @@ bool BreakLocationIterator::IsDebuggerStatement() {
     Code* code = Code::GetCodeFromTargetAddress(target);
     if (code->kind() == Code::STUB) {
       CodeStub::Major major_key = code->major_key();
-      if (major_key == CodeStub::Runtime) {
-        return (*debug_break_stub_ == code);
-      }
+      return (major_key == CodeStub::DebuggerStatement);
     }
   }
   return false;
index 576be930f984ced1e246831ecb6d5a357ae6789e..cab9e8e447c951265ec3bdb44743abd4c9334484 100644 (file)
@@ -132,7 +132,6 @@ class BreakLocationIterator {
   int position_;
   int statement_position_;
   Handle<DebugInfo> debug_info_;
-  Handle<Code> debug_break_stub_;
   RelocIterator* reloc_iterator_;
   RelocIterator* reloc_iterator_original_;
 
index 524dbe671949ebfe2eeeee17f92d15338f846e24..50f3eb996bbd64eb0c43838aa2e4755e8eb5da94 100644 (file)
@@ -266,13 +266,7 @@ static int DecodeIt(FILE* f,
               case CodeStub::CallFunction:
                 out.AddFormatted("argc = %d", minor_key);
                 break;
-              case CodeStub::Runtime: {
-                const char* name =
-                    RuntimeStub::GetNameFromMinorKey(minor_key);
-                out.AddFormatted("%s", name);
-                break;
-              }
-              default:
+            default:
                 out.AddFormatted("minor: %d", minor_key);
             }
           }
index a14b09fbabf8384694cfa4064760bfc3bd05332b..ca8fb032c47c3c73141aa2a76c3ddedccaf40fa3 100644 (file)
@@ -998,7 +998,9 @@ void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
 #ifdef ENABLE_DEBUGGER_SUPPORT
   Comment cmnt(masm_, "[ DebuggerStatement");
   SetStatementPosition(stmt);
-  __ CallRuntime(Runtime::kDebugBreak, 0);
+
+  DebugerStatementStub ces;
+  __ CallStub(&ces);
   // Ignore the return value.
 #endif
 }
index 8c6039d0579b072256fe56379a9af5bd87d7b18a..c54991ffeb3208c6a4fc8c5d9eb7c1c60cc7327a 100644 (file)
@@ -1499,7 +1499,7 @@ void Heap::CreateRegExpCEntryStub() {
 
 
 void Heap::CreateCEntryDebugBreakStub() {
-  CEntryDebugBreakStub stub;
+  DebugerStatementStub stub;
   set_c_entry_debug_break_code(*stub.GetCode());
 }
 
@@ -1526,7 +1526,7 @@ void Heap::CreateFixedStubs() {
   // {  CEntryStub stub;
   //    c_entry_code_ = *stub.GetCode();
   // }
-  // {  CEntryDebugBreakStub stub;
+  // {  DebugerStatementStub stub;
   //    c_entry_debug_break_code_ = *stub.GetCode();
   // }
   // To workaround the problem, make separate functions without inlining.
index e19067c97979c646255800802b0d44e8296f926a..326d609605f3831ec6cfc50ce094f8447b690390 100644 (file)
@@ -3901,7 +3901,9 @@ void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Spill everything, even constants, to the frame.
   frame_->SpillAll();
-  frame_->CallRuntime(Runtime::kDebugBreak, 0);
+
+  DebugerStatementStub ces;
+  frame_->CallStub(&ces, 0);
   // Ignore the return value.
 #endif
 }
index 5ebe1e070367a2137cb6b4963fa156a6527e0b6b..2f1470fd51632acc779880109f8fe0fd2abd4b44 100644 (file)
@@ -94,7 +94,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
   __ Set(eax, Immediate(0));  // no arguments
   __ mov(ebx, Immediate(ExternalReference::debug_break()));
 
-  CEntryDebugBreakStub ceb;
+  CEntryStub ceb(1);
   __ CallStub(&ceb);
 
   // Restore the register values containing object pointers from the expression
index a16c10337a71d9c3b97f95c58f553edb31c2a0be..74525ea5a6d4d1c0dccae9bd8c91443734be9bd5 100644 (file)
@@ -1098,10 +1098,14 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
     return;
   }
 
-  Runtime::FunctionId function_id =
-      static_cast<Runtime::FunctionId>(f->stub_id);
-  RuntimeStub stub(function_id, num_arguments);
-  CallStub(&stub);
+  // TODO(1236192): Most runtime routines don't need the number of
+  // arguments passed in because it is constant. At some point we
+  // should remove this need and make the runtime routine entry code
+  // 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();
   }
 
-  Runtime::FunctionId function_id =
-      static_cast<Runtime::FunctionId>(f->stub_id);
-  RuntimeStub stub(function_id, num_arguments);
-  return TryCallStub(&stub);
+  // TODO(1236192): Most runtime routines don't need the number of
+  // arguments passed in because it is constant. At some point we
+  // should remove this need and make the runtime routine entry code
+  // smarter.
+  Set(eax, Immediate(num_arguments));
+  mov(ebx, Immediate(ExternalReference(f)));
+  CEntryStub ces(1);
+  return TryCallStub(&ces);
 }
 
 
index 3f000ee411c704b1eb83229f580fc1345e1f9209..cc245602d84e6a491197f73933437ffa5841a388 100644 (file)
@@ -331,7 +331,7 @@ class MacroAssembler: public Assembler {
   // Eventually this should be used for all C calls.
   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
   // but instead return a retry after GC failure.
   Object* TryCallRuntime(Runtime::Function* f, int num_arguments);
index 58ed3b3e321ae991cca1f2056eb4c72a30fa29c2..48147b7d0f47d9028aa4d2f1f83d97a477a4f18e 100644 (file)
@@ -8130,12 +8130,12 @@ static Object* Runtime_IS_VAR(Arguments args) {
 // Implementation of Runtime
 
 #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 Runtime::Function Runtime_functions[] = {
   RUNTIME_FUNCTION_LIST(F)
-  { NULL, NULL, NULL, 0, -1, 0 }
+  { NULL, NULL, 0, -1, 0 }
 };
 
 #undef F
index efef7db81982c97e70daa01ae25dba3ba106a600..b2b8609e7442530f4aa0feabf9af449506324e85 100644 (file)
@@ -373,9 +373,6 @@ class Runtime : public AllStatic {
     // The JS name of the function.
     const char* name;
 
-    // The name of the stub that calls the runtime function.
-    const char* stub_name;
-
     // The C++ (native) entry point.
     byte* entry;
 
index 6f93d2afb255f66896728cf626742c8635d42ac6..8e80ed962751af744701e6d3da3b8485e28bff96 100644 (file)
@@ -2212,7 +2212,9 @@ void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Spill everything, even constants, to the frame.
   frame_->SpillAll();
-  frame_->CallRuntime(Runtime::kDebugBreak, 0);
+
+  DebugerStatementStub ces;
+  frame_->CallStub(&ces, 0);
   // Ignore the return value.
 #endif
 }
@@ -7337,9 +7339,7 @@ int CEntryStub::MinorKey() {
 #ifdef _WIN64
   // Simple results returned in rax (using default code).
   // Complex results must be written to address passed as first argument.
-  // Use even numbers for minor keys, reserving the odd numbers for
-  // CEntryDebugBreakStub.
-  return (result_size_ < 2) ? 0 : result_size_ * 2;
+  return (result_size_ < 2) ? 0 : 1;
 #else
   // Single results returned in rax (both AMD64 and Win64 calling conventions)
   // and a struct of two pointers in rax+rdx (AMD64 calling convention only)
index bc88d4668d7c0b911519396bb5e09c574e7bd24d..b3e1b2e78701e20029c4c878d9faadc13e76b822 100644 (file)
@@ -68,7 +68,7 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
   __ xor_(rax, rax);  // No arguments (argc == 0).
   __ movq(rbx, ExternalReference::debug_break());
 
-  CEntryDebugBreakStub ceb;
+  CEntryStub ceb(1);
   __ CallStub(&ceb);
 
   // Restore the register values containing object pointers from the expression
index bd7bf27267b4aede2cadb5d051055609c14c2f62..b3729f194b2a0e49d1595f58179e0f0764572c36 100644 (file)
@@ -344,10 +344,14 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
     return;
   }
 
-  Runtime::FunctionId function_id =
-      static_cast<Runtime::FunctionId>(f->stub_id);
-  RuntimeStub stub(function_id, num_arguments);
-  CallStub(&stub);
+  // TODO(1236192): Most runtime routines don't need the number of
+  // arguments passed in because it is constant. At some point we
+  // should remove this need and make the runtime routine entry code
+  // smarter.
+  movq(rax, Immediate(num_arguments));
+  movq(rbx, ExternalReference(f));
+  CEntryStub ces(f->result_size);
+  CallStub(&ces);
 }
 
 
index 583a9c2c298553d506d17b1f5910fa234ab73731..92e18e06857d7db356d80436e75163872c81504f 100644 (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
 // the correct results.
 TEST(DebugEvaluate) {