Commit 86164a25 authored by yangguo's avatar yangguo Committed by Commit bot

[interpreter, debugger] implement debugger statement.

R=mstarzinger@chromium.org, rmcilroy@chromium.org
BUG=v8:4690
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#33739}
parent ce16b44b
......@@ -1518,6 +1518,13 @@ void BytecodeGraphBuilder::VisitReturn() {
MergeControlToLeaveFunction(control);
}
void BytecodeGraphBuilder::VisitDebugger() {
FrameStateBeforeAndAfter states(this);
Node* call =
NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement));
environment()->BindAccumulator(call, &states);
}
void BytecodeGraphBuilder::BuildForInPrepare() {
FrameStateBeforeAndAfter states(this);
Node* receiver = environment()->LookupAccumulator();
......
......@@ -989,6 +989,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() {
Output(Bytecode::kDebugger);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
Register cache_info_triple) {
......
......@@ -242,6 +242,9 @@ class BytecodeArrayBuilder final : public ZoneObject, private RegisterMover {
BytecodeArrayBuilder& ReThrow();
BytecodeArrayBuilder& Return();
// Debugger.
BytecodeArrayBuilder& Debugger();
// Complex flow control.
BytecodeArrayBuilder& ForInPrepare(Register cache_info_triple);
BytecodeArrayBuilder& ForInDone(Register index, Register cache_length);
......
......@@ -1212,7 +1212,7 @@ void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
UNIMPLEMENTED();
builder()->Debugger();
}
......
......@@ -265,7 +265,10 @@ namespace interpreter {
/* Non-local flow control */ \
V(Throw, OperandType::kNone) \
V(ReThrow, OperandType::kNone) \
V(Return, OperandType::kNone)
V(Return, OperandType::kNone) \
\
/* Debugger */ \
V(Debugger, OperandType::kNone)
// Enumeration of the size classes of operand types used by bytecodes.
enum class OperandSize : uint8_t {
......
......@@ -1824,6 +1824,13 @@ void Interpreter::DoReturn(compiler::InterpreterAssembler* assembler) {
__ Return();
}
// Debugger
//
// Call runtime to handle debugger statement.
void Interpreter::DoDebugger(compiler::InterpreterAssembler* assembler) {
__ CallRuntime(Runtime::kHandleDebuggerStatement);
__ Dispatch();
}
// ForInPrepare <cache_info_triple>
//
......
......@@ -511,7 +511,6 @@
# TODO(yangguo,4690): Required DebuggerStatement support.
'test-profile-generator/BailoutReason': [FAIL],
'test-api/Regress385349': [FAIL],
# TODO(mstarzinger,4674): Support exception handlers in BytecodeGraphBuilder.
'test-run-deopt/DeoptExceptionHandlerCatch': [PASS, FAIL],
......
......@@ -2716,6 +2716,37 @@ TEST(BytecodeGraphBuilderWithStatement) {
}
}
TEST(BytecodeGraphBuilderDebuggerStatement) {
FLAG_expose_debug_as = "debug";
HandleAndZoneScope scope;
Isolate* isolate = scope.main_isolate();
Zone* zone = scope.main_zone();
ExpectedSnippet<0> snippet = {
"var Debug = debug.Debug;"
"var count = 0;"
"function f() {"
" debugger;"
"}"
"function listener(event) {"
" if (event == Debug.DebugEvent.Break) count++;"
"}"
"Debug.setListener(listener);"
"f();"
"Debug.setListener(null);"
"return count;",
{handle(Smi::FromInt(1), isolate)}};
ScopedVector<char> script(1024);
SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
snippet.code_snippet, kFunctionName);
BytecodeGraphTester tester(isolate, zone, script.start());
auto callable = tester.GetCallable<>();
Handle<Object> return_value = callable().ToHandleChecked();
CHECK(return_value->SameValue(*snippet.return_value()));
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -8352,6 +8352,31 @@ TEST(WithStatement) {
}
}
TEST(DoDebugger) {
InitializedHandleScope handle_scope;
BytecodeGeneratorHelper helper;
// clang-format off
ExpectedSnippet<const char*> snippet = {
"debugger;",
0,
1,
4,
{
B(StackCheck), //
B(Debugger), //
B(LdaUndefined), //
B(Return) //
},
0
};
// clang-format on
Handle<BytecodeArray> bytecode_array =
helper.MakeBytecodeForFunctionBody(snippet.code_snippet);
CheckBytecodeArrayEqual(snippet, bytecode_array);
}
} // namespace interpreter
} // namespace internal
} // namespace v8
// Copyright 2016 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: --ignition-filter=f --expose-debug-as debug
var Debug = debug.Debug;
var break_count = 0;
function f() {
debugger;
}
function listener(event, exec_data) {
if (event != Debug.DebugEvent.Break) return;
break_count++;
}
f();
assertEquals(0, break_count);
Debug.setListener(listener);
f();
assertEquals(1, break_count);
Debug.setListener(null);
f();
assertEquals(1, break_count);
......@@ -278,6 +278,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK)
.JumpIfFalse(&start);
builder.Debugger();
builder.Return();
// Generate BytecodeArray.
......
......@@ -45,6 +45,7 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
.LoadNamedProperty(reg_1, name, feedback_slot, LanguageMode::SLOPPY)
.StoreAccumulatorInRegister(reg_2)
.CallRuntime(Runtime::kLoadIC_Miss, reg_0, 1)
.Debugger()
.Return();
// Test iterator sees the expected output from the builder.
......@@ -98,6 +99,10 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
CHECK(!iterator.done());
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
CHECK(!iterator.done());
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
CHECK(!iterator.done());
iterator.Advance();
......
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