void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC call (from ic-arm.cc)
// ----------- S t a t e -------------
- // -- r0: number of arguments
- // -- r1: receiver
- // -- lr: return address
+ // -- r2: name
// -----------------------------------
- // Register r1 contains an object that needs to be pushed on the expression
- // stack of the fake JS frame. r0 is the actual number of arguments not
- // encoded as a smi, therefore it cannot be on the expression stack of the
- // fake JS frame as it can easily be an invalid pointer (e.g. 1). r0 will be
- // pushed on the stack of the C frame and restored from there.
- Generate_DebugBreakCallHelper(masm, r1.bit());
+ Generate_DebugBreakCallHelper(masm, r2.bit());
}
// -- ecx : key
// -- edx : receiver
// -----------------------------------
- // Register eax contains an object that needs to be pushed on the
- // expression stack of the fake JS frame.
Generate_DebugBreakCallHelper(masm, eax.bit() | ecx.bit() | edx.bit(), false);
}
void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
// Register state for keyed IC call call (from ic-ia32.cc)
// ----------- S t a t e -------------
- // -- eax: number of arguments
+ // -- ecx: name
// -----------------------------------
- // The number of arguments in eax is not smi encoded.
- Generate_DebugBreakCallHelper(masm, 0, false);
+ Generate_DebugBreakCallHelper(masm, ecx.bit(), false);
}
void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
- // Register state for keyed IC call call (from ic-x64.cc)
+ // Register state for IC call call (from ic-x64.cc)
// ----------- S t a t e -------------
- // -- rax: number of arguments
+ // -- rcx: function name
// -----------------------------------
- // The number of arguments in rax is not smi encoded.
- Generate_DebugBreakCallHelper(masm, 0, false);
+ Generate_DebugBreakCallHelper(masm, rcx.bit(), false);
}
// Scavenge.
Heap::CollectGarbage(0, v8::internal::NEW_SPACE);
} else {
- // Mark sweep (and perhaps compact).
- Heap::CollectAllGarbage(false);
+ // Mark sweep compact.
+ Heap::CollectAllGarbage(true);
}
}
}
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(0, break_point_hit_count);
- // Run with breakpoint
+ // Run with breakpoint.
int bp = SetBreakPoint(foo, 0);
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(1, break_point_hit_count);
}
+// Test that a break point can be set at an IC call location and survive a GC.
+TEST(BreakPointICCallWithGC) {
+ break_point_hit_count = 0;
+ v8::HandleScope scope;
+ DebugLocalContext env;
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage,
+ v8::Undefined());
+ v8::Script::Compile(v8::String::New("function bar(){return 1;}"))->Run();
+ v8::Script::Compile(v8::String::New("function foo(){return bar();}"))->Run();
+ v8::Local<v8::Function> foo =
+ v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("foo")));
+
+ // Run without breakpoints.
+ CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
+ CHECK_EQ(0, break_point_hit_count);
+
+ // Run with breakpoint.
+ int bp = SetBreakPoint(foo, 0);
+ CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
+ CHECK_EQ(1, break_point_hit_count);
+ CHECK_EQ(1, foo->Call(env->Global(), 0, NULL)->Int32Value());
+ CHECK_EQ(2, break_point_hit_count);
+
+ // Run without breakpoints.
+ ClearBreakPoint(bp);
+ foo->Call(env->Global(), 0, NULL);
+ CHECK_EQ(2, break_point_hit_count);
+
+ v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
+}
+
+
// Test that a break point can be set at a return store location.
TEST(BreakPointReturn) {
break_point_hit_count = 0;