Debugger: use debug break slot to break on call.
authoryangguo <yangguo@chromium.org>
Fri, 10 Jul 2015 08:49:14 +0000 (01:49 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 10 Jul 2015 08:49:31 +0000 (08:49 +0000)
Break point at calls are currently set via IC. To change this, we
need to set debug break slots instead. We also need to distinguish
those debug break slots as calls to support step-in.

To implement this, we add a data field to debug break reloc info to
indicate non-call debug breaks or in case of call debug breaks, the
number of arguments. We can later use this to find the callee on the
evaluation stack in Debug::PrepareStep.

BUG=v8:4269
R=ulan@chromium.org
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#29561}

30 files changed:
src/arm/assembler-arm.h
src/arm/debug-arm.cc
src/arm/full-codegen-arm.cc
src/arm64/assembler-arm64.h
src/arm64/debug-arm64.cc
src/arm64/full-codegen-arm64.cc
src/assembler.cc
src/assembler.h
src/builtins.cc
src/builtins.h
src/code-stubs.h
src/debug.cc
src/debug.h
src/disassembler.cc
src/full-codegen.cc
src/full-codegen.h
src/ia32/assembler-ia32.h
src/ia32/debug-ia32.cc
src/ia32/full-codegen-ia32.cc
src/mips/assembler-mips.h
src/mips/debug-mips.cc
src/mips/full-codegen-mips.cc
src/mips64/assembler-mips64.h
src/mips64/debug-mips64.cc
src/mips64/full-codegen-mips64.cc
src/x64/assembler-x64.h
src/x64/debug-x64.cc
src/x64/full-codegen-x64.cc
test/cctest/test-debug.cc
test/mjsunit/debug-stepin-construct-call.js [new file with mode: 0644]

index 36f3fda6f47daa6920e6cb0a6c5678042bd7cb57..73c109972ed48e7e64a90a691bd6f3c427c4393d 100644 (file)
@@ -1359,6 +1359,8 @@ class Assembler : public AssemblerBase {
 
   // Mark address of a debug break slot.
   void RecordDebugBreakSlot();
+  void RecordDebugBreakSlotForCall(int argc);
+  void RecordDebugBreakSlotForConstructCall();
 
   // Record the AST id of the CallIC being compiled, so that it can be placed
   // in the relocation information.
index 7d9313200b82b8227cbf4679fc0b1b3c9eed6a12..57681b1478651eacdcd770a0fc66906016ce4f98 100644 (file)
@@ -54,8 +54,7 @@ void BreakLocation::SetDebugBreakAtSlot() {
 
 
 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
-                                          RegList object_regs,
-                                          RegList non_object_regs) {
+                                          RegList object_regs) {
   {
     FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
 
@@ -71,21 +70,8 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
     // make sure that these are correctly updated during GC. Non object values
     // are stored as a smi causing it to be untouched by GC.
     DCHECK((object_regs & ~kJSCallerSaved) == 0);
-    DCHECK((non_object_regs & ~kJSCallerSaved) == 0);
-    DCHECK((object_regs & non_object_regs) == 0);
-    if ((object_regs | non_object_regs) != 0) {
-      for (int i = 0; i < kNumJSCallerSaved; i++) {
-        int r = JSCallerSavedCode(i);
-        Register reg = { r };
-        if ((non_object_regs & (1 << r)) != 0) {
-          if (FLAG_debug_code) {
-            __ tst(reg, Operand(0xc0000000));
-            __ Assert(eq, kUnableToEncodeValueAsSmi);
-          }
-          __ SmiTag(reg);
-        }
-      }
-      __ stm(db_w, sp, object_regs | non_object_regs);
+    if (object_regs != 0) {
+      __ stm(db_w, sp, object_regs);
     }
 
 #ifdef DEBUG
@@ -98,18 +84,15 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
     __ CallStub(&ceb);
 
     // Restore the register values from the expression stack.
-    if ((object_regs | non_object_regs) != 0) {
-      __ ldm(ia_w, sp, object_regs | non_object_regs);
-      for (int i = 0; i < kNumJSCallerSaved; i++) {
-        int r = JSCallerSavedCode(i);
-        Register reg = { r };
-        if ((non_object_regs & (1 << r)) != 0) {
-          __ SmiUntag(reg);
-        }
-        if (FLAG_debug_code &&
-            (((object_regs |non_object_regs) & (1 << r)) == 0)) {
-          __ mov(reg, Operand(kDebugZapValue));
-        }
+    if (object_regs != 0) {
+      __ ldm(ia_w, sp, object_regs);
+    }
+
+    for (int i = 0; i < kNumJSCallerSaved; i++) {
+      int r = JSCallerSavedCode(i);
+      Register reg = {r};
+      if (FLAG_debug_code && ((object_regs & (1 << r)) == 0)) {
+        __ mov(reg, Operand(kDebugZapValue));
       }
     }
 
@@ -130,53 +113,11 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
 }
 
 
-void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
-  // Register state for CallICStub
-  // ----------- S t a t e -------------
-  //  -- r1 : function
-  //  -- r3 : slot in feedback array (smi)
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, r1.bit() | r3.bit(), 0);
-}
-
-
 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
   // In places other than IC call sites it is expected that r0 is TOS which
   // is an object - this is not generally the case so this should be used with
   // care.
-  Generate_DebugBreakCallHelper(masm, r0.bit(), 0);
-}
-
-
-void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) {
-  // Register state for CallFunctionStub (from code-stubs-arm.cc).
-  // ----------- S t a t e -------------
-  //  -- r1 : function
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, r1.bit(), 0);
-}
-
-
-void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) {
-  // Calling convention for CallConstructStub (from code-stubs-arm.cc)
-  // ----------- S t a t e -------------
-  //  -- r0     : number of arguments (not smi)
-  //  -- r1     : constructor function
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, r1.bit(), r0.bit());
-}
-
-
-void DebugCodegen::GenerateCallConstructStubRecordDebugBreak(
-    MacroAssembler* masm) {
-  // Calling convention for CallConstructStub (from code-stubs-arm.cc)
-  // ----------- S t a t e -------------
-  //  -- r0     : number of arguments (not smi)
-  //  -- r1     : constructor function
-  //  -- r2     : feedback array
-  //  -- r3     : feedback slot (smi)
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, r1.bit() | r2.bit() | r3.bit(), r0.bit());
+  Generate_DebugBreakCallHelper(masm, r0.bit());
 }
 
 
@@ -186,7 +127,6 @@ void DebugCodegen::GenerateSlot(MacroAssembler* masm) {
   Assembler::BlockConstPoolScope block_const_pool(masm);
   Label check_codesize;
   __ bind(&check_codesize);
-  __ RecordDebugBreakSlot();
   for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
     __ nop(MacroAssembler::DEBUG_BREAK_NOP);
   }
@@ -198,7 +138,7 @@ void DebugCodegen::GenerateSlot(MacroAssembler* masm) {
 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) {
   // In the places where a debug break slot is inserted no registers can contain
   // object pointers.
-  Generate_DebugBreakCallHelper(masm, 0, 0);
+  Generate_DebugBreakCallHelper(masm, 0);
 }
 
 
index e4b7cf34ee461dcfd8574f4e5c0e3d2a467867d8..3dea3bc18b16b07b790135ed02cd314faf4512e7 100644 (file)
@@ -2269,6 +2269,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       CallIC(ic, TypeFeedbackId::None());
       __ mov(r1, r0);
       __ str(r1, MemOperand(sp, 2 * kPointerSize));
+      SetCallPosition(expr, 1);
       CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
       __ CallStub(&stub);
 
@@ -3103,7 +3104,7 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
     VisitForStackValue(args->at(i));
   }
 
-  SetExpressionPosition(expr);
+  SetCallPosition(expr, arg_count);
   Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
   __ mov(r3, Operand(SmiFromSlot(expr->CallFeedbackICSlot())));
   __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
@@ -3238,7 +3239,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
     PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
 
     // Record source position for debugger.
-    SetExpressionPosition(expr);
+    SetCallPosition(expr, arg_count);
     CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
     __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
     __ CallStub(&stub);
@@ -3310,7 +3311,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
 
   // Call the construct call builtin that handles allocation and
   // constructor invocation.
-  SetExpressionPosition(expr);
+  SetConstructCallPosition(expr);
 
   // Load function and argument count into r1 and r0.
   __ mov(r0, Operand(arg_count));
@@ -3353,7 +3354,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
 
   // Call the construct call builtin that handles allocation and
   // constructor invocation.
-  SetExpressionPosition(expr);
+  SetConstructCallPosition(expr);
 
   // Load function and argument count into r1 and r0.
   __ mov(r0, Operand(arg_count));
@@ -4732,7 +4733,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
 
-  SetExpressionPosition(expr);
+  SetCallPosition(expr, arg_count);
   CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
   __ ldr(r1, MemOperand(sp, (arg_count + 1) * kPointerSize));
   __ CallStub(&stub);
index 5fab081d4b41b52ca802c99d3cbf6cb3349048c0..b13d2199a0b94cbf2d87511784e327f54ba9aaca 100644 (file)
@@ -1027,6 +1027,8 @@ class Assembler : public AssemblerBase {
 
   // Mark address of a debug break slot.
   void RecordDebugBreakSlot();
+  void RecordDebugBreakSlotForCall(int argc);
+  void RecordDebugBreakSlotForConstructCall();
 
   // Record the emission of a constant pool.
   //
index 2eec4466e1f7df8e440cd328ab56963281140534..7b24526dc1ed57000b8b58f0e848ea3adfc16001 100644 (file)
@@ -94,9 +94,8 @@ void BreakLocation::SetDebugBreakAtSlot() {
 
 
 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
-                                          RegList object_regs,
-                                          RegList non_object_regs,
-                                          Register scratch) {
+                                          RegList object_regs) {
+  Register scratch = x10;
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
 
@@ -120,30 +119,10 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
     //
     // TODO(jbramley): Why can't this handle callee-saved registers?
     DCHECK((~kCallerSaved.list() & object_regs) == 0);
-    DCHECK((~kCallerSaved.list() & non_object_regs) == 0);
-    DCHECK((object_regs & non_object_regs) == 0);
     DCHECK((scratch.Bit() & object_regs) == 0);
-    DCHECK((scratch.Bit() & non_object_regs) == 0);
-    DCHECK((masm->TmpList()->list() & (object_regs | non_object_regs)) == 0);
+    DCHECK((masm->TmpList()->list() & object_regs) == 0);
     STATIC_ASSERT(kSmiValueSize == 32);
 
-    CPURegList non_object_list =
-        CPURegList(CPURegister::kRegister, kXRegSizeInBits, non_object_regs);
-    while (!non_object_list.IsEmpty()) {
-      // Store each non-object register as two SMIs.
-      Register reg = Register(non_object_list.PopLowestIndex());
-      __ Lsr(scratch, reg, 32);
-      __ SmiTagAndPush(scratch, reg);
-
-      // Stack:
-      //  jssp[12]: reg[63:32]
-      //  jssp[8]: 0x00000000 (SMI tag & padding)
-      //  jssp[4]: reg[31:0]
-      //  jssp[0]: 0x00000000 (SMI tag & padding)
-      STATIC_ASSERT(kSmiTag == 0);
-      STATIC_ASSERT(static_cast<unsigned>(kSmiShift) == kWRegSizeInBits);
-    }
-
     if (object_regs != 0) {
       __ PushXRegList(object_regs);
     }
@@ -162,20 +141,6 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
       __ PopXRegList(object_regs);
     }
 
-    non_object_list =
-        CPURegList(CPURegister::kRegister, kXRegSizeInBits, non_object_regs);
-    while (!non_object_list.IsEmpty()) {
-      // Load each non-object register from two SMIs.
-      // Stack:
-      //  jssp[12]: reg[63:32]
-      //  jssp[8]: 0x00000000 (SMI tag & padding)
-      //  jssp[4]: reg[31:0]
-      //  jssp[0]: 0x00000000 (SMI tag & padding)
-      Register reg = Register(non_object_list.PopHighestIndex());
-      __ Pop(scratch, reg);
-      __ Bfxil(reg, scratch, 32, 32);
-    }
-
     // Don't bother removing padding bytes pushed on the stack
     // as the frame is going to be restored right away.
 
@@ -193,54 +158,11 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
 }
 
 
-void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
-  // Register state for CallICStub
-  // ----------- S t a t e -------------
-  //  -- x1 : function
-  //  -- x3 : slot in feedback array
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, x1.Bit() | x3.Bit(), 0, x10);
-}
-
-
 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
   // In places other than IC call sites it is expected that r0 is TOS which
   // is an object - this is not generally the case so this should be used with
   // care.
-  Generate_DebugBreakCallHelper(masm, x0.Bit(), 0, x10);
-}
-
-
-void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) {
-  // Register state for CallFunctionStub (from code-stubs-arm64.cc).
-  // ----------- S t a t e -------------
-  //  -- x1 : function
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, x1.Bit(), 0, x10);
-}
-
-
-void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) {
-  // Calling convention for CallConstructStub (from code-stubs-arm64.cc).
-  // ----------- S t a t e -------------
-  //  -- x0 : number of arguments (not smi)
-  //  -- x1 : constructor function
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, x1.Bit(), x0.Bit(), x10);
-}
-
-
-void DebugCodegen::GenerateCallConstructStubRecordDebugBreak(
-    MacroAssembler* masm) {
-  // Calling convention for CallConstructStub (from code-stubs-arm64.cc).
-  // ----------- S t a t e -------------
-  //  -- x0 : number of arguments (not smi)
-  //  -- x1 : constructor function
-  //  -- x2     : feedback array
-  //  -- x3     : feedback slot (smi)
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(
-      masm, x1.Bit() | x2.Bit() | x3.Bit(), x0.Bit(), x10);
+  Generate_DebugBreakCallHelper(masm, x0.Bit());
 }
 
 
@@ -249,7 +171,6 @@ void DebugCodegen::GenerateSlot(MacroAssembler* masm) {
   // the constant pool in the debug break slot code.
   InstructionAccurateScope scope(masm, Assembler::kDebugBreakSlotInstructions);
 
-  __ RecordDebugBreakSlot();
   for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
     __ nop(Assembler::DEBUG_BREAK_NOP);
   }
@@ -259,7 +180,7 @@ void DebugCodegen::GenerateSlot(MacroAssembler* masm) {
 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) {
   // In the places where a debug break slot is inserted no registers can contain
   // object pointers.
-  Generate_DebugBreakCallHelper(masm, 0, 0, x10);
+  Generate_DebugBreakCallHelper(masm, 0);
 }
 
 
index 324bfb8160158e3de1875abbd8da9ffb6d89c41c..9896771b5813ea3a5b57749c8db9cba5ca714074 100644 (file)
@@ -2788,10 +2788,11 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
   // Load the arguments.
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
-    for (int i = 0; i < arg_count; i++) {
-      VisitForStackValue(args->at(i));
-    }
-    SetExpressionPosition(expr);
+  for (int i = 0; i < arg_count; i++) {
+    VisitForStackValue(args->at(i));
+  }
+
+  SetCallPosition(expr, arg_count);
 
   Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
   __ Mov(x3, SmiFromSlot(expr->CallFeedbackICSlot()));
@@ -2907,26 +2908,26 @@ void FullCodeGenerator::VisitCall(Call* expr) {
     ZoneList<Expression*>* args = expr->arguments();
     int arg_count = args->length();
 
-      PushCalleeAndWithBaseObject(expr);
+    PushCalleeAndWithBaseObject(expr);
 
-      // Push the arguments.
-      for (int i = 0; i < arg_count; i++) {
-        VisitForStackValue(args->at(i));
-      }
+    // Push the arguments.
+    for (int i = 0; i < arg_count; i++) {
+      VisitForStackValue(args->at(i));
+    }
 
-      // Push a copy of the function (found below the arguments) and
-      // resolve eval.
-      __ Peek(x10, (arg_count + 1) * kPointerSize);
-      __ Push(x10);
-      EmitResolvePossiblyDirectEval(arg_count);
+    // Push a copy of the function (found below the arguments) and
+    // resolve eval.
+    __ Peek(x10, (arg_count + 1) * kPointerSize);
+    __ Push(x10);
+    EmitResolvePossiblyDirectEval(arg_count);
 
-      // Touch up the stack with the resolved function.
-      __ Poke(x0, (arg_count + 1) * kPointerSize);
+    // Touch up the stack with the resolved function.
+    __ Poke(x0, (arg_count + 1) * kPointerSize);
 
-      PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
+    PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
 
     // Record source position for debugger.
-      SetExpressionPosition(expr);
+    SetCallPosition(expr, arg_count);
 
     // Call the evaluated function.
     CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
@@ -3001,7 +3002,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
 
   // Call the construct call builtin that handles allocation and
   // constructor invocation.
-  SetExpressionPosition(expr);
+  SetConstructCallPosition(expr);
 
   // Load function and argument count into x1 and x0.
   __ Mov(x0, arg_count);
@@ -3044,7 +3045,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
 
   // Call the construct call builtin that handles allocation and
   // constructor invocation.
-  SetExpressionPosition(expr);
+  SetConstructCallPosition(expr);
 
   // Load function and argument count into x1 and x0.
   __ Mov(x0, arg_count);
@@ -4424,7 +4425,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
 
-  SetExpressionPosition(expr);
+  SetCallPosition(expr, arg_count);
   CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
   __ Peek(x1, (arg_count + 1) * kPointerSize);
   __ CallStub(&stub);
@@ -5186,6 +5187,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       CallIC(ic, TypeFeedbackId::None());
       __ Mov(x1, x0);
       __ Poke(x1, 2 * kPointerSize);
+      SetCallPosition(expr, 1);
       CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
       __ CallStub(&stub);
 
index e6aaa914bfe308e290f60f79718d3d750d9b005d..d03593f36fef993589c470f2601f3f8f44c13512 100644 (file)
@@ -380,23 +380,27 @@ void RelocInfoWriter::WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag) {
 }
 
 
-void RelocInfoWriter::WriteExtraTaggedIntData(int data_delta, int top_tag) {
-  WriteExtraTag(kDataJumpExtraTag, top_tag);
+void RelocInfoWriter::WriteInt(int number) {
   for (int i = 0; i < kIntSize; i++) {
-    *--pos_ = static_cast<byte>(data_delta);
+    *--pos_ = static_cast<byte>(number);
     // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
-    data_delta = data_delta >> kBitsPerByte;
+    number = number >> kBitsPerByte;
   }
 }
 
 
+void RelocInfoWriter::WriteDebugBreakSlotData(int data) { WriteInt(data); }
+
+
+void RelocInfoWriter::WriteExtraTaggedIntData(int data_delta, int top_tag) {
+  WriteExtraTag(kDataJumpExtraTag, top_tag);
+  WriteInt(data_delta);
+}
+
+
 void RelocInfoWriter::WriteExtraTaggedPoolData(int data, int pool_type) {
   WriteExtraTag(kPoolExtraTag, pool_type);
-  for (int i = 0; i < kIntSize; i++) {
-    *--pos_ = static_cast<byte>(data);
-    // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
-    data = data >> kBitsPerByte;
-  }
+  WriteInt(data);
 }
 
 
@@ -498,10 +502,10 @@ void RelocInfoWriter::Write(const RelocInfo* rinfo) {
     WriteExtraTaggedData(rinfo->data(), kCommentTag);
     DCHECK(begin_pos - pos_ >= RelocInfo::kMinRelocCommentSize);
   } else if (RelocInfo::IsConstPool(rmode) || RelocInfo::IsVeneerPool(rmode)) {
-      WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
-      WriteExtraTaggedPoolData(static_cast<int>(rinfo->data()),
-                               RelocInfo::IsConstPool(rmode) ? kConstPoolTag
-                                                             : kVeneerPoolTag);
+    WriteExtraTaggedPC(pc_delta, kPCJumpExtraTag);
+    WriteExtraTaggedPoolData(
+        static_cast<int>(rinfo->data()),
+        RelocInfo::IsConstPool(rmode) ? kConstPoolTag : kVeneerPoolTag);
   } else {
     DCHECK(rmode > RelocInfo::LAST_COMPACT_ENUM);
     DCHECK(rmode <= RelocInfo::LAST_STANDARD_NONCOMPACT_ENUM);
@@ -513,6 +517,9 @@ void RelocInfoWriter::Write(const RelocInfo* rinfo) {
     // None of these modes need a data component.
     DCHECK(0 <= saved_mode && saved_mode < kPoolExtraTag);
     WriteExtraTaggedPC(pc_delta, saved_mode);
+    if (RelocInfo::IsDebugBreakSlot(rmode)) {
+      WriteDebugBreakSlotData(static_cast<int>(rinfo->data()));
+    }
   }
   last_pc_ = rinfo->pc();
   last_mode_ = rmode;
@@ -557,7 +564,7 @@ void RelocIterator::AdvanceReadId() {
 }
 
 
-void RelocIterator::AdvanceReadPoolData() {
+void RelocIterator::AdvanceReadInt() {
   int x = 0;
   for (int i = 0; i < kIntSize; i++) {
     x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
@@ -566,6 +573,12 @@ void RelocIterator::AdvanceReadPoolData() {
 }
 
 
+void RelocIterator::AdvanceReadPoolData() { AdvanceReadInt(); }
+
+
+void RelocIterator::AdvanceReadDebugBreakSlotData() { AdvanceReadInt(); }
+
+
 void RelocIterator::AdvanceReadPosition() {
   int x = 0;
   for (int i = 0; i < kIntSize; i++) {
@@ -718,8 +731,17 @@ void RelocIterator::next() {
         Advance(kIntSize);
       } else {
         AdvanceReadPC();
-        int rmode = extra_tag + RelocInfo::LAST_COMPACT_ENUM + 1;
-        if (SetMode(static_cast<RelocInfo::Mode>(rmode))) return;
+        RelocInfo::Mode rmode = static_cast<RelocInfo::Mode>(
+            extra_tag + RelocInfo::LAST_COMPACT_ENUM + 1);
+        if (RelocInfo::IsDebugBreakSlot(rmode)) {
+          if (SetMode(rmode)) {
+            AdvanceReadDebugBreakSlotData();
+            return;
+          }
+          Advance(kIntSize);
+        } else if (SetMode(rmode)) {
+          return;
+        }
       }
     }
   }
@@ -883,6 +905,14 @@ void RelocInfo::Print(Isolate* isolate, std::ostream& os) {  // NOLINT
     }
   } else if (IsConstPool(rmode_)) {
     os << " (size " << static_cast<int>(data_) << ")";
+  } else if (IsDebugBreakSlot(rmode_)) {
+    if (DebugBreakIsCall(data_)) {
+      os << " (call with " << DebugBreakCallArgumentsCount(data_) << " args)";
+    } else if (DebugBreakIsConstructCall(data_)) {
+      os << " (construct call)";
+    } else {
+      os << " (slot)";
+    }
   }
 
   os << "\n";
@@ -946,6 +976,20 @@ void RelocInfo::Verify(Isolate* isolate) {
 #endif  // VERIFY_HEAP
 
 
+bool RelocInfo::DebugBreakIsConstructCall(intptr_t data) {
+  return data == static_cast<intptr_t>(kDebugBreakConstructCallSentinel);
+}
+
+
+bool RelocInfo::DebugBreakIsCall(intptr_t data) { return data >= 0; }
+
+
+int RelocInfo::DebugBreakCallArgumentsCount(intptr_t data) {
+  DCHECK(DebugBreakIsCall(data));
+  return static_cast<int>(data);
+}
+
+
 // -----------------------------------------------------------------------------
 // Implementation of ExternalReference
 
@@ -1869,7 +1913,23 @@ void Assembler::RecordJSReturn() {
 
 void Assembler::RecordDebugBreakSlot() {
   EnsureSpace ensure_space(this);
-  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
+  intptr_t data = static_cast<intptr_t>(RelocInfo::kDebugBreakNonCallSentinel);
+  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT, data);
+}
+
+
+void Assembler::RecordDebugBreakSlotForCall(int argc) {
+  EnsureSpace ensure_space(this);
+  intptr_t data = static_cast<intptr_t>(argc);
+  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT, data);
+}
+
+
+void Assembler::RecordDebugBreakSlotForConstructCall() {
+  EnsureSpace ensure_space(this);
+  intptr_t data =
+      static_cast<intptr_t>(RelocInfo::kDebugBreakConstructCallSentinel);
+  RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT, data);
 }
 
 
index fb59ceb7bd1bd22d43d705d9cb8f6082fec4e471..9433692ed6f8d20251364b2ad354ac04cc919c58 100644 (file)
@@ -506,6 +506,10 @@ class RelocInfo {
   // constant pool, otherwise the pointer is embedded in the instruction stream.
   bool IsInConstantPool();
 
+  static bool DebugBreakIsConstructCall(intptr_t data);
+  static bool DebugBreakIsCall(intptr_t data);
+  static int DebugBreakCallArgumentsCount(intptr_t data);
+
   // Read/modify the code target in the branch/call instruction
   // this relocation applies to;
   // can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
@@ -623,6 +627,8 @@ class RelocInfo {
   static const int kDataMask =
       (1 << CODE_TARGET_WITH_ID) | kPositionMask | (1 << COMMENT);
   static const int kApplyMask;  // Modes affected by apply. Depends on arch.
+  static const int kDebugBreakNonCallSentinel = -2;
+  static const int kDebugBreakConstructCallSentinel = -1;
 
  private:
   // On ARM, note that pc_ is the address of the constant pool entry
@@ -690,6 +696,8 @@ class RelocInfoWriter BASE_EMBEDDED {
   inline uint32_t WriteVariableLengthPCJump(uint32_t pc_delta);
   inline void WriteTaggedPC(uint32_t pc_delta, int tag);
   inline void WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag);
+  inline void WriteInt(int number);
+  inline void WriteDebugBreakSlotData(int data);
   inline void WriteExtraTaggedIntData(int data_delta, int top_tag);
   inline void WriteExtraTaggedPoolData(int data, int pool_type);
   inline void WriteExtraTaggedData(intptr_t data_delta, int top_tag);
@@ -750,7 +758,9 @@ class RelocIterator: public Malloced {
   void ReadTaggedPC();
   void AdvanceReadPC();
   void AdvanceReadId();
+  void AdvanceReadInt();
   void AdvanceReadPoolData();
+  void AdvanceReadDebugBreakSlotData();
   void AdvanceReadPosition();
   void AdvanceReadData();
   void AdvanceReadVariableLengthPCJump();
index 869ad2cc00203488e1727fd17d024a71436f7059..69c2871650e87b16abea5b6c8abd3f8522247236 100644 (file)
@@ -1369,32 +1369,11 @@ static void Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler* masm) {
 }
 
 
-static void Generate_CallICStub_DebugBreak(MacroAssembler* masm) {
-  DebugCodegen::GenerateCallICStubDebugBreak(masm);
-}
-
-
 static void Generate_Return_DebugBreak(MacroAssembler* masm) {
   DebugCodegen::GenerateReturnDebugBreak(masm);
 }
 
 
-static void Generate_CallFunctionStub_DebugBreak(MacroAssembler* masm) {
-  DebugCodegen::GenerateCallFunctionStubDebugBreak(masm);
-}
-
-
-static void Generate_CallConstructStub_DebugBreak(MacroAssembler* masm) {
-  DebugCodegen::GenerateCallConstructStubDebugBreak(masm);
-}
-
-
-static void Generate_CallConstructStub_Recording_DebugBreak(
-    MacroAssembler* masm) {
-  DebugCodegen::GenerateCallConstructStubRecordDebugBreak(masm);
-}
-
-
 static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
   DebugCodegen::GenerateSlotDebugBreak(masm);
 }
index e1e202b3f724cabca5529a821d3d6e6fdbec8838..d831b0bfb5eb29894d70ce399d4926ed4f957325 100644 (file)
@@ -143,14 +143,6 @@ enum BuiltinExtraArguments {
 #define BUILTIN_LIST_DEBUG_A(V)                                               \
   V(Return_DebugBreak,                         BUILTIN, DEBUG_STUB,           \
                                                DEBUG_BREAK)                   \
-  V(CallFunctionStub_DebugBreak,               BUILTIN, DEBUG_STUB,           \
-                                               DEBUG_BREAK)                   \
-  V(CallConstructStub_DebugBreak,              BUILTIN, DEBUG_STUB,           \
-                                               DEBUG_BREAK)                   \
-  V(CallConstructStub_Recording_DebugBreak,    BUILTIN, DEBUG_STUB,           \
-                                               DEBUG_BREAK)                   \
-  V(CallICStub_DebugBreak,                     CALL_IC, DEBUG_STUB,           \
-                                               DEBUG_BREAK)                   \
   V(Slot_DebugBreak,                           BUILTIN, DEBUG_STUB,           \
                                                DEBUG_BREAK)                   \
   V(PlainReturn_LiveEdit,                      BUILTIN, DEBUG_STUB,           \
index a798d5e35010e21646886de17de70556188f235f..30624ea4aab18214ab2571eea01ebcb20d2082e9 100644 (file)
@@ -1013,11 +1013,6 @@ class CallICStub: public PlatformCodeStub {
     minor_key_ = state.GetExtraICState();
   }
 
-  static int ExtractArgcFromMinorKey(int minor_key) {
-    CallICState state(static_cast<ExtraICState>(minor_key));
-    return state.arg_count();
-  }
-
   Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
 
   InlineCacheState GetICState() const override { return DEFAULT; }
@@ -1913,10 +1908,6 @@ class CallFunctionStub: public PlatformCodeStub {
     minor_key_ = ArgcBits::encode(argc) | FlagBits::encode(flags);
   }
 
-  static int ExtractArgcFromMinorKey(int minor_key) {
-    return ArgcBits::decode(minor_key);
-  }
-
  private:
   int argc() const { return ArgcBits::decode(minor_key_); }
   int flags() const { return FlagBits::decode(minor_key_); }
index b7bf3e39aa08bc12d88df301247a0c5513a810e6..c3c0dcb667028d21893f713012ff72a414cf4fda 100644 (file)
@@ -117,7 +117,6 @@ void BreakLocation::Iterator::Next() {
       continue;
     }
 
-    // Check for break at return.
     if (RelocInfo::IsJSReturn(rmode())) {
       // Set the positions to the end of the function.
       if (debug_info_->shared()->HasSourceCode()) {
@@ -127,43 +126,21 @@ void BreakLocation::Iterator::Next() {
         position_ = 0;
       }
       statement_position_ = position_;
-      break_index_++;
       break;
     }
 
-    if (RelocInfo::IsCodeTarget(rmode())) {
-      // Check for breakable code target. Look in the original code as setting
-      // break points can cause the code targets in the running (debugged) code
-      // to be of a different kind than in the original code.
-      Address target = original_rinfo()->target_address();
-      Code* code = Code::GetCodeFromTargetAddress(target);
-
-      if (RelocInfo::IsConstructCall(rmode()) || code->is_call_stub()) {
-        break_index_++;
-        break;
-      }
-
-      if (code->kind() == Code::STUB &&
-          CodeStub::GetMajorKey(code) == CodeStub::CallFunction) {
-        break_index_++;
-        break;
-      }
-    }
-
-    // Skip below if we only want locations for calls and returns.
-    if (type_ == CALLS_AND_RETURNS) continue;
-
-    if (RelocInfo::IsDebuggerStatement(rmode())) {
-      break_index_++;
+    if (RelocInfo::IsDebugBreakSlot(rmode()) &&
+        (type_ == ALL_BREAK_LOCATIONS ||
+         RelocInfo::DebugBreakIsCall(rinfo()->data()))) {
       break;
     }
 
-    if (RelocInfo::IsDebugBreakSlot(rmode()) && type_ != CALLS_AND_RETURNS) {
-      // There is always a possible break point at a debug break slot.
-      break_index_++;
+    if (RelocInfo::IsDebuggerStatement(rmode()) &&
+        type_ == ALL_BREAK_LOCATIONS) {
       break;
     }
   }
+  break_index_++;
 }
 
 
@@ -311,9 +288,6 @@ void BreakLocation::SetDebugBreak() {
   } else if (IsDebugBreakSlot()) {
     // Patch the code in the break slot.
     SetDebugBreakAtSlot();
-  } else {
-    // Patch the IC call.
-    SetDebugBreakAtIC();
   }
   DCHECK(IsDebugBreak());
 }
@@ -329,13 +303,6 @@ void BreakLocation::ClearDebugBreak() {
   } else if (IsDebugBreakSlot()) {
     // Restore the code in the break slot.
     RestoreFromOriginal(Assembler::kDebugBreakSlotLength);
-  } else {
-    // Restore the IC call.
-    rinfo().set_target_address(original_rinfo().target_address());
-    // Some ICs store data in the feedback vector. Clear this to ensure we
-    // won't miss future stepping requirements.
-    SharedFunctionInfo* shared = debug_info_->shared();
-    shared->feedback_vector()->ClearICSlots(shared);
   }
   DCHECK(!IsDebugBreak());
 }
@@ -348,13 +315,7 @@ void BreakLocation::RestoreFromOriginal(int length_in_bytes) {
 
 
 bool BreakLocation::IsStepInLocation() const {
-  if (IsConstructCall()) return true;
-  if (RelocInfo::IsCodeTarget(rmode())) {
-    HandleScope scope(debug_info_->GetIsolate());
-    Handle<Code> target_code = CodeTarget();
-    return target_code->is_call_stub();
-  }
-  return false;
+  return IsConstructCall() || IsCall();
 }
 
 
@@ -363,52 +324,8 @@ bool BreakLocation::IsDebugBreak() const {
     return rinfo().IsPatchedReturnSequence();
   } else if (IsDebugBreakSlot()) {
     return rinfo().IsPatchedDebugBreakSlotSequence();
-  } else {
-    return Debug::IsDebugBreak(rinfo().target_address());
-  }
-}
-
-
-// Find the builtin to use for invoking the debug break
-static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) {
-  Isolate* isolate = code->GetIsolate();
-
-  // Find the builtin debug break function matching the calling convention
-  // used by the call site.
-  if (code->is_inline_cache_stub()) {
-    DCHECK(code->kind() == Code::CALL_IC);
-    return isolate->builtins()->CallICStub_DebugBreak();
-  }
-  if (RelocInfo::IsConstructCall(mode)) {
-    if (code->has_function_cache()) {
-      return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
-    } else {
-      return isolate->builtins()->CallConstructStub_DebugBreak();
-    }
-  }
-  if (code->kind() == Code::STUB) {
-    DCHECK(CodeStub::GetMajorKey(*code) == CodeStub::CallFunction);
-    return isolate->builtins()->CallFunctionStub_DebugBreak();
-  }
-
-  UNREACHABLE();
-  return Handle<Code>::null();
-}
-
-
-void BreakLocation::SetDebugBreakAtIC() {
-  // Patch the original code with the current address as the current address
-  // might have changed by the inline caching since the code was copied.
-  original_rinfo().set_target_address(rinfo().target_address());
-
-  if (RelocInfo::IsCodeTarget(rmode_)) {
-    Handle<Code> target_code = CodeTarget();
-
-    // Patch the code to invoke the builtin debug break function matching the
-    // calling convention used by the call site.
-    Handle<Code> debug_break_code = DebugBreakForIC(target_code, rmode_);
-    rinfo().set_target_address(debug_break_code->entry());
   }
+  return false;
 }
 
 
@@ -417,20 +334,6 @@ Handle<Object> BreakLocation::BreakPointObjects() const {
 }
 
 
-Handle<Code> BreakLocation::CodeTarget() const {
-  DCHECK(IsCodeTarget());
-  Address target = rinfo().target_address();
-  return Handle<Code>(Code::GetCodeFromTargetAddress(target));
-}
-
-
-Handle<Code> BreakLocation::OriginalCodeTarget() const {
-  DCHECK(IsCodeTarget());
-  Address target = original_rinfo().target_address();
-  return Handle<Code>(Code::GetCodeFromTargetAddress(target));
-}
-
-
 bool BreakLocation::Iterator::RinfoDone() const {
   DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done());
   return reloc_iterator_.done();
@@ -442,7 +345,7 @@ void BreakLocation::Iterator::RinfoNext() {
   reloc_iterator_original_.next();
 #ifdef DEBUG
   DCHECK(reloc_iterator_.done() == reloc_iterator_original_.done());
-  DCHECK(reloc_iterator_.done() || rmode() == original_rmode());
+  DCHECK(reloc_iterator_.done() || rmode() == original_rinfo()->rmode());
 #endif
 }
 
@@ -941,7 +844,7 @@ bool Debug::SetBreakPoint(Handle<JSFunction> function,
 
   // Find the break point and change it.
   BreakLocation location = BreakLocation::FromPosition(
-      debug_info, SOURCE_BREAK_LOCATIONS, *source_position, STATEMENT_ALIGNED);
+      debug_info, ALL_BREAK_LOCATIONS, *source_position, STATEMENT_ALIGNED);
   *source_position = location.statement_position();
   location.SetBreakPoint(break_point_object);
 
@@ -985,7 +888,7 @@ bool Debug::SetBreakPointForScript(Handle<Script> script,
 
   // Find the break point and change it.
   BreakLocation location = BreakLocation::FromPosition(
-      debug_info, SOURCE_BREAK_LOCATIONS, position, alignment);
+      debug_info, ALL_BREAK_LOCATIONS, position, alignment);
   location.SetBreakPoint(break_point_object);
 
   position = (alignment == STATEMENT_ALIGNED) ? location.statement_position()
@@ -1017,7 +920,7 @@ void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
                    break_point_info->code_position()->value();
 
       BreakLocation location =
-          BreakLocation::FromAddress(debug_info, SOURCE_BREAK_LOCATIONS, pc);
+          BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, pc);
       location.ClearBreakPoint(break_point_object);
 
       // If there are no more break points left remove the debug info for this
@@ -1238,27 +1141,7 @@ void Debug::PrepareStep(StepAction step_action,
   BreakLocation location =
       BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc);
 
-  if (thread_local_.restarter_frame_function_pointer_ == NULL) {
-    if (location.IsCodeTarget()) {
-      Handle<Code> target_code = location.CodeTarget();
-
-      // Check if target code is CallFunction stub.
-      Handle<Code> maybe_call_function_stub = target_code;
-      // If there is a breakpoint at this line look at the original code to
-      // check if it is a CallFunction stub.
-      if (location.IsDebugBreak()) {
-        maybe_call_function_stub = location.OriginalCodeTarget();
-      }
-      if ((maybe_call_function_stub->kind() == Code::STUB &&
-           CodeStub::GetMajorKey(*maybe_call_function_stub) ==
-               CodeStub::CallFunction) ||
-          maybe_call_function_stub->is_call_stub()) {
-        // Save reference to the code as we may need it to find out arguments
-        // count for 'step in' later.
-        call_function_stub = maybe_call_function_stub;
-      }
-    }
-  } else {
+  if (thread_local_.restarter_frame_function_pointer_ != NULL) {
     is_at_restarted_function = true;
   }
 
@@ -1297,24 +1180,7 @@ void Debug::PrepareStep(StepAction step_action,
       Handle<JSFunction> restarted_function(
           JSFunction::cast(*thread_local_.restarter_frame_function_pointer_));
       FloodWithOneShot(restarted_function);
-    } else if (!call_function_stub.is_null()) {
-      // If it's CallFunction stub ensure target function is compiled and flood
-      // it with one shot breakpoints.
-      bool is_call_ic = call_function_stub->kind() == Code::CALL_IC;
-
-      // Find out number of arguments from the stub minor key.
-      uint32_t key = call_function_stub->stub_key();
-      // Argc in the stub is the number of arguments passed - not the
-      // expected arguments of the called function.
-      int call_function_arg_count = is_call_ic
-          ? CallICStub::ExtractArgcFromMinorKey(CodeStub::MinorKeyFromKey(key))
-          : CallFunctionStub::ExtractArgcFromMinorKey(
-              CodeStub::MinorKeyFromKey(key));
-
-      DCHECK(is_call_ic ||
-             CodeStub::GetMajorKey(*call_function_stub) ==
-                 CodeStub::MajorKeyFromKey(key));
-
+    } else if (location.IsCall()) {
       // Find target function on the expression stack.
       // Expression stack looks like this (top to bottom):
       // argN
@@ -1322,10 +1188,10 @@ void Debug::PrepareStep(StepAction step_action,
       // arg0
       // Receiver
       // Function to call
-      int expressions_count = frame->ComputeExpressionsCount();
-      DCHECK(expressions_count - 2 - call_function_arg_count >= 0);
-      Object* fun = frame->GetExpression(
-          expressions_count - 2 - call_function_arg_count);
+      int num_expressions_without_args =
+          frame->ComputeExpressionsCount() - location.CallArgumentsCount();
+      DCHECK(num_expressions_without_args >= 2);
+      Object* fun = frame->GetExpression(num_expressions_without_args - 2);
 
       // Flood the actual target of call/apply.
       if (fun->IsJSFunction()) {
@@ -1338,10 +1204,9 @@ void Debug::PrepareStep(StepAction step_action,
         while (fun->IsJSFunction()) {
           Code* code = JSFunction::cast(fun)->shared()->code();
           if (code != apply && code != call) break;
-          DCHECK(expressions_count - i - call_function_arg_count >= 0);
-          fun = frame->GetExpression(expressions_count - i -
-                                     call_function_arg_count);
-          i -= 1;
+          DCHECK(num_expressions_without_args >= i);
+          fun = frame->GetExpression(num_expressions_without_args - i);
+          i--;
         }
       }
 
@@ -2209,27 +2074,6 @@ void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
 
     // Continue just after the slot.
     after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
-  } else {
-    addr = Assembler::target_address_from_return_address(frame->pc());
-    if (IsDebugBreak(Assembler::target_address_at(addr, *code))) {
-      // We now know that there is still a debug break call at the target
-      // address, so the break point is still there and the original code will
-      // hold the address to jump to in order to complete the call which is
-      // replaced by a call to DebugBreakXXX.
-
-      // Find the corresponding address in the original code.
-      addr += original_code->instruction_start() - code->instruction_start();
-
-      // Install jump to the call address in the original code. This will be the
-      // call which was overwritten by the call to DebugBreakXXX.
-      after_break_target_ = Assembler::target_address_at(addr, *original_code);
-    } else {
-      // There is no longer a break point present. Don't try to look in the
-      // original code as the running code will have the right address. This
-      // takes care of the case where the last break point is removed from the
-      // function and therefore no "original code" is available.
-      after_break_target_ = Assembler::target_address_at(addr, *code);
-    }
   }
 }
 
index 0eef0bc9a37d8179d52c3b9c48e7d3f93d5a287c..d7470d12352e398681763ceadfc4b23b0d1461b4 100644 (file)
@@ -51,11 +51,7 @@ enum ExceptionBreakType {
 
 
 // Type of exception break.
-enum BreakLocatorType {
-  ALL_BREAK_LOCATIONS = 0,
-  SOURCE_BREAK_LOCATIONS = 1,
-  CALLS_AND_RETURNS = 2
-};
+enum BreakLocatorType { ALL_BREAK_LOCATIONS, CALLS_AND_RETURNS };
 
 
 // The different types of breakpoint position alignments.
@@ -83,13 +79,16 @@ class BreakLocation {
 
   bool IsDebugBreak() const;
   inline bool IsExit() const { return RelocInfo::IsJSReturn(rmode_); }
+  inline bool IsCall() const {
+    return IsDebugBreakSlot() && RelocInfo::DebugBreakIsCall(data_);
+  }
   inline bool IsConstructCall() const {
-    return RelocInfo::IsConstructCall(rmode_);
+    return IsDebugBreakSlot() && RelocInfo::DebugBreakIsConstructCall(data_);
+  }
+  inline int CallArgumentsCount() const {
+    DCHECK(IsCall());
+    return RelocInfo::DebugBreakCallArgumentsCount(data_);
   }
-  inline bool IsCodeTarget() const { return RelocInfo::IsCodeTarget(rmode_); }
-
-  Handle<Code> CodeTarget() const;
-  Handle<Code> OriginalCodeTarget() const;
 
   bool IsStepInLocation() const;
   inline bool HasBreakPoint() const {
@@ -104,28 +103,22 @@ class BreakLocation {
   void SetOneShot();
   void ClearOneShot();
 
+
   inline RelocInfo rinfo() const {
     return RelocInfo(pc(), rmode(), data_, code());
   }
 
-  inline RelocInfo original_rinfo() const {
-    return RelocInfo(original_pc(), original_rmode(), original_data_,
-                     original_code());
-  }
-
   inline int position() const { return position_; }
   inline int statement_position() const { return statement_position_; }
 
   inline Address pc() const { return code()->entry() + pc_offset_; }
   inline Address original_pc() const {
-    return original_code()->entry() + original_pc_offset_;
+    return debug_info_->original_code()->entry() + original_pc_offset_;
   }
 
   inline RelocInfo::Mode rmode() const { return rmode_; }
-  inline RelocInfo::Mode original_rmode() const { return original_rmode_; }
 
   inline Code* code() const { return debug_info_->code(); }
-  inline Code* original_code() const { return debug_info_->original_code(); }
 
  private:
   BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo,
@@ -149,20 +142,13 @@ class BreakLocation {
     }
 
     inline RelocInfo::Mode rmode() { return reloc_iterator_.rinfo()->rmode(); }
-    inline RelocInfo::Mode original_rmode() {
-      return reloc_iterator_.rinfo()->rmode();
-    }
-
     inline RelocInfo* rinfo() { return reloc_iterator_.rinfo(); }
     inline RelocInfo* original_rinfo() {
       return reloc_iterator_original_.rinfo();
     }
 
     inline Address pc() { return rinfo()->pc(); }
-    inline Address original_pc() { return original_rinfo()->pc(); }
-
     int break_index() const { return break_index_; }
-
     inline int position() const { return position_; }
     inline int statement_position() const { return statement_position_; }
 
@@ -194,7 +180,6 @@ class BreakLocation {
   void SetDebugBreak();
   void SetDebugBreakAtReturn();
   void SetDebugBreakAtSlot();
-  void SetDebugBreakAtIC();
 
   inline bool IsDebuggerStatement() const {
     return RelocInfo::IsDebuggerStatement(rmode_);
@@ -807,16 +792,7 @@ class SuppressDebug BASE_EMBEDDED {
 class DebugCodegen : public AllStatic {
  public:
   static void GenerateSlot(MacroAssembler* masm);
-  static void GenerateCallICStubDebugBreak(MacroAssembler* masm);
-  static void GenerateLoadICDebugBreak(MacroAssembler* masm);
-  static void GenerateStoreICDebugBreak(MacroAssembler* masm);
-  static void GenerateKeyedLoadICDebugBreak(MacroAssembler* masm);
-  static void GenerateKeyedStoreICDebugBreak(MacroAssembler* masm);
-  static void GenerateCompareNilICDebugBreak(MacroAssembler* masm);
   static void GenerateReturnDebugBreak(MacroAssembler* masm);
-  static void GenerateCallFunctionStubDebugBreak(MacroAssembler* masm);
-  static void GenerateCallConstructStubDebugBreak(MacroAssembler* masm);
-  static void GenerateCallConstructStubRecordDebugBreak(MacroAssembler* masm);
   static void GenerateSlotDebugBreak(MacroAssembler* masm);
   static void GeneratePlainReturnLiveEdit(MacroAssembler* masm);
 
index 47e506d1127ef03adc42f26ceb647ced2061c4a2..06eb2397eb8d0ecf6278634f5448206c854055a2 100644 (file)
@@ -216,15 +216,7 @@ static int DecodeIt(Isolate* isolate, std::ostream* os,
           DCHECK(major_key == CodeStub::MajorKeyFromKey(key));
           out.AddFormatted(" %s, %s, ", Code::Kind2String(kind),
                            CodeStub::MajorName(major_key, false));
-          switch (major_key) {
-            case CodeStub::CallFunction: {
-              int argc = CallFunctionStub::ExtractArgcFromMinorKey(minor_key);
-              out.AddFormatted("argc = %d", argc);
-              break;
-            }
-            default:
-              out.AddFormatted("minor: %d", minor_key);
-          }
+          out.AddFormatted("minor: %d", minor_key);
         } else {
           out.AddFormatted(" %s", Code::Kind2String(kind));
         }
index 8ca40ccacd568033cee8b9cafd8a56a055ed0485..5cc4881549144433b40794db177012d084a32c7b 100644 (file)
@@ -433,6 +433,7 @@ void FullCodeGenerator::SetStatementPosition(
   bool recorded = RecordStatementPosition(masm_, stmt->position());
   if (recorded && insert_break == INSERT_BREAK && info_->is_debug() &&
       !stmt->IsDebuggerStatement()) {
+    masm_->RecordDebugBreakSlot();
     DebugCodegen::GenerateSlot(masm_);
   }
 }
@@ -443,6 +444,7 @@ void FullCodeGenerator::SetExpressionPosition(
   if (expr->position() == RelocInfo::kNoPosition) return;
   bool recorded = RecordPosition(masm_, expr->position());
   if (recorded && insert_break == INSERT_BREAK && info_->is_debug()) {
+    masm_->RecordDebugBreakSlot();
     DebugCodegen::GenerateSlot(masm_);
   }
 }
@@ -451,7 +453,32 @@ void FullCodeGenerator::SetExpressionPosition(
 void FullCodeGenerator::SetExpressionAsStatementPosition(Expression* expr) {
   if (expr->position() == RelocInfo::kNoPosition) return;
   bool recorded = RecordStatementPosition(masm_, expr->position());
-  if (recorded && info_->is_debug()) DebugCodegen::GenerateSlot(masm_);
+  if (recorded && info_->is_debug()) {
+    masm_->RecordDebugBreakSlot();
+    DebugCodegen::GenerateSlot(masm_);
+  }
+}
+
+
+void FullCodeGenerator::SetCallPosition(Expression* expr, int argc) {
+  if (expr->position() == RelocInfo::kNoPosition) return;
+  RecordPosition(masm_, expr->position());
+  if (info_->is_debug()) {
+    // Always emit a debug break slot before a call.
+    masm_->RecordDebugBreakSlotForCall(argc);
+    DebugCodegen::GenerateSlot(masm_);
+  }
+}
+
+
+void FullCodeGenerator::SetConstructCallPosition(Expression* expr) {
+  if (expr->position() == RelocInfo::kNoPosition) return;
+  RecordPosition(masm_, expr->position());
+  if (info_->is_debug()) {
+    // Always emit a debug break slot before a construct call.
+    masm_->RecordDebugBreakSlotForConstructCall();
+    DebugCodegen::GenerateSlot(masm_);
+  }
 }
 
 
index b4294f585606625b12804a918d3df9a1f0fcc61f..e5cc3e84936966a457413c839a7bda16b8506274 100644 (file)
@@ -676,6 +676,10 @@ class FullCodeGenerator: public AstVisitor {
   // This is used in loop headers where we want to break for each iteration.
   void SetExpressionAsStatementPosition(Expression* expr);
 
+  void SetCallPosition(Expression* expr, int argc);
+
+  void SetConstructCallPosition(Expression* expr);
+
   // Non-local control flow support.
   void EnterTryBlock(int handler_index, Label* handler);
   void ExitTryBlock(int handler_index);
index e77ef28ce738ec45bbf25f9759df463ee2b63cca..31a9dfdb14c1bc8d45b4e72b826564df817ac90b 100644 (file)
@@ -1438,6 +1438,8 @@ class Assembler : public AssemblerBase {
 
   // Mark address of a debug break slot.
   void RecordDebugBreakSlot();
+  void RecordDebugBreakSlotForCall(int argc);
+  void RecordDebugBreakSlotForConstructCall();
 
   // Record a comment relocation entry that can be used by a disassembler.
   // Use --code-comments to enable.
index 5666cf4d22f88befd406b3fa67c7cd02a86bbff2..651c32b4444b16363eca559d59752e70d63507e0 100644 (file)
@@ -71,9 +71,7 @@ void BreakLocation::SetDebugBreakAtSlot() {
 #define __ ACCESS_MASM(masm)
 
 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
-                                          RegList object_regs,
-                                          RegList non_object_regs,
-                                          bool convert_call_to_jmp) {
+                                          RegList object_regs) {
   // Enter an internal frame.
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
@@ -88,22 +86,12 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
     // make sure that these are correctly updated during GC. Non object values
     // are stored as a smi causing it to be untouched by GC.
     DCHECK((object_regs & ~kJSCallerSaved) == 0);
-    DCHECK((non_object_regs & ~kJSCallerSaved) == 0);
-    DCHECK((object_regs & non_object_regs) == 0);
     for (int i = 0; i < kNumJSCallerSaved; i++) {
       int r = JSCallerSavedCode(i);
       Register reg = { r };
       if ((object_regs & (1 << r)) != 0) {
         __ push(reg);
       }
-      if ((non_object_regs & (1 << r)) != 0) {
-        if (FLAG_debug_code) {
-          __ test(reg, Immediate(0xc0000000));
-          __ Assert(zero, kUnableToEncodeValueAsSmi);
-        }
-        __ SmiTag(reg);
-        __ push(reg);
-      }
     }
 
 #ifdef DEBUG
@@ -132,11 +120,6 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
         __ pop(reg);
         taken = true;
       }
-      if ((non_object_regs & (1 << r)) != 0) {
-        __ pop(reg);
-        __ SmiUntag(reg);
-        taken = true;
-      }
       if (!taken) {
         unused_reg = reg;
       }
@@ -153,11 +136,9 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
     // Get rid of the internal frame.
   }
 
-  // If this call did not replace a call but patched other code then there will
-  // be an unwanted return address left on the stack. Here we get rid of that.
-  if (convert_call_to_jmp) {
-    __ add(esp, Immediate(kPointerSize));
-  }
+  // This call did not replace a call , so there will be an unwanted
+  // return address left on the stack. Here we get rid of that.
+  __ add(esp, Immediate(kPointerSize));
 
   // Now that the break point has been handled, resume normal execution by
   // jumping to the target address intended by the caller and that was
@@ -168,62 +149,12 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
 }
 
 
-void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
-  // Register state for CallICStub
-  // ----------- S t a t e -------------
-  //  -- edx    : type feedback slot (smi)
-  //  -- edi    : function
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, edx.bit() | edi.bit(),
-                                0, false);
-}
-
-
 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
   // Register state just before return from JS function (from codegen-ia32.cc).
   // ----------- S t a t e -------------
   //  -- eax: return value
   // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, eax.bit(), 0, true);
-}
-
-
-void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) {
-  // Register state for CallFunctionStub (from code-stubs-ia32.cc).
-  // ----------- S t a t e -------------
-  //  -- edi: function
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, edi.bit(), 0, false);
-}
-
-
-void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) {
-  // Register state for CallConstructStub (from code-stubs-ia32.cc).
-  // eax is the actual number of arguments not encoded as a smi see comment
-  // above IC call.
-  // ----------- S t a t e -------------
-  //  -- eax: number of arguments (not smi)
-  //  -- edi: constructor function
-  // -----------------------------------
-  // The number of arguments in eax is not smi encoded.
-  Generate_DebugBreakCallHelper(masm, edi.bit(), eax.bit(), false);
-}
-
-
-void DebugCodegen::GenerateCallConstructStubRecordDebugBreak(
-    MacroAssembler* masm) {
-  // Register state for CallConstructStub (from code-stubs-ia32.cc).
-  // eax is the actual number of arguments not encoded as a smi see comment
-  // above IC call.
-  // ----------- S t a t e -------------
-  //  -- eax: number of arguments (not smi)
-  //  -- ebx: feedback array
-  //  -- edx: feedback slot (smi)
-  //  -- edi: constructor function
-  // -----------------------------------
-  // The number of arguments in eax is not smi encoded.
-  Generate_DebugBreakCallHelper(masm, ebx.bit() | edx.bit() | edi.bit(),
-                                eax.bit(), false);
+  Generate_DebugBreakCallHelper(masm, eax.bit());
 }
 
 
@@ -231,7 +162,6 @@ void DebugCodegen::GenerateSlot(MacroAssembler* masm) {
   // Generate enough nop's to make space for a call instruction.
   Label check_codesize;
   __ bind(&check_codesize);
-  __ RecordDebugBreakSlot();
   __ Nop(Assembler::kDebugBreakSlotLength);
   DCHECK_EQ(Assembler::kDebugBreakSlotLength,
             masm->SizeOfCodeGeneratedSince(&check_codesize));
@@ -239,7 +169,7 @@ void DebugCodegen::GenerateSlot(MacroAssembler* masm) {
 
 
 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) {
-  Generate_DebugBreakCallHelper(masm, 0, 0, true);
+  Generate_DebugBreakCallHelper(masm, 0);
 }
 
 
index 535f2c2c63e7b68d50307d7465f4bda6cae68708..6bd74016ec4c6d7834b75de607b9b049bab08ef5 100644 (file)
@@ -2194,6 +2194,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       CallIC(ic, TypeFeedbackId::None());
       __ mov(edi, eax);
       __ mov(Operand(esp, 2 * kPointerSize), edi);
+      SetCallPosition(expr, 1);
       CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
       __ CallStub(&stub);
 
@@ -2995,7 +2996,7 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
     VisitForStackValue(args->at(i));
   }
 
-  SetExpressionPosition(expr);
+  SetCallPosition(expr, arg_count);
   Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
   __ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot())));
   __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
@@ -3126,7 +3127,7 @@ void FullCodeGenerator::VisitCall(Call* expr) {
 
     PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
 
-    SetExpressionPosition(expr);
+    SetCallPosition(expr, arg_count);
     CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
     __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
     __ CallStub(&stub);
@@ -3197,7 +3198,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
 
   // Call the construct call builtin that handles allocation and
   // constructor invocation.
-  SetExpressionPosition(expr);
+  SetConstructCallPosition(expr);
 
   // Load function and argument count into edi and eax.
   __ Move(eax, Immediate(arg_count));
@@ -3240,7 +3241,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
 
   // Call the construct call builtin that handles allocation and
   // constructor invocation.
-  SetExpressionPosition(expr);
+  SetConstructCallPosition(expr);
 
   // Load function and argument count into edi and eax.
   __ Move(eax, Immediate(arg_count));
@@ -4663,7 +4664,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
 
-  SetExpressionPosition(expr);
+  SetCallPosition(expr, arg_count);
   CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
   __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
   __ CallStub(&stub);
index 1f642dec07dbc105048efd84809933f2173bf358..386946dc0cd29caf8c05e18a9a55ff1a1ce96940 100644 (file)
@@ -1063,6 +1063,8 @@ class Assembler : public AssemblerBase {
 
   // Mark address of a debug break slot.
   void RecordDebugBreakSlot();
+  void RecordDebugBreakSlotForCall(int argc);
+  void RecordDebugBreakSlotForConstructCall();
 
   // Record the AST id of the CallIC being compiled, so that it can be placed
   // in the relocation information.
index 896309a36e3201f168320691a1a237e2b588d4d7..2c7c23591a95730963faf99bf72cad65c675c339 100644 (file)
@@ -60,10 +60,8 @@ void BreakLocation::SetDebugBreakAtSlot() {
 #define __ ACCESS_MASM(masm)
 
 
-
 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
-                                          RegList object_regs,
-                                          RegList non_object_regs) {
+                                          RegList object_regs) {
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
 
@@ -81,21 +79,8 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
     // make sure that these are correctly updated during GC. Non object values
     // are stored as a smi causing it to be untouched by GC.
     DCHECK((object_regs & ~kJSCallerSaved) == 0);
-    DCHECK((non_object_regs & ~kJSCallerSaved) == 0);
-    DCHECK((object_regs & non_object_regs) == 0);
-    if ((object_regs | non_object_regs) != 0) {
-      for (int i = 0; i < kNumJSCallerSaved; i++) {
-        int r = JSCallerSavedCode(i);
-        Register reg = { r };
-        if ((non_object_regs & (1 << r)) != 0) {
-          if (FLAG_debug_code) {
-            __ And(at, reg, 0xc0000000);
-            __ Assert(eq, kUnableToEncodeValueAsSmi, at, Operand(zero_reg));
-          }
-          __ sll(reg, reg, kSmiTagSize);
-        }
-      }
-      __ MultiPush(object_regs | non_object_regs);
+    if (object_regs != 0) {
+      __ MultiPush(object_regs);
     }
 
 #ifdef DEBUG
@@ -108,18 +93,14 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
     __ CallStub(&ceb);
 
     // Restore the register values from the expression stack.
-    if ((object_regs | non_object_regs) != 0) {
-      __ MultiPop(object_regs | non_object_regs);
-      for (int i = 0; i < kNumJSCallerSaved; i++) {
-        int r = JSCallerSavedCode(i);
-        Register reg = { r };
-        if ((non_object_regs & (1 << r)) != 0) {
-          __ srl(reg, reg, kSmiTagSize);
-        }
-        if (FLAG_debug_code &&
-            (((object_regs |non_object_regs) & (1 << r)) == 0)) {
-          __ li(reg, kDebugZapValue);
-        }
+    if (object_regs != 0) {
+      __ MultiPop(object_regs);
+    }
+    for (int i = 0; i < kNumJSCallerSaved; i++) {
+      int r = JSCallerSavedCode(i);
+      Register reg = {r};
+      if (FLAG_debug_code && ((object_regs & (1 << r)) == 0)) {
+        __ li(reg, kDebugZapValue);
       }
     }
 
@@ -140,53 +121,11 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
 }
 
 
-void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
-  // Register state for CallICStub
-  // ----------- S t a t e -------------
-  //  -- a1 : function
-  //  -- a3 : slot in feedback array (smi)
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, a1.bit() | a3.bit(), 0);
-}
-
-
 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
   // In places other than IC call sites it is expected that v0 is TOS which
   // is an object - this is not generally the case so this should be used with
   // care.
-  Generate_DebugBreakCallHelper(masm, v0.bit(), 0);
-}
-
-
-void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) {
-  // Register state for CallFunctionStub (from code-stubs-mips.cc).
-  // ----------- S t a t e -------------
-  //  -- a1 : function
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, a1.bit(), 0);
-}
-
-
-void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) {
-  // Calling convention for CallConstructStub (from code-stubs-mips.cc).
-  // ----------- S t a t e -------------
-  //  -- a0     : number of arguments (not smi)
-  //  -- a1     : constructor function
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, a1.bit() , a0.bit());
-}
-
-
-void DebugCodegen::GenerateCallConstructStubRecordDebugBreak(
-    MacroAssembler* masm) {
-  // Calling convention for CallConstructStub (from code-stubs-mips.cc).
-  // ----------- S t a t e -------------
-  //  -- a0     : number of arguments (not smi)
-  //  -- a1     : constructor function
-  //  -- a2     : feedback array
-  //  -- a3     : feedback slot (smi)
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, a1.bit() | a2.bit() | a3.bit(), a0.bit());
+  Generate_DebugBreakCallHelper(masm, v0.bit());
 }
 
 
@@ -196,7 +135,6 @@ void DebugCodegen::GenerateSlot(MacroAssembler* masm) {
   Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm);
   Label check_codesize;
   __ bind(&check_codesize);
-  __ RecordDebugBreakSlot();
   for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
     __ nop(MacroAssembler::DEBUG_BREAK_NOP);
   }
@@ -208,7 +146,7 @@ void DebugCodegen::GenerateSlot(MacroAssembler* masm) {
 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) {
   // In the places where a debug break slot is inserted no registers can contain
   // object pointers.
-  Generate_DebugBreakCallHelper(masm, 0, 0);
+  Generate_DebugBreakCallHelper(masm, 0);
 }
 
 
index 841ee4b99586bfae8736407212c72db69e2e0622..978c0799f59d19c9bf0e495ec7a22c7e67f391b0 100644 (file)
@@ -2266,6 +2266,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       __ mov(a0, v0);
       __ mov(a1, a0);
       __ sw(a1, MemOperand(sp, 2 * kPointerSize));
+      SetCallPosition(expr, 1);
       CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
       __ CallStub(&stub);
 
@@ -3089,7 +3090,7 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
   }
 
   // Record source position of the IC call.
-  SetExpressionPosition(expr);
+  SetCallPosition(expr, arg_count);
   Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
   __ li(a3, Operand(SmiFromSlot(expr->CallFeedbackICSlot())));
   __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
@@ -3205,25 +3206,25 @@ void FullCodeGenerator::VisitCall(Call* expr) {
     // function using the given arguments.
     ZoneList<Expression*>* args = expr->arguments();
     int arg_count = args->length();
-      PushCalleeAndWithBaseObject(expr);
+    PushCalleeAndWithBaseObject(expr);
 
-      // Push the arguments.
-      for (int i = 0; i < arg_count; i++) {
-        VisitForStackValue(args->at(i));
-      }
+    // Push the arguments.
+    for (int i = 0; i < arg_count; i++) {
+      VisitForStackValue(args->at(i));
+    }
 
-      // Push a copy of the function (found below the arguments) and
-      // resolve eval.
-      __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
-      __ push(a1);
-      EmitResolvePossiblyDirectEval(arg_count);
+    // Push a copy of the function (found below the arguments) and
+    // resolve eval.
+    __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
+    __ push(a1);
+    EmitResolvePossiblyDirectEval(arg_count);
 
-      // Touch up the stack with the resolved function.
-      __ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
+    // Touch up the stack with the resolved function.
+    __ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
 
-      PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
+    PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
     // Record source position for debugger.
-      SetExpressionPosition(expr);
+    SetCallPosition(expr, arg_count);
     CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
     __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
     __ CallStub(&stub);
@@ -3294,7 +3295,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
 
   // Call the construct call builtin that handles allocation and
   // constructor invocation.
-  SetExpressionPosition(expr);
+  SetConstructCallPosition(expr);
 
   // Load function and argument count into a1 and a0.
   __ li(a0, Operand(arg_count));
@@ -3337,7 +3338,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
 
   // Call the construct call builtin that handles allocation and
   // constructor invocation.
-  SetExpressionPosition(expr);
+  SetConstructCallPosition(expr);
 
   // Load function and argument count into a1 and a0.
   __ li(a0, Operand(arg_count));
@@ -4751,7 +4752,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
 
-  SetExpressionPosition(expr);
+  SetCallPosition(expr, arg_count);
   CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
   __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
   __ CallStub(&stub);
index a83661c087dac4a6d8fe6c46077accda506ffe1d..9f0a9bb8e719f3ecd107a2305cf418aaa7f3cb18 100644 (file)
@@ -1105,6 +1105,8 @@ class Assembler : public AssemblerBase {
 
   // Mark address of a debug break slot.
   void RecordDebugBreakSlot();
+  void RecordDebugBreakSlotForCall(int argc);
+  void RecordDebugBreakSlotForConstructCall();
 
   // Record the AST id of the CallIC being compiled, so that it can be placed
   // in the relocation information.
index 75e37c5e779f97e066553ae881bd07fa5ea46559..2762e0beb5e7f837a90f68e0bc4ec3ded8c9a7d0 100644 (file)
@@ -63,10 +63,8 @@ void BreakLocation::SetDebugBreakAtSlot() {
 #define __ ACCESS_MASM(masm)
 
 
-
 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
-                                          RegList object_regs,
-                                          RegList non_object_regs) {
+                                          RegList object_regs) {
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
 
@@ -88,17 +86,12 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
     // make sure that these are correctly updated during GC. Non object values
     // are stored as a smi causing it to be untouched by GC.
     DCHECK((object_regs & ~kJSCallerSaved) == 0);
-    DCHECK((non_object_regs & ~kJSCallerSaved) == 0);
-    DCHECK((object_regs & non_object_regs) == 0);
     for (int i = 0; i < kNumJSCallerSaved; i++) {
       int r = JSCallerSavedCode(i);
       Register reg = { r };
       if ((object_regs & (1 << r)) != 0) {
         __ push(reg);
       }
-      if ((non_object_regs & (1 << r)) != 0) {
-        __ PushRegisterAsTwoSmis(reg);
-      }
     }
 
 #ifdef DEBUG
@@ -114,14 +107,10 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
     for (int i = kNumJSCallerSaved - 1; i >= 0; i--) {
       int r = JSCallerSavedCode(i);
       Register reg = { r };
-      if ((non_object_regs & (1 << r)) != 0) {
-        __ PopRegisterAsTwoSmis(reg, at);
-      }
       if ((object_regs & (1 << r)) != 0) {
         __ pop(reg);
       }
-      if (FLAG_debug_code &&
-          (((object_regs |non_object_regs) & (1 << r)) == 0)) {
+      if (FLAG_debug_code && ((object_regs & (1 << r)) == 0)) {
         __ li(reg, kDebugZapValue);
       }
     }
@@ -143,54 +132,11 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
 }
 
 
-void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
-  // Register state for CallICStub
-  // ----------- S t a t e -------------
-  //  -- a1 : function
-  //  -- a3 : slot in feedback array (smi)
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, a1.bit() | a3.bit(), 0);
-}
-
-
 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
   // In places other than IC call sites it is expected that v0 is TOS which
   // is an object - this is not generally the case so this should be used with
   // care.
-  Generate_DebugBreakCallHelper(masm, v0.bit(), 0);
-}
-
-
-void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) {
-  // Register state for CallFunctionStub (from code-stubs-mips.cc).
-  // ----------- S t a t e -------------
-  //  -- a1 : function
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, a1.bit(), 0);
-}
-
-
-void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) {
-  // Calling convention for CallConstructStub (from code-stubs-mips.cc).
-  // ----------- S t a t e -------------
-  //  -- a0     : number of arguments (not smi)
-  //  -- a1     : constructor function
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, a1.bit() , a0.bit());
-}
-
-
-
-void DebugCodegen::GenerateCallConstructStubRecordDebugBreak(
-    MacroAssembler* masm) {
-  // Calling convention for CallConstructStub (from code-stubs-mips.cc).
-  // ----------- S t a t e -------------
-  //  -- a0     : number of arguments (not smi)
-  //  -- a1     : constructor function
-  //  -- a2     : feedback array
-  //  -- a3     : feedback slot (smi)
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, a1.bit() | a2.bit() | a3.bit(), a0.bit());
+  Generate_DebugBreakCallHelper(masm, v0.bit());
 }
 
 
@@ -200,7 +146,6 @@ void DebugCodegen::GenerateSlot(MacroAssembler* masm) {
   Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm);
   Label check_codesize;
   __ bind(&check_codesize);
-  __ RecordDebugBreakSlot();
   for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
     __ nop(MacroAssembler::DEBUG_BREAK_NOP);
   }
@@ -212,7 +157,7 @@ void DebugCodegen::GenerateSlot(MacroAssembler* masm) {
 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) {
   // In the places where a debug break slot is inserted no registers can contain
   // object pointers.
-  Generate_DebugBreakCallHelper(masm, 0, 0);
+  Generate_DebugBreakCallHelper(masm, 0);
 }
 
 
index 569dc51afc66fd6305cb28db59a9299700238c60..97d5a45d846e6afc54785526f52e3c6909bb5bc2 100644 (file)
@@ -2261,6 +2261,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       __ mov(a0, v0);
       __ mov(a1, a0);
       __ sd(a1, MemOperand(sp, 2 * kPointerSize));
+      SetCallPosition(expr, 1);
       CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
       __ CallStub(&stub);
 
@@ -3091,7 +3092,7 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
   }
 
   // Record source position of the IC call.
-  SetExpressionPosition(expr);
+  SetCallPosition(expr, arg_count);
   Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
   __ li(a3, Operand(SmiFromSlot(expr->CallFeedbackICSlot())));
   __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
@@ -3206,25 +3207,25 @@ void FullCodeGenerator::VisitCall(Call* expr) {
     // function using the given arguments.
     ZoneList<Expression*>* args = expr->arguments();
     int arg_count = args->length();
-      PushCalleeAndWithBaseObject(expr);
+    PushCalleeAndWithBaseObject(expr);
 
-      // Push the arguments.
-      for (int i = 0; i < arg_count; i++) {
-        VisitForStackValue(args->at(i));
-      }
+    // Push the arguments.
+    for (int i = 0; i < arg_count; i++) {
+      VisitForStackValue(args->at(i));
+    }
 
-      // Push a copy of the function (found below the arguments) and
-      // resolve eval.
-      __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
-      __ push(a1);
-      EmitResolvePossiblyDirectEval(arg_count);
+    // Push a copy of the function (found below the arguments) and
+    // resolve eval.
+    __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
+    __ push(a1);
+    EmitResolvePossiblyDirectEval(arg_count);
 
-      // Touch up the stack with the resolved function.
-      __ sd(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
+    // Touch up the stack with the resolved function.
+    __ sd(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
 
-      PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
+    PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
     // Record source position for debugger.
-      SetExpressionPosition(expr);
+    SetCallPosition(expr, arg_count);
     CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
     __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
     __ CallStub(&stub);
@@ -3295,7 +3296,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
 
   // Call the construct call builtin that handles allocation and
   // constructor invocation.
-  SetExpressionPosition(expr);
+  SetConstructCallPosition(expr);
 
   // Load function and argument count into a1 and a0.
   __ li(a0, Operand(arg_count));
@@ -3338,7 +3339,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
 
   // Call the construct call builtin that handles allocation and
   // constructor invocation.
-  SetExpressionPosition(expr);
+  SetConstructCallPosition(expr);
 
   // Load function and argument count into a1 and a0.
   __ li(a0, Operand(arg_count));
@@ -4754,7 +4755,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
 
-  SetExpressionPosition(expr);
+  SetCallPosition(expr, arg_count);
   CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
   __ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
   __ CallStub(&stub);
index 15c531960f337ac094ebd24c08bcdac8a34c2535..f5780a40bdbad57c7a93a48aadf7c34dc3365a25 100644 (file)
@@ -1619,6 +1619,8 @@ class Assembler : public AssemblerBase {
 
   // Mark address of a debug break slot.
   void RecordDebugBreakSlot();
+  void RecordDebugBreakSlotForCall(int argc);
+  void RecordDebugBreakSlotForConstructCall();
 
   // Record a comment relocation entry that can be used by a disassembler.
   // Use --code-comments to enable.
index 1749760d3746716ea696cccae9f44bae590a7566..c7acf9824a5de4e7c9c935e17db3048da7f6e9b9 100644 (file)
@@ -69,9 +69,7 @@ void BreakLocation::SetDebugBreakAtSlot() {
 
 
 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
-                                          RegList object_regs,
-                                          RegList non_object_regs,
-                                          bool convert_call_to_jmp) {
+                                          RegList object_regs) {
   // Enter an internal frame.
   {
     FrameScope scope(masm, StackFrame::INTERNAL);
@@ -86,8 +84,6 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
     // make sure that these are correctly updated during GC. Non object values
     // are stored as as two smis causing it to be untouched by GC.
     DCHECK((object_regs & ~kJSCallerSaved) == 0);
-    DCHECK((non_object_regs & ~kJSCallerSaved) == 0);
-    DCHECK((object_regs & non_object_regs) == 0);
     for (int i = 0; i < kNumJSCallerSaved; i++) {
       int r = JSCallerSavedCode(i);
       Register reg = { r };
@@ -95,9 +91,6 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
       if ((object_regs & (1 << r)) != 0) {
         __ Push(reg);
       }
-      if ((non_object_regs & (1 << r)) != 0) {
-        __ PushRegisterAsTwoSmis(reg);
-      }
     }
 
 #ifdef DEBUG
@@ -119,10 +112,6 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
       if ((object_regs & (1 << r)) != 0) {
         __ Pop(reg);
       }
-      // Reconstruct the 64-bit value from two smis.
-      if ((non_object_regs & (1 << r)) != 0) {
-        __ PopRegisterAsTwoSmis(reg);
-      }
     }
 
     // Read current padding counter and skip corresponding number of words.
@@ -133,11 +122,9 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
     // Get rid of the internal frame.
   }
 
-  // If this call did not replace a call but patched other code then there will
-  // be an unwanted return address left on the stack. Here we get rid of that.
-  if (convert_call_to_jmp) {
-    __ addp(rsp, Immediate(kPCOnStackSize));
-  }
+  // This call did not replace a call , so there will be an unwanted
+  // return address left on the stack. Here we get rid of that.
+  __ addp(rsp, Immediate(kPCOnStackSize));
 
   // Now that the break point has been handled, resume normal execution by
   // jumping to the target address intended by the caller and that was
@@ -149,59 +136,12 @@ static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
 }
 
 
-void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
-  // Register state for CallICStub
-  // ----------- S t a t e -------------
-  //  -- rdx    : type feedback slot (smi)
-  //  -- rdi    : function
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, rdx.bit() | rdi.bit(), 0, false);
-}
-
-
 void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
   // Register state just before return from JS function (from codegen-x64.cc).
   // ----------- S t a t e -------------
   //  -- rax: return value
   // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, rax.bit(), 0, true);
-}
-
-
-void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) {
-  // Register state for CallFunctionStub (from code-stubs-x64.cc).
-  // ----------- S t a t e -------------
-  //  -- rdi : function
-  // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, rdi.bit(), 0, false);
-}
-
-
-void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) {
-  // Register state for CallConstructStub (from code-stubs-x64.cc).
-  // rax is the actual number of arguments not encoded as a smi, see comment
-  // above IC call.
-  // ----------- S t a t e -------------
-  //  -- rax: number of arguments
-  // -----------------------------------
-  // The number of arguments in rax is not smi encoded.
-  Generate_DebugBreakCallHelper(masm, rdi.bit(), rax.bit(), false);
-}
-
-
-void DebugCodegen::GenerateCallConstructStubRecordDebugBreak(
-    MacroAssembler* masm) {
-  // Register state for CallConstructStub (from code-stubs-x64.cc).
-  // rax is the actual number of arguments not encoded as a smi, see comment
-  // above IC call.
-  // ----------- S t a t e -------------
-  //  -- rax: number of arguments
-  //  -- rbx: feedback array
-  //  -- rdx: feedback slot (smi)
-  // -----------------------------------
-  // The number of arguments in rax is not smi encoded.
-  Generate_DebugBreakCallHelper(masm, rbx.bit() | rdx.bit() | rdi.bit(),
-                                rax.bit(), false);
+  Generate_DebugBreakCallHelper(masm, rax.bit());
 }
 
 
@@ -209,7 +149,6 @@ void DebugCodegen::GenerateSlot(MacroAssembler* masm) {
   // Generate enough nop's to make space for a call instruction.
   Label check_codesize;
   __ bind(&check_codesize);
-  __ RecordDebugBreakSlot();
   __ Nop(Assembler::kDebugBreakSlotLength);
   DCHECK_EQ(Assembler::kDebugBreakSlotLength,
             masm->SizeOfCodeGeneratedSince(&check_codesize));
@@ -219,7 +158,7 @@ void DebugCodegen::GenerateSlot(MacroAssembler* masm) {
 void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) {
   // In the places where a debug break slot is inserted no registers can contain
   // object pointers.
-  Generate_DebugBreakCallHelper(masm, 0, 0, true);
+  Generate_DebugBreakCallHelper(masm, 0);
 }
 
 
index ef8c15087fe292930e5322509eccd9be17b7b4cd..f5939357ccaf9889ce20c2d7bd4c93c6df5e3937 100644 (file)
@@ -2228,6 +2228,8 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
       CallIC(ic, TypeFeedbackId::None());
       __ movp(rdi, rax);
       __ movp(Operand(rsp, 2 * kPointerSize), rdi);
+
+      SetCallPosition(expr, 1);
       CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
       __ CallStub(&stub);
 
@@ -2996,7 +2998,7 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
     VisitForStackValue(args->at(i));
   }
 
-  SetExpressionPosition(expr);
+  SetCallPosition(expr, arg_count);
   Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
   __ Move(rdx, SmiFromSlot(expr->CallFeedbackICSlot()));
   __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
@@ -3108,24 +3110,24 @@ void FullCodeGenerator::VisitCall(Call* expr) {
     // function using the given arguments.
     ZoneList<Expression*>* args = expr->arguments();
     int arg_count = args->length();
-      PushCalleeAndWithBaseObject(expr);
+    PushCalleeAndWithBaseObject(expr);
 
-      // Push the arguments.
-      for (int i = 0; i < arg_count; i++) {
-        VisitForStackValue(args->at(i));
-      }
+    // Push the arguments.
+    for (int i = 0; i < arg_count; i++) {
+      VisitForStackValue(args->at(i));
+    }
+
+    // Push a copy of the function (found below the arguments) and resolve
+    // eval.
+    __ Push(Operand(rsp, (arg_count + 1) * kPointerSize));
+    EmitResolvePossiblyDirectEval(arg_count);
 
-      // Push a copy of the function (found below the arguments) and resolve
-      // eval.
-      __ Push(Operand(rsp, (arg_count + 1) * kPointerSize));
-      EmitResolvePossiblyDirectEval(arg_count);
+    // Touch up the callee.
+    __ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
 
-      // Touch up the callee.
-      __ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
+    PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
 
-      PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
-    // Record source position for debugger.
-      SetExpressionPosition(expr);
+    SetCallPosition(expr, arg_count);
     CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
     __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
     __ CallStub(&stub);
@@ -3196,7 +3198,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
 
   // Call the construct call builtin that handles allocation and
   // constructor invocation.
-  SetExpressionPosition(expr);
+  SetConstructCallPosition(expr);
 
   // Load function and argument count into rdi and rax.
   __ Set(rax, arg_count);
@@ -3239,7 +3241,7 @@ void FullCodeGenerator::EmitSuperConstructorCall(Call* expr) {
 
   // Call the construct call builtin that handles allocation and
   // constructor invocation.
-  SetExpressionPosition(expr);
+  SetConstructCallPosition(expr);
 
   // Load function and argument count into edi and eax.
   __ Set(rax, arg_count);
@@ -4688,7 +4690,7 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   int arg_count = args->length();
 
-  SetExpressionPosition(expr);
+  SetCallPosition(expr, arg_count);
   CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
   __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
   __ CallStub(&stub);
index a6ffdca179767b44424d1a3604acbf2020b8c5c0..c8c80b266205caa09a076b96f5f41277ac7829e3 100644 (file)
@@ -439,61 +439,6 @@ static void CheckDebuggerUnloaded(bool check_functions = false) {
 }
 
 
-// Compile a function, set a break point and check that the call at the break
-// location in the code is the expected debug_break function.
-void CheckDebugBreakFunction(DebugLocalContext* env,
-                             const char* source, const char* name,
-                             int position, v8::internal::RelocInfo::Mode mode,
-                             Code* debug_break) {
-  EnableDebugger();
-  i::Debug* debug = CcTest::i_isolate()->debug();
-
-  // Create function and set the break point.
-  Handle<i::JSFunction> fun =
-      v8::Utils::OpenHandle(*CompileFunction(env, source, name));
-  int bp = SetBreakPoint(fun, position);
-
-  // Check that the debug break function is as expected.
-  Handle<i::SharedFunctionInfo> shared(fun->shared());
-  CHECK(Debug::HasDebugInfo(shared));
-  i::BreakLocation location = i::BreakLocation::FromPosition(
-      Debug::GetDebugInfo(shared), i::SOURCE_BREAK_LOCATIONS, position,
-      i::STATEMENT_ALIGNED);
-  i::RelocInfo::Mode actual_mode = location.rmode();
-  if (actual_mode == i::RelocInfo::CODE_TARGET_WITH_ID) {
-    actual_mode = i::RelocInfo::CODE_TARGET;
-  }
-  CHECK_EQ(mode, actual_mode);
-  if (mode != i::RelocInfo::JS_RETURN) {
-    CHECK_EQ(debug_break, *location.CodeTarget());
-  } else {
-    i::RelocInfo rinfo = location.rinfo();
-    CHECK(i::RelocInfo::IsJSReturn(rinfo.rmode()));
-    CHECK(rinfo.IsPatchedReturnSequence());
-  }
-
-  // Clear the break point and check that the debug break function is no longer
-  // there
-  ClearBreakPoint(bp);
-  CHECK(!debug->HasDebugInfo(shared));
-  CHECK(debug->EnsureDebugInfo(shared, fun));
-  location = i::BreakLocation::FromPosition(Debug::GetDebugInfo(shared),
-                                            i::SOURCE_BREAK_LOCATIONS, position,
-                                            i::STATEMENT_ALIGNED);
-  actual_mode = location.rmode();
-  if (actual_mode == i::RelocInfo::CODE_TARGET_WITH_ID) {
-    actual_mode = i::RelocInfo::CODE_TARGET;
-  }
-  CHECK_EQ(mode, actual_mode);
-  if (mode == i::RelocInfo::JS_RETURN) {
-    i::RelocInfo rinfo = location.rinfo();
-    CHECK(!rinfo.IsPatchedReturnSequence());
-  }
-
-  DisableDebugger();
-}
-
-
 // --- D e b u g   E v e n t   H a n d l e r s
 // ---
 // --- The different tests uses a number of debug event handlers.
diff --git a/test/mjsunit/debug-stepin-construct-call.js b/test/mjsunit/debug-stepin-construct-call.js
new file mode 100644 (file)
index 0000000..5e21455
--- /dev/null
@@ -0,0 +1,42 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug
+
+var break_count = 0;
+var exception = null;
+
+function listener(event, exec_state, event_data, data) {
+  if (event != Debug.DebugEvent.Break) return;
+  try {
+    var source_line = exec_state.frame(0).sourceLineText();
+    print(source_line);
+    exec_state.prepareStep(Debug.StepAction.StepIn, 1);
+    break_count++;
+  } catch (e) {
+    exception = e;
+  }
+}
+
+var Debug = debug.Debug;
+Debug.setListener(listener);
+
+
+function f() {
+  this.x = 1;
+}
+
+function g() {
+  new f();
+}
+
+Debug.setBreakPoint(g, 6, Debug.BreakPositionAlignment.BreakPosition);
+print(Debug.showBreakPoints(g, undefined,
+      Debug.BreakPositionAlignment.BreakPosition));
+
+g();
+Debug.setListener(null);
+
+assertEquals(6, break_count);
+assertNull(exception);