Commit a8a4c364 authored by yangguo's avatar yangguo Committed by Commit bot

Debugger: use debug break slots instead of ICs (except for calls).

BUG=v8:3147,v8:4269
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#29487}
parent ef661b08
......@@ -140,50 +140,6 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
}
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC load (from ic-arm.cc).
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
Register slot = LoadDescriptor::SlotRegister();
RegList regs = receiver.bit() | name.bit() | slot.bit();
Generate_DebugBreakCallHelper(masm, regs, 0);
}
void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC store (from ic-arm.cc).
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
Register value = StoreDescriptor::ValueRegister();
RegList regs = receiver.bit() | name.bit() | value.bit();
if (FLAG_vector_stores) {
regs |= VectorStoreICDescriptor::SlotRegister().bit();
}
Generate_DebugBreakCallHelper(masm, regs, 0);
}
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
// Calling convention for keyed IC load (from ic-arm.cc).
GenerateLoadICDebugBreak(masm);
}
void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC keyed store call (from ic-arm.cc).
GenerateStoreICDebugBreak(masm);
}
void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) {
// Register state for CompareNil IC
// ----------- S t a t e -------------
// -- r0 : value
// -----------------------------------
Generate_DebugBreakCallHelper(masm, r0.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
......
This diff is collapsed.
......@@ -203,50 +203,6 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
}
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC load (from ic-arm.cc).
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
Register slot = LoadDescriptor::SlotRegister();
RegList regs = receiver.Bit() | name.Bit() | slot.Bit();
Generate_DebugBreakCallHelper(masm, regs, 0, x10);
}
void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC store (from ic-arm64.cc).
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
Register value = StoreDescriptor::ValueRegister();
RegList regs = receiver.Bit() | name.Bit() | value.Bit();
if (FLAG_vector_stores) {
regs |= VectorStoreICDescriptor::SlotRegister().Bit();
}
Generate_DebugBreakCallHelper(masm, regs, 0, x10);
}
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
// Calling convention for keyed IC load (from ic-arm.cc).
GenerateLoadICDebugBreak(masm);
}
void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC keyed store call (from ic-arm64.cc).
GenerateStoreICDebugBreak(masm);
}
void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) {
// Register state for CompareNil IC
// ----------- S t a t e -------------
// -- r0 : value
// -----------------------------------
Generate_DebugBreakCallHelper(masm, x0.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
......
This diff is collapsed.
......@@ -1617,20 +1617,19 @@ bool PositionsRecorder::WriteRecordedPositions() {
EnsureSpace ensure_space(assembler_);
assembler_->RecordRelocInfo(RelocInfo::STATEMENT_POSITION,
state_.current_statement_position);
state_.written_position = state_.current_statement_position;
state_.written_statement_position = state_.current_statement_position;
written = true;
}
state_.written_statement_position = state_.current_statement_position;
// Write the position if it is different from what was written last time and
// also different from the statement position that was just written.
if (state_.current_position != state_.written_position &&
(state_.current_position != state_.written_statement_position ||
!written)) {
if (state_.current_position != state_.written_position) {
EnsureSpace ensure_space(assembler_);
assembler_->RecordRelocInfo(RelocInfo::POSITION, state_.current_position);
state_.written_position = state_.current_position;
written = true;
}
state_.written_position = state_.current_position;
// Return whether something was written.
return written;
......@@ -1869,7 +1868,6 @@ void Assembler::RecordJSReturn() {
void Assembler::RecordDebugBreakSlot() {
positions_recorder()->WriteRecordedPositions();
EnsureSpace ensure_space(this);
RecordRelocInfo(RelocInfo::DEBUG_BREAK_SLOT);
}
......
......@@ -1085,34 +1085,11 @@ class PositionsRecorder BASE_EMBEDDED {
// Currently jit_handler_data_ is used to store JITHandler-specific data
// over the lifetime of a PositionsRecorder
void* jit_handler_data_;
friend class PreservePositionScope;
DISALLOW_COPY_AND_ASSIGN(PositionsRecorder);
};
class PreservePositionScope BASE_EMBEDDED {
public:
explicit PreservePositionScope(PositionsRecorder* positions_recorder)
: positions_recorder_(positions_recorder),
saved_state_(positions_recorder->state_) {
// Reset positions so that previous ones do not accidentally get
// recorded within this scope.
positions_recorder->state_ = PositionState();
}
~PreservePositionScope() {
positions_recorder_->state_ = saved_state_;
}
private:
PositionsRecorder* positions_recorder_;
const PositionState saved_state_;
DISALLOW_COPY_AND_ASSIGN(PreservePositionScope);
};
// -----------------------------------------------------------------------------
// Utility functions
......
......@@ -1374,31 +1374,6 @@ static void Generate_CallICStub_DebugBreak(MacroAssembler* masm) {
}
static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
DebugCodegen::GenerateLoadICDebugBreak(masm);
}
static void Generate_StoreIC_DebugBreak(MacroAssembler* masm) {
DebugCodegen::GenerateStoreICDebugBreak(masm);
}
static void Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {
DebugCodegen::GenerateKeyedLoadICDebugBreak(masm);
}
static void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {
DebugCodegen::GenerateKeyedStoreICDebugBreak(masm);
}
static void Generate_CompareNilIC_DebugBreak(MacroAssembler* masm) {
DebugCodegen::GenerateCompareNilICDebugBreak(masm);
}
static void Generate_Return_DebugBreak(MacroAssembler* masm) {
DebugCodegen::GenerateReturnDebugBreak(masm);
}
......
......@@ -151,16 +151,6 @@ enum BuiltinExtraArguments {
DEBUG_BREAK) \
V(CallICStub_DebugBreak, CALL_IC, DEBUG_STUB, \
DEBUG_BREAK) \
V(LoadIC_DebugBreak, LOAD_IC, DEBUG_STUB, \
DEBUG_BREAK) \
V(KeyedLoadIC_DebugBreak, KEYED_LOAD_IC, DEBUG_STUB, \
DEBUG_BREAK) \
V(StoreIC_DebugBreak, STORE_IC, DEBUG_STUB, \
DEBUG_BREAK) \
V(KeyedStoreIC_DebugBreak, KEYED_STORE_IC, DEBUG_STUB, \
DEBUG_BREAK) \
V(CompareNilIC_DebugBreak, COMPARE_NIL_IC, DEBUG_STUB, \
DEBUG_BREAK) \
V(Slot_DebugBreak, BUILTIN, DEBUG_STUB, \
DEBUG_BREAK) \
V(PlainReturn_LiveEdit, BUILTIN, DEBUG_STUB, \
......
......@@ -239,19 +239,5 @@ void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
#endif // ENABLE_DISASSEMBLER
}
bool CodeGenerator::RecordPositions(MacroAssembler* masm,
int pos,
bool right_here) {
if (pos != RelocInfo::kNoPosition) {
masm->positions_recorder()->RecordStatementPosition(pos);
masm->positions_recorder()->RecordPosition(pos);
if (right_here) {
return masm->positions_recorder()->WriteRecordedPositions();
}
}
return false;
}
} // namespace internal
} // namespace v8
......@@ -84,10 +84,6 @@ class CodeGenerator {
// Print the code after compiling it.
static void PrintCode(Handle<Code> code, CompilationInfo* info);
static bool RecordPositions(MacroAssembler* masm,
int pos,
bool right_here = false);
private:
DISALLOW_COPY_AND_ASSIGN(CodeGenerator);
};
......
......@@ -84,8 +84,7 @@ BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info,
~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE)),
break_index_(-1),
position_(1),
statement_position_(1),
has_immediate_position_(false) {
statement_position_(1) {
Next();
}
......@@ -115,7 +114,6 @@ void BreakLocation::Iterator::Next() {
debug_info_->shared()->start_position());
DCHECK(position_ >= 0);
DCHECK(statement_position_ >= 0);
has_immediate_position_ = true;
continue;
}
......@@ -145,25 +143,19 @@ void BreakLocation::Iterator::Next() {
break;
}
// Skip below if we only want locations for calls and returns.
if (type_ == CALLS_AND_RETURNS) continue;
// Only break at an inline cache if it has an immediate position attached.
if (has_immediate_position_ &&
(code->is_inline_cache_stub() && !code->is_binary_op_stub() &&
!code->is_compare_ic_stub() && !code->is_to_boolean_ic_stub())) {
if (code->kind() == Code::STUB &&
CodeStub::GetMajorKey(code) == CodeStub::CallFunction) {
break_index_++;
break;
}
if (code->kind() == Code::STUB) {
if (RelocInfo::IsDebuggerStatement(rmode())) {
break_index_++;
break;
} else if (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_++;
break;
}
if (RelocInfo::IsDebugBreakSlot(rmode()) && type_ != CALLS_AND_RETURNS) {
......@@ -172,7 +164,6 @@ void BreakLocation::Iterator::Next() {
break;
}
}
has_immediate_position_ = false;
}
......@@ -385,28 +376,8 @@ static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) {
// Find the builtin debug break function matching the calling convention
// used by the call site.
if (code->is_inline_cache_stub()) {
switch (code->kind()) {
case Code::CALL_IC:
return isolate->builtins()->CallICStub_DebugBreak();
case Code::LOAD_IC:
return isolate->builtins()->LoadIC_DebugBreak();
case Code::STORE_IC:
return isolate->builtins()->StoreIC_DebugBreak();
case Code::KEYED_LOAD_IC:
return isolate->builtins()->KeyedLoadIC_DebugBreak();
case Code::KEYED_STORE_IC:
return isolate->builtins()->KeyedStoreIC_DebugBreak();
case Code::COMPARE_NIL_IC:
return isolate->builtins()->CompareNilIC_DebugBreak();
default:
UNREACHABLE();
}
DCHECK(code->kind() == Code::CALL_IC);
return isolate->builtins()->CallICStub_DebugBreak();
}
if (RelocInfo::IsConstructCall(mode)) {
if (code->has_function_cache()) {
......@@ -1258,8 +1229,6 @@ void Debug::PrepareStep(StepAction step_action,
Handle<DebugInfo> debug_info = GetDebugInfo(shared);
// Compute whether or not the target is a call target.
bool is_load_or_store = false;
bool is_inline_cache_stub = false;
bool is_at_restarted_function = false;
Handle<Code> call_function_stub;
......@@ -1272,8 +1241,6 @@ void Debug::PrepareStep(StepAction step_action,
if (thread_local_.restarter_frame_function_pointer_ == NULL) {
if (location.IsCodeTarget()) {
Handle<Code> target_code = location.CodeTarget();
is_inline_cache_stub = target_code->is_inline_cache_stub();
is_load_or_store = is_inline_cache_stub && !target_code->is_call_stub();
// Check if target code is CallFunction stub.
Handle<Code> maybe_call_function_stub = target_code;
......@@ -1320,21 +1287,10 @@ void Debug::PrepareStep(StepAction step_action,
// Set target frame pointer.
ActivateStepOut(frames_it.frame());
}
} else if (!(is_inline_cache_stub || location.IsConstructCall() ||
!call_function_stub.is_null() || is_at_restarted_function) ||
step_action == StepNext || step_action == StepMin) {
// Step next or step min.
// Fill the current function with one-shot break points.
// If we are stepping into another frame, only fill calls and returns.
FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
: ALL_BREAK_LOCATIONS);
// Remember source position and frame to handle step next.
thread_local_.last_statement_position_ =
debug_info->code()->SourceStatementPosition(summary.pc());
thread_local_.last_fp_ = frame->UnpaddedFP();
} else {
return;
}
if (step_action != StepNext && step_action != StepMin) {
// If there's restarter frame on top of the stack, just get the pointer
// to function which is going to be restarted.
if (is_at_restarted_function) {
......@@ -1395,36 +1351,21 @@ void Debug::PrepareStep(StepAction step_action,
}
}
// Fill the current function with one-shot break points even for step in on
// a call target as the function called might be a native function for
// which step in will not stop. It also prepares for stepping in
// getters/setters.
// If we are stepping into another frame, only fill calls and returns.
FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
: ALL_BREAK_LOCATIONS);
if (is_load_or_store) {
// Remember source position and frame to handle step in getter/setter. If
// there is a custom getter/setter it will be handled in
// Object::Get/SetPropertyWithAccessor, otherwise the step action will be
// propagated on the next Debug::Break.
thread_local_.last_statement_position_ =
debug_info->code()->SourceStatementPosition(summary.pc());
thread_local_.last_fp_ = frame->UnpaddedFP();
}
// Step in or Step in min
// Step in through construct call requires no changes to the running code.
// Step in through getters/setters should already be prepared as well
// because caller of this function (Debug::PrepareStep) is expected to
// flood the top frame's function with one shot breakpoints.
// Step in through CallFunction stub should also be prepared by caller of
// this function (Debug::PrepareStep) which should flood target function
// with breakpoints.
DCHECK(location.IsConstructCall() || is_inline_cache_stub ||
!call_function_stub.is_null() || is_at_restarted_function);
ActivateStepIn(frame);
}
// Fill the current function with one-shot break points even for step in on
// a call target as the function called might be a native function for
// which step in will not stop. It also prepares for stepping in
// getters/setters.
// If we are stepping into another frame, only fill calls and returns.
FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
: ALL_BREAK_LOCATIONS);
// Remember source position and frame to handle step next.
thread_local_.last_statement_position_ =
debug_info->code()->SourceStatementPosition(summary.pc());
thread_local_.last_fp_ = frame->UnpaddedFP();
}
......
......@@ -177,7 +177,6 @@ class BreakLocation {
int break_index_;
int position_;
int statement_position_;
bool has_immediate_position_;
DisallowHeapAllocation no_gc_;
......
This diff is collapsed.
......@@ -24,35 +24,6 @@ namespace internal {
// Forward declarations.
class JumpPatchSite;
// AST node visitor which can tell whether a given statement will be breakable
// when the code is compiled by the full compiler in the debugger. This means
// that there will be an IC (load/store/call) in the code generated for the
// debugger to piggybag on.
class BreakableStatementChecker: public AstVisitor {
public:
BreakableStatementChecker(Isolate* isolate, Zone* zone)
: is_breakable_(false) {
InitializeAstVisitor(isolate, zone);
}
void Check(Statement* stmt);
void Check(Expression* stmt);
bool is_breakable() { return is_breakable_; }
private:
// AST node visit functions.
#define DECLARE_VISIT(type) virtual void Visit##type(type* node) override;
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
bool is_breakable_;
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
DISALLOW_COPY_AND_ASSIGN(BreakableStatementChecker);
};
// -----------------------------------------------------------------------------
// Full code generator.
......@@ -688,9 +659,21 @@ class FullCodeGenerator: public AstVisitor {
void SetFunctionPosition(FunctionLiteral* fun);
void SetReturnPosition(FunctionLiteral* fun);
void SetStatementPosition(Statement* stmt);
void SetExpressionPosition(Expression* expr);
void SetSourcePosition(int pos);
enum InsertBreak { INSERT_BREAK, SKIP_BREAK };
// During stepping we want to be able to break at each statement, but not at
// every (sub-)expression. That is why by default we insert breaks at every
// statement position, but not at every expression position, unless stated
// otherwise.
void SetStatementPosition(Statement* stmt,
InsertBreak insert_break = INSERT_BREAK);
void SetExpressionPosition(Expression* expr,
InsertBreak insert_break = SKIP_BREAK);
// Consider an expression a statement. As such, we also insert a break.
// This is used in loop headers where we want to break for each iteration.
void SetExpressionAsStatementPosition(Expression* expr);
// Non-local control flow support.
void EnterTryBlock(int handler_index, Label* handler);
......
......@@ -179,50 +179,6 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
}
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
// Register state for IC load call (from ic-ia32.cc).
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
Register slot = LoadDescriptor::SlotRegister();
RegList regs = receiver.bit() | name.bit() | slot.bit();
Generate_DebugBreakCallHelper(masm, regs, 0, false);
}
void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
// Register state for IC store call (from ic-ia32.cc).
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
Register value = StoreDescriptor::ValueRegister();
RegList regs = receiver.bit() | name.bit() | value.bit();
if (FLAG_vector_stores) {
regs |= VectorStoreICDescriptor::SlotRegister().bit();
}
Generate_DebugBreakCallHelper(masm, regs, 0, false);
}
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
// Register state for keyed IC load call (from ic-ia32.cc).
GenerateLoadICDebugBreak(masm);
}
void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
// Register state for keyed IC store call (from ic-ia32.cc).
GenerateStoreICDebugBreak(masm);
}
void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) {
// Register state for CompareNil IC
// ----------- S t a t e -------------
// -- eax : value
// -----------------------------------
Generate_DebugBreakCallHelper(masm, eax.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 -------------
......@@ -283,8 +239,6 @@ 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);
}
......
This diff is collapsed.
......@@ -150,49 +150,6 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
}
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
Register slot = LoadDescriptor::SlotRegister();
RegList regs = receiver.bit() | name.bit() | slot.bit();
Generate_DebugBreakCallHelper(masm, regs, 0);
}
void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC store (from ic-mips.cc).
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
Register value = StoreDescriptor::ValueRegister();
RegList regs = receiver.bit() | name.bit() | value.bit();
if (FLAG_vector_stores) {
regs |= VectorStoreICDescriptor::SlotRegister().bit();
}
Generate_DebugBreakCallHelper(masm, regs, 0);
}
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
// Calling convention for keyed IC load (from ic-mips.cc).
GenerateLoadICDebugBreak(masm);
}
void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC keyed store call (from ic-mips.cc).
GenerateStoreICDebugBreak(masm);
}
void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) {
// Register state for CompareNil IC
// ----------- S t a t e -------------
// -- a0 : value
// -----------------------------------
Generate_DebugBreakCallHelper(masm, a0.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
......
This diff is collapsed.
......@@ -153,48 +153,6 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
}
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
Register slot = LoadDescriptor::SlotRegister();
RegList regs = receiver.bit() | name.bit() | slot.bit();
Generate_DebugBreakCallHelper(masm, regs, 0);
}
void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
Register value = StoreDescriptor::ValueRegister();
RegList regs = receiver.bit() | name.bit() | value.bit();
if (FLAG_vector_stores) {
regs |= VectorStoreICDescriptor::SlotRegister().bit();
}
Generate_DebugBreakCallHelper(masm, regs, 0);
}
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
// Calling convention for keyed IC load (from ic-mips64.cc).
GenerateLoadICDebugBreak(masm);
}
void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
// Calling convention for IC keyed store call (from ic-mips64.cc).
GenerateStoreICDebugBreak(masm);
}
void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) {
// Register state for CompareNil IC
// ----------- S t a t e -------------
// -- a0 : value
// -----------------------------------
Generate_DebugBreakCallHelper(masm, a0.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
......
This diff is collapsed.
......@@ -3208,7 +3208,7 @@ void Parser::InitializeForEachStatement(ForEachStatement* stmt,
Expression* result_value = factory()->NewProperty(
result_proxy, value_literal, RelocInfo::kNoPosition);
assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
each->position());
RelocInfo::kNoPosition);
}
for_of->Initialize(each, subject, body,
......@@ -3592,6 +3592,7 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
parsing_result.declarations[0];
auto descriptor = parsing_result.descriptor;
descriptor.declaration_pos = RelocInfo::kNoPosition;
descriptor.initialization_pos = RelocInfo::kNoPosition;
decl.initializer = factory()->NewVariableProxy(temp);
PatternRewriter::DeclareAndInitializeVariables(
......@@ -3688,7 +3689,8 @@ Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
return loop;
} else {
init = factory()->NewExpressionStatement(expression, position());
init =
factory()->NewExpressionStatement(expression, lhs_location.beg_pos);
}
}
}
......
......@@ -159,50 +159,6 @@ void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
}
void DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
// Register state for IC load call (from ic-x64.cc).
Register receiver = LoadDescriptor::ReceiverRegister();
Register name = LoadDescriptor::NameRegister();
Register slot = LoadDescriptor::SlotRegister();
RegList regs = receiver.bit() | name.bit() | slot.bit();
Generate_DebugBreakCallHelper(masm, regs, 0, false);
}
void DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
// Register state for IC store call (from ic-x64.cc).
Register receiver = StoreDescriptor::ReceiverRegister();
Register name = StoreDescriptor::NameRegister();
Register value = StoreDescriptor::ValueRegister();
RegList regs = receiver.bit() | name.bit() | value.bit();
if (FLAG_vector_stores) {
regs |= VectorStoreICDescriptor::SlotRegister().bit();
}
Generate_DebugBreakCallHelper(masm, regs, 0, false);
}
void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
// Register state for keyed IC load call (from ic-x64.cc).
GenerateLoadICDebugBreak(masm);
}
void DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
// Register state for keyed IC store call (from ic-x64.cc).
GenerateStoreICDebugBreak(masm);
}
void DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) {
// Register state for CompareNil IC
// ----------- S t a t e -------------
// -- rax : value
// -----------------------------------
Generate_DebugBreakCallHelper(masm, rax.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 -------------
......
This diff is collapsed.
......@@ -969,82 +969,6 @@ static void MessageCallbackCount(v8::Handle<v8::Message> message,
// --- T h e A c t u a l T e s t s
// Test that the debug break function is the expected one for different kinds
// of break locations.
TEST(DebugStub) {
using ::v8::internal::Builtins;
using ::v8::internal::Isolate;
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
CheckDebugBreakFunction(&env,
"function f1(){}", "f1",
0,
v8::internal::RelocInfo::JS_RETURN,
NULL);
CheckDebugBreakFunction(&env,
"function f2(){x=1;}", "f2",
0,
v8::internal::RelocInfo::CODE_TARGET,
CcTest::i_isolate()->builtins()->builtin(
Builtins::kStoreIC_DebugBreak));
CheckDebugBreakFunction(
&env, "function f3(){x();}", "f3", 0,
v8::internal::RelocInfo::CODE_TARGET,
CcTest::i_isolate()->builtins()->builtin(Builtins::kLoadIC_DebugBreak));
// TODO(1240753): Make the test architecture independent or split
// parts of the debugger into architecture dependent files. This
// part currently disabled as it is not portable between IA32/ARM.
// Currently on ICs for keyed store/load on ARM.
#if !defined (__arm__) && !defined(__thumb__)
CheckDebugBreakFunction(
&env,
"function f4(){var index='propertyName'; var a={}; a[index] = 'x';}",
"f4", 39, v8::internal::RelocInfo::CODE_TARGET,
CcTest::i_isolate()->builtins()->builtin(
Builtins::kKeyedStoreIC_DebugBreak));
CheckDebugBreakFunction(
&env,
"function f5(){var index='propertyName'; var a={}; return a[index];}",
"f5", 39, v8::internal::RelocInfo::CODE_TARGET,
CcTest::i_isolate()->builtins()->builtin(
Builtins::kKeyedLoadIC_DebugBreak));
#endif
CheckDebugBreakFunction(&env, "function f6(){(0==null)()}", "f6", 0,
v8::internal::RelocInfo::CODE_TARGET,
CcTest::i_isolate()->builtins()->builtin(
Builtins::kCompareNilIC_DebugBreak));
// Check the debug break code stubs for call ICs with different number of
// parameters.
// TODO(verwaest): XXX update test.
// Handle<Code> debug_break_0 = v8::internal::ComputeCallDebugBreak(0);
// Handle<Code> debug_break_1 = v8::internal::ComputeCallDebugBreak(1);
// Handle<Code> debug_break_4 = v8::internal::ComputeCallDebugBreak(4);
// CheckDebugBreakFunction(&env,
// "function f4_0(){x();}", "f4_0",
// 0,
// v8::internal::RelocInfo::CODE_TARGET,
// *debug_break_0);
// CheckDebugBreakFunction(&env,
// "function f4_1(){x(1);}", "f4_1",
// 0,
// v8::internal::RelocInfo::CODE_TARGET,
// *debug_break_1);
// CheckDebugBreakFunction(&env,
// "function f4_4(){x(1,2,3,4);}", "f4_4",
// 0,
// v8::internal::RelocInfo::CODE_TARGET,
// *debug_break_4);
}
// Test that the debug info in the VM is in sync with the functions being
// debugged.
TEST(DebugInfo) {
......@@ -2346,7 +2270,7 @@ TEST(DebuggerStatementBreakpoint) {
v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "foo")));
// The debugger statement triggers breakpint hit
// The debugger statement triggers breakpoint hit
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(1, break_point_hit_count);
......@@ -3270,6 +3194,13 @@ TEST(DebugStepDoWhile) {
v8::Local<v8::Function> foo = CompileFunction(&env, src, "foo");
SetBreakPoint(foo, 8); // "var a = 0;"
// Looping 0 times.
step_action = StepIn;
break_point_hit_count = 0;
v8::Handle<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)};
foo->Call(env->Global(), argc, argv_0);
CHECK_EQ(4, break_point_hit_count);
// Looping 10 times.
step_action = StepIn;
break_point_hit_count = 0;
......@@ -3312,19 +3243,26 @@ TEST(DebugStepFor) {
SetBreakPoint(foo, 8); // "a = 1;"
// Looping 0 times.
step_action = StepIn;
break_point_hit_count = 0;
v8::Handle<v8::Value> argv_0[argc] = {v8::Number::New(isolate, 0)};
foo->Call(env->Global(), argc, argv_0);
CHECK_EQ(4, break_point_hit_count);
// Looping 10 times.
step_action = StepIn;
break_point_hit_count = 0;
v8::Handle<v8::Value> argv_10[argc] = { v8::Number::New(isolate, 10) };
foo->Call(env->Global(), argc, argv_10);
CHECK_EQ(45, break_point_hit_count);
CHECK_EQ(34, break_point_hit_count);
// Looping 100 times.
step_action = StepIn;
break_point_hit_count = 0;
v8::Handle<v8::Value> argv_100[argc] = { v8::Number::New(isolate, 100) };
foo->Call(env->Global(), argc, argv_100);
CHECK_EQ(405, break_point_hit_count);
CHECK_EQ(304, break_point_hit_count);
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
......@@ -3539,14 +3477,14 @@ TEST(DebugConditional) {
step_action = StepIn;
break_point_hit_count = 0;
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(5, break_point_hit_count);
CHECK_EQ(4, break_point_hit_count);
step_action = StepIn;
break_point_hit_count = 0;
const int argc = 1;
v8::Handle<v8::Value> argv_true[argc] = { v8::True(isolate) };
foo->Call(env->Global(), argc, argv_true);
CHECK_EQ(5, break_point_hit_count);
CHECK_EQ(4, break_point_hit_count);
// Get rid of the debug event listener.
v8::Debug::SetDebugEventListener(NULL);
......
......@@ -165,7 +165,7 @@ function listener(event, exec_state, event_data, data) {
assertEquals("f", response.lookup(frame.func.ref).name);
assertTrue(frame.constructCall);
assertEquals(31, frame.line);
assertEquals(3, frame.column);
assertEquals(2, frame.column);
assertEquals(2, frame.arguments.length);
assertEquals('x', frame.arguments[0].name);
assertEquals('number', response.lookup(frame.arguments[0].value.ref).type);
......@@ -179,7 +179,7 @@ function listener(event, exec_state, event_data, data) {
assertEquals(0, frame.index);
assertEquals("f", response.lookup(frame.func.ref).name);
assertEquals(31, frame.line);
assertEquals(3, frame.column);
assertEquals(2, frame.column);
assertEquals(2, frame.arguments.length);
assertEquals('x', frame.arguments[0].name);
assertEquals('number', response.lookup(frame.arguments[0].value.ref).type);
......
......@@ -211,7 +211,6 @@ assertTrue(Debug.showBreakPoints(g).indexOf("[B0]") < 0);
// (This may be sensitive to compiler break position map generation).
function h() {a=f(f2(1,2),f3())+f3();b=f3();}
var scenario = [
[5, "{a[B0]=f"],
[6, "{a=[B0]f("],
[7, "{a=f([B0]f2("],
[16, "f2(1,2),[B0]f3()"],
......
......@@ -11,7 +11,7 @@ function f0() {
try {
throw 1;
} catch (e) {
try{
try {
f1();
} catch (e) {
var v02 = 2; // Break 13
......@@ -19,6 +19,8 @@ function f0() {
}
var v03 = 3;
var v04 = 4;
eval('var v05 = 5; // Break 14');
var v06 = 6; // Break 15
}
function f1() {
......@@ -104,7 +106,7 @@ for (step_size = 1; step_size < 6; step_size++) {
Debug.setListener(listener);
debugger; // Break 0
f0();
Debug.setListener(null); // Break 14
Debug.setListener(null); // Break 16
assertTrue(break_count > 14);
}
......
......@@ -14,6 +14,7 @@ function listener(event, execState, eventData, data) {
if (!done) {
execState.prepareStep(Debug.StepAction.StepInto);
var s = execState.frame().sourceLineText();
print(s);
assertTrue(s.indexOf('// ' + stepCount + '.') !== -1);
stepCount++;
}
......@@ -24,10 +25,10 @@ Debug.setListener(listener);
class Base {
constructor() {
var x = 1; // 1.
var y = 2; // 2.
done = true; // 3.
constructor() { // 1.
var x = 1; // 2.
var y = 2; // 3.
done = true; // 4.
}
}
......@@ -40,7 +41,7 @@ class Derived extends Base {}
var bp = Debug.setBreakPoint(Base, 0);
new Base();
assertEquals(4, stepCount);
assertEquals(5, stepCount);
Debug.clearBreakPoint(bp);
})();
......@@ -52,7 +53,7 @@ class Derived extends Base {}
var bp = Debug.setBreakPoint(Base, 0);
new Derived();
assertEquals(4, stepCount);
assertEquals(5, stepCount);
Debug.clearBreakPoint(bp);
})();
......@@ -68,7 +69,7 @@ class Derived extends Base {}
var bp = Debug.setBreakPoint(f, 0);
f();
assertEquals(4, stepCount);
assertEquals(5, stepCount);
Debug.clearBreakPoint(bp);
})();
......@@ -86,7 +87,7 @@ class Derived extends Base {}
var bp = Debug.setBreakPoint(f, 0);
f();
assertEquals(4, stepCount);
assertEquals(5, stepCount);
Debug.clearBreakPoint(bp);
})();
......@@ -104,7 +105,7 @@ class Derived extends Base {}
var bp = Debug.setBreakPoint(f, 0);
f();
assertEquals(4, stepCount);
assertEquals(5, stepCount);
Debug.clearBreakPoint(bp);
})();
......
......@@ -106,7 +106,7 @@ var expected = [
// For-var: var decl, condition, body, next, condition, body, ...
"k7","k20","K4","k23","k20","K4","k23","k20","K4","k23","k20",
// For: init, condition, body, next, condition, body, ...
"l11","l16","L4","l19","l16","L4","l19","l16","L4","l19","l16",
"l7","l16","L4","l19","l16","L4","l19","l16","L4","l19","l16",
// Exit.
"y0","z0",
]
......
......@@ -354,9 +354,6 @@
'regress/regress-2185-2': [PASS, TIMEOUT],
'whitespaces': [PASS, TIMEOUT, SLOW],
# BUG(v8:3147). It works on other architectures by accident.
'regress/regress-conditional-position': [FAIL],
# BUG(v8:3457).
'deserialize-reference': [PASS, FAIL],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment