[debug] fix break for builtin constructors with regular construct stub.
Regular construct stubs eventually call InvokeFunction, which does performs debug hook checking. For builtins such as Object, Array, etc. this approach does not work since they have specialized construct stubs that do not check for the debug hook. R=bmeurer@chromium.org Bug: v8:178 Change-Id: I3e1f5d2dae1c7a6220b7236bd6ea71d83a65171f Reviewed-on: https://chromium-review.googlesource.com/931702 Reviewed-by: Sigurd Schneider <sigurds@chromium.org> Commit-Queue: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#51503}
This commit is contained in:
parent
3856d8d57d
commit
0b9b48b59d
@ -3468,6 +3468,9 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
|
||||
if (m.Value()->IsJSFunction()) {
|
||||
Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
|
||||
|
||||
// Do not reduce constructors with break points.
|
||||
if (function->shared()->HasBreakInfo()) return NoChange();
|
||||
|
||||
// Don't inline cross native context.
|
||||
if (function->native_context() != *native_context()) return NoChange();
|
||||
|
||||
|
@ -1197,15 +1197,16 @@ TEST(BreakPointReturn) {
|
||||
TEST(BreakPointBuiltin) {
|
||||
i::FLAG_allow_natives_syntax = true;
|
||||
i::FLAG_block_concurrent_recompilation = true;
|
||||
break_point_hit_count = 0;
|
||||
i::FLAG_experimental_inline_promise_constructor = true;
|
||||
DebugLocalContext env;
|
||||
v8::HandleScope scope(env->GetIsolate());
|
||||
|
||||
SetDebugEventListener(env->GetIsolate(), DebugEventBreakPointHitCount);
|
||||
v8::Local<v8::Function> builtin =
|
||||
CompileRun("String.prototype.repeat").As<v8::Function>();
|
||||
|
||||
// === Test simple builtin ===
|
||||
break_point_hit_count = 0;
|
||||
v8::Local<v8::Function> builtin =
|
||||
CompileRun("String.prototype.repeat").As<v8::Function>();
|
||||
CompileRun("'a'.repeat(10)");
|
||||
CHECK_EQ(0, break_point_hit_count);
|
||||
|
||||
@ -1219,6 +1220,41 @@ TEST(BreakPointBuiltin) {
|
||||
CompileRun("'b'.repeat(10)");
|
||||
CHECK_EQ(1, break_point_hit_count);
|
||||
|
||||
// === Test bound function from a builtin ===
|
||||
break_point_hit_count = 0;
|
||||
builtin = CompileRun(
|
||||
"var boundrepeat = String.prototype.repeat.bind('a');"
|
||||
"String.prototype.repeat")
|
||||
.As<v8::Function>();
|
||||
CompileRun("boundrepeat(10)");
|
||||
CHECK_EQ(0, break_point_hit_count);
|
||||
|
||||
// Run with breakpoint.
|
||||
bp = SetBreakPoint(builtin, 0);
|
||||
CompileRun("boundrepeat(10)");
|
||||
CHECK_EQ(1, break_point_hit_count);
|
||||
|
||||
// Run without breakpoints.
|
||||
ClearBreakPoint(bp);
|
||||
CompileRun("boundrepeat(10)");
|
||||
CHECK_EQ(1, break_point_hit_count);
|
||||
|
||||
// === Test constructor builtin (for ones with normal construct stubs) ===
|
||||
break_point_hit_count = 0;
|
||||
builtin = CompileRun("Promise").As<v8::Function>();
|
||||
CompileRun("new Promise(()=>{})");
|
||||
CHECK_EQ(0, break_point_hit_count);
|
||||
|
||||
// Run with breakpoint.
|
||||
bp = SetBreakPoint(builtin, 0);
|
||||
CompileRun("new Promise(()=>{})");
|
||||
CHECK_EQ(1, break_point_hit_count);
|
||||
|
||||
// Run without breakpoints.
|
||||
ClearBreakPoint(bp);
|
||||
CompileRun("new Promise(()=>{})");
|
||||
CHECK_EQ(1, break_point_hit_count);
|
||||
|
||||
// === Test inlined builtin ===
|
||||
break_point_hit_count = 0;
|
||||
builtin = CompileRun("Math.sin").As<v8::Function>();
|
||||
@ -1245,6 +1281,58 @@ TEST(BreakPointBuiltin) {
|
||||
CompileRun("test(0.3);");
|
||||
CHECK_EQ(3, break_point_hit_count);
|
||||
|
||||
// === Test inlined bound builtin ===
|
||||
break_point_hit_count = 0;
|
||||
builtin = CompileRun("String.prototype.repeat").As<v8::Function>();
|
||||
CompileRun("function test(x) { return 'a' + boundrepeat(x) }");
|
||||
CompileRun(
|
||||
"test(4); test(5);"
|
||||
"%OptimizeFunctionOnNextCall(test); test(6);");
|
||||
CHECK_EQ(0, break_point_hit_count);
|
||||
|
||||
// Run with breakpoint.
|
||||
bp = SetBreakPoint(builtin, 0);
|
||||
CompileRun("'a'.repeat(2);");
|
||||
CHECK_EQ(1, break_point_hit_count);
|
||||
CompileRun("test(7);");
|
||||
CHECK_EQ(2, break_point_hit_count);
|
||||
|
||||
// Re-optimize.
|
||||
CompileRun("%OptimizeFunctionOnNextCall(test);");
|
||||
CompileRun("test(8);");
|
||||
CHECK_EQ(3, break_point_hit_count);
|
||||
|
||||
// Run without breakpoints.
|
||||
ClearBreakPoint(bp);
|
||||
CompileRun("test(9);");
|
||||
CHECK_EQ(3, break_point_hit_count);
|
||||
|
||||
// === Test inlined constructor builtin (regular construct builtin) ===
|
||||
break_point_hit_count = 0;
|
||||
builtin = CompileRun("Promise").As<v8::Function>();
|
||||
CompileRun("function test(x) { return new Promise(()=>x); }");
|
||||
CompileRun(
|
||||
"test(4); test(5);"
|
||||
"%OptimizeFunctionOnNextCall(test); test(6);");
|
||||
CHECK_EQ(0, break_point_hit_count);
|
||||
|
||||
// Run with breakpoint.
|
||||
bp = SetBreakPoint(builtin, 0);
|
||||
CompileRun("new Promise();");
|
||||
CHECK_EQ(1, break_point_hit_count);
|
||||
CompileRun("test(7);");
|
||||
CHECK_EQ(2, break_point_hit_count);
|
||||
|
||||
// Re-optimize.
|
||||
CompileRun("%OptimizeFunctionOnNextCall(test);");
|
||||
CompileRun("test(8);");
|
||||
CHECK_EQ(3, break_point_hit_count);
|
||||
|
||||
// Run without breakpoints.
|
||||
ClearBreakPoint(bp);
|
||||
CompileRun("test(9);");
|
||||
CHECK_EQ(3, break_point_hit_count);
|
||||
|
||||
// === Test concurrent optimization ===
|
||||
break_point_hit_count = 0;
|
||||
builtin = CompileRun("Math.sin").As<v8::Function>();
|
||||
|
Loading…
Reference in New Issue
Block a user