mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 14:32:49 +00:00
Introduce is_debuggable state bit on function objects
Simplify debugger logic. Any function can be marked as non-debuggable when is is created. The debugger no longer needs a heuristic which functions are debuggable. Mostly used for synthetic, generated functions that have no source code, e.g. async code, implicit getters and setters, implicit constructors, forwarding constructors, dispatcher functions. Review URL: https://codereview.chromium.org//789643006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@42570 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
4dc4caa34d
commit
ab3af6ec00
|
@ -1388,6 +1388,7 @@ void ClassFinalizer::ResolveAndFinalizeMemberTypes(const Class& cls) {
|
|||
cls,
|
||||
field.token_pos()));
|
||||
getter.set_result_type(type);
|
||||
getter.set_is_debuggable(false);
|
||||
cls.AddFunction(getter);
|
||||
field.set_value(Instance::Handle(I, Object::sentinel().raw()));
|
||||
}
|
||||
|
@ -2070,6 +2071,7 @@ void ClassFinalizer::CreateForwardingConstructors(
|
|||
clone.SetNumOptionalParameters(func.NumOptionalParameters(),
|
||||
func.HasOptionalPositionalParameters());
|
||||
clone.set_result_type(dynamic_type);
|
||||
clone.set_is_debuggable(false);
|
||||
|
||||
const intptr_t num_parameters = func.NumParameters();
|
||||
// The cloned ctor shares the parameter names array with the
|
||||
|
|
|
@ -1164,6 +1164,7 @@ RawObject* Compiler::ExecuteOnce(SequenceNode* fragment) {
|
|||
func.SetNumOptionalParameters(0, true);
|
||||
// Manually generated AST, do not recompile.
|
||||
func.SetIsOptimizable(false);
|
||||
func.set_is_debuggable(false);
|
||||
|
||||
// We compile the function here, even though InvokeFunction() below
|
||||
// would compile func automatically. We are checking fewer invariants
|
||||
|
|
|
@ -111,6 +111,7 @@ void SourceBreakpoint::SetResolved(const Function& func, intptr_t token_pos) {
|
|||
ASSERT(func.script() == script_);
|
||||
ASSERT((func.token_pos() <= token_pos) &&
|
||||
(token_pos <= func.end_token_pos()));
|
||||
ASSERT(func.is_debuggable());
|
||||
function_ = func.raw();
|
||||
token_pos_ = token_pos;
|
||||
end_token_pos_ = token_pos;
|
||||
|
@ -1565,12 +1566,12 @@ void Debugger::FindCompiledFunctions(const Script& script,
|
|||
if ((function.token_pos() == start_pos)
|
||||
&& (function.end_token_pos() == end_pos)
|
||||
&& (function.script() == script.raw())) {
|
||||
if (function.HasCode() && !function.IsAsyncFunction()) {
|
||||
if (function.HasCode() && function.is_debuggable()) {
|
||||
function_list->Add(function);
|
||||
}
|
||||
if (function.HasImplicitClosureFunction()) {
|
||||
function = function.ImplicitClosureFunction();
|
||||
if (function.HasCode() && !function.IsAsyncFunction()) {
|
||||
if (function.HasCode() && function.is_debuggable()) {
|
||||
function_list->Add(function);
|
||||
}
|
||||
}
|
||||
|
@ -1586,12 +1587,12 @@ void Debugger::FindCompiledFunctions(const Script& script,
|
|||
if ((function.token_pos() == start_pos)
|
||||
&& (function.end_token_pos() == end_pos)
|
||||
&& (function.script() == script.raw())) {
|
||||
if (function.HasCode() && !function.IsAsyncFunction()) {
|
||||
if (function.HasCode() && function.is_debuggable()) {
|
||||
function_list->Add(function);
|
||||
}
|
||||
if (function.HasImplicitClosureFunction()) {
|
||||
function = function.ImplicitClosureFunction();
|
||||
if (function.HasCode() && !function.IsAsyncFunction()) {
|
||||
if (function.HasCode() && function.is_debuggable()) {
|
||||
function_list->Add(function);
|
||||
}
|
||||
}
|
||||
|
@ -1603,22 +1604,6 @@ void Debugger::FindCompiledFunctions(const Script& script,
|
|||
}
|
||||
|
||||
|
||||
static bool IsDebuggableFunctionKind(const Function& func) {
|
||||
RawFunction::Kind kind = func.kind();
|
||||
if ((kind == RawFunction::kImplicitGetter) ||
|
||||
(kind == RawFunction::kImplicitSetter) ||
|
||||
(kind == RawFunction::kImplicitStaticFinalGetter) ||
|
||||
(kind == RawFunction::kMethodExtractor) ||
|
||||
(kind == RawFunction::kNoSuchMethodDispatcher) ||
|
||||
(kind == RawFunction::kInvokeFieldDispatcher) ||
|
||||
(kind == RawFunction::kIrregexpFunction) ||
|
||||
func.IsImplicitConstructor()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void SelectBestFit(Function* best_fit, Function* func) {
|
||||
if (best_fit->IsNull()) {
|
||||
*best_fit = func->raw();
|
||||
|
@ -1661,7 +1646,7 @@ RawFunction* Debugger::FindBestFit(const Script& script,
|
|||
for (intptr_t pos = 0; pos < num_functions; pos++) {
|
||||
function ^= functions.At(pos);
|
||||
ASSERT(!function.IsNull());
|
||||
if (IsDebuggableFunctionKind(function) &&
|
||||
if (function.is_debuggable() &&
|
||||
FunctionContains(function, script, token_pos)) {
|
||||
SelectBestFit(&best_fit, &function);
|
||||
}
|
||||
|
@ -1674,7 +1659,7 @@ RawFunction* Debugger::FindBestFit(const Script& script,
|
|||
for (intptr_t pos = 0; pos < num_closures; pos++) {
|
||||
function ^= closures.At(pos);
|
||||
ASSERT(!function.IsNull());
|
||||
if (IsDebuggableFunctionKind(function) &&
|
||||
if (function.is_debuggable() &&
|
||||
FunctionContains(function, script, token_pos)) {
|
||||
SelectBestFit(&best_fit, &function);
|
||||
}
|
||||
|
@ -1792,6 +1777,9 @@ RawError* Debugger::OneTimeBreakAtEntry(const Function& target_function) {
|
|||
SourceBreakpoint* Debugger::SetBreakpointAtEntry(
|
||||
const Function& target_function) {
|
||||
ASSERT(!target_function.IsNull());
|
||||
if (!target_function.is_debuggable()) {
|
||||
return NULL;
|
||||
}
|
||||
const Script& script = Script::Handle(target_function.script());
|
||||
return SetBreakpoint(script,
|
||||
target_function.token_pos(),
|
||||
|
@ -2134,7 +2122,7 @@ void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace) {
|
|||
|
||||
// static
|
||||
bool Debugger::IsDebuggable(const Function& func) {
|
||||
if (!IsDebuggableFunctionKind(func)) {
|
||||
if (!func.is_debuggable()) {
|
||||
return false;
|
||||
}
|
||||
if (Service::IsRunning()) {
|
||||
|
@ -2298,7 +2286,8 @@ RawFunction* Debugger::FindInnermostClosure(const Function& function,
|
|||
Function& best_fit = Function::Handle(isolate_);
|
||||
for (intptr_t i = 0; i < num_closures; i++) {
|
||||
closure ^= closures.At(i);
|
||||
if ((function.token_pos() < closure.token_pos()) &&
|
||||
if (closure.is_debuggable() &&
|
||||
(function.token_pos() < closure.token_pos()) &&
|
||||
(closure.end_token_pos() < function.end_token_pos()) &&
|
||||
(closure.token_pos() <= token_pos) &&
|
||||
(token_pos <= closure.end_token_pos()) &&
|
||||
|
@ -2315,6 +2304,12 @@ void Debugger::NotifyCompilation(const Function& func) {
|
|||
// Return with minimal overhead if there are no breakpoints.
|
||||
return;
|
||||
}
|
||||
if (!func.is_debuggable()) {
|
||||
// Nothing to do if the function is not debuggable. If there is
|
||||
// a pending breakpoint in an inner function (that is debuggable),
|
||||
// we'll resolve the breakpoint when the inner function is compiled.
|
||||
return;
|
||||
}
|
||||
// Iterate over all source breakpoints to check whether breakpoints
|
||||
// need to be set in the newly compiled function.
|
||||
Script& script = Script::Handle(isolate_);
|
||||
|
|
|
@ -67,6 +67,7 @@ void MegamorphicCacheTable::InitMissHandler() {
|
|||
false, // Not native.
|
||||
cls,
|
||||
0)); // No token position.
|
||||
function.set_is_debuggable(false);
|
||||
miss_handler_code_ = code.raw();
|
||||
miss_handler_function_ = function.raw();
|
||||
function.AttachCode(code);
|
||||
|
|
|
@ -2669,6 +2669,7 @@ RawFunction* Class::CreateInvocationDispatcher(const String& target_name,
|
|||
invocation.SetParameterNameAt(i, String::Handle(desc.NameAt(index)));
|
||||
}
|
||||
invocation.set_result_type(Type::Handle(Type::DynamicType()));
|
||||
invocation.set_is_debuggable(false);
|
||||
invocation.set_is_visible(false); // Not visible in stack trace.
|
||||
invocation.set_saved_args_desc(args_desc);
|
||||
|
||||
|
@ -6197,6 +6198,7 @@ RawFunction* Function::New(const String& name,
|
|||
result.set_is_external(is_external);
|
||||
result.set_is_native(is_native);
|
||||
result.set_is_visible(true); // Will be computed later.
|
||||
result.set_is_debuggable(true); // Will be computed later.
|
||||
result.set_is_intrinsic(false);
|
||||
result.set_is_redirecting(false);
|
||||
result.set_is_async_closure(false);
|
||||
|
@ -6222,7 +6224,6 @@ RawFunction* Function::New(const String& name,
|
|||
const ClosureData& data = ClosureData::Handle(ClosureData::New());
|
||||
result.set_data(data);
|
||||
}
|
||||
|
||||
return result.raw();
|
||||
}
|
||||
|
||||
|
@ -6297,6 +6298,7 @@ RawFunction* Function::NewEvalFunction(const Class& owner,
|
|||
owner,
|
||||
0));
|
||||
ASSERT(!script.IsNull());
|
||||
result.set_is_debuggable(false);
|
||||
result.set_eval_script(script);
|
||||
return result.raw();
|
||||
}
|
||||
|
|
|
@ -2174,6 +2174,7 @@ class Function : public Object {
|
|||
V(Const, is_const) \
|
||||
V(Abstract, is_abstract) \
|
||||
V(Visible, is_visible) \
|
||||
V(Debuggable, is_debuggable) \
|
||||
V(Optimizable, is_optimizable) \
|
||||
V(Inlinable, is_inlinable) \
|
||||
V(Intrinsic, is_intrinsic) \
|
||||
|
|
|
@ -944,6 +944,7 @@ RawObject* Parser::ParseMetadata(const Class& cls, intptr_t token_pos) {
|
|||
false, // is_native
|
||||
cls,
|
||||
token_pos));
|
||||
fake_function.set_is_debuggable(false);
|
||||
ParsedFunction* parsed_function =
|
||||
new ParsedFunction(isolate, fake_function);
|
||||
Parser parser(script, parsed_function, token_pos);
|
||||
|
@ -1082,6 +1083,7 @@ ParsedFunction* Parser::ParseStaticFieldInitializer(const Field& field) {
|
|||
// and inlining them. After the field is initialized, the
|
||||
// compiler can eliminate the call to the static initializer.
|
||||
initializer.set_is_visible(false);
|
||||
initializer.set_is_debuggable(false);
|
||||
initializer.SetIsOptimizable(false);
|
||||
initializer.set_is_inlinable(false);
|
||||
|
||||
|
@ -1647,6 +1649,7 @@ void Parser::ParseFormalParameter(bool allow_explicit_default_value,
|
|||
current_class(),
|
||||
parameter.name_pos));
|
||||
signature_function.set_result_type(result_type);
|
||||
signature_function.set_is_debuggable(false);
|
||||
AddFormalParamsToFunction(&func_params, signature_function);
|
||||
const String& signature = String::Handle(I,
|
||||
signature_function.Signature());
|
||||
|
@ -3129,8 +3132,12 @@ SequenceNode* Parser::ParseFunc(const Function& func,
|
|||
|
||||
Function& async_closure = Function::ZoneHandle(I);
|
||||
if (func.IsAsyncFunction() && !func.is_async_closure()) {
|
||||
// The code of an async function is synthesized. Disable debugging.
|
||||
func.set_is_debuggable(false);
|
||||
async_closure = OpenAsyncFunction(func.token_pos());
|
||||
} else if (func.is_async_closure()) {
|
||||
// The closure containing the body of an async function is debuggable.
|
||||
ASSERT(func.is_debuggable());
|
||||
OpenAsyncClosure();
|
||||
}
|
||||
|
||||
|
@ -3774,6 +3781,7 @@ void Parser::ParseFieldDefinition(ClassDesc* members, MemberDesc* field) {
|
|||
current_class(),
|
||||
field->name_pos);
|
||||
getter.set_result_type(*field->type);
|
||||
getter.set_is_debuggable(false);
|
||||
members->AddFunction(getter);
|
||||
}
|
||||
}
|
||||
|
@ -3794,6 +3802,7 @@ void Parser::ParseFieldDefinition(ClassDesc* members, MemberDesc* field) {
|
|||
ASSERT(current_class().raw() == getter.Owner());
|
||||
params.AddReceiver(ReceiverType(current_class()), field->name_pos);
|
||||
getter.set_result_type(*field->type);
|
||||
getter.set_is_debuggable(false);
|
||||
AddFormalParamsToFunction(¶ms, getter);
|
||||
members->AddFunction(getter);
|
||||
if (!field->has_final) {
|
||||
|
@ -3815,6 +3824,7 @@ void Parser::ParseFieldDefinition(ClassDesc* members, MemberDesc* field) {
|
|||
&Symbols::Value(),
|
||||
field->type);
|
||||
setter.set_result_type(Type::Handle(I, Type::VoidType()));
|
||||
setter.set_is_debuggable(false);
|
||||
AddFormalParamsToFunction(¶ms, setter);
|
||||
members->AddFunction(setter);
|
||||
}
|
||||
|
@ -4414,6 +4424,7 @@ void Parser::ParseEnumDefinition(const Class& cls) {
|
|||
cls,
|
||||
cls.token_pos());
|
||||
getter.set_result_type(int_type);
|
||||
getter.set_is_debuggable(false);
|
||||
ParamList params;
|
||||
params.AddReceiver(&dynamic_type, cls.token_pos());
|
||||
AddFormalParamsToFunction(¶ms, getter);
|
||||
|
@ -4560,6 +4571,7 @@ void Parser::AddImplicitConstructor(const Class& cls) {
|
|||
cls,
|
||||
cls.token_pos()));
|
||||
ctor.set_end_token_pos(ctor.token_pos());
|
||||
ctor.set_is_debuggable(false);
|
||||
if (library_.is_dart_scheme() && library_.IsPrivate(ctor_name)) {
|
||||
ctor.set_is_visible(false);
|
||||
}
|
||||
|
@ -4796,6 +4808,7 @@ void Parser::ParseTypedef(const GrowableObjectArray& pending_classes,
|
|||
function_type_alias,
|
||||
alias_name_pos));
|
||||
signature_function.set_result_type(result_type);
|
||||
signature_function.set_is_debuggable(false);
|
||||
AddFormalParamsToFunction(&func_params, signature_function);
|
||||
|
||||
// Patch the signature function in the signature class.
|
||||
|
@ -5137,6 +5150,7 @@ void Parser::ParseTopLevelVariable(TopLevel* top_level,
|
|||
current_class(),
|
||||
name_pos);
|
||||
getter.set_result_type(type);
|
||||
getter.set_is_debuggable(false);
|
||||
top_level->functions.Add(getter);
|
||||
}
|
||||
} else if (is_final) {
|
||||
|
@ -5259,8 +5273,11 @@ void Parser::ParseTopLevelFunction(TopLevel* top_level,
|
|||
func.set_result_type(result_type);
|
||||
func.set_end_token_pos(function_end_pos);
|
||||
func.set_modifier(func_modifier);
|
||||
if (is_native && library_.is_dart_scheme() && library_.IsPrivate(func_name)) {
|
||||
func.set_is_visible(false);
|
||||
if (is_native) {
|
||||
func.set_is_debuggable(false);
|
||||
if (library_.is_dart_scheme() && library_.IsPrivate(func_name)) {
|
||||
func.set_is_visible(false);
|
||||
}
|
||||
}
|
||||
AddFormalParamsToFunction(¶ms, func);
|
||||
top_level->functions.Add(func);
|
||||
|
@ -5399,9 +5416,11 @@ void Parser::ParseTopLevelAccessor(TopLevel* top_level,
|
|||
func.set_result_type(result_type);
|
||||
func.set_end_token_pos(accessor_end_pos);
|
||||
func.set_modifier(func_modifier);
|
||||
if (is_native && library_.is_dart_scheme() &&
|
||||
library_.IsPrivate(accessor_name)) {
|
||||
func.set_is_visible(false);
|
||||
if (is_native) {
|
||||
func.set_is_debuggable(false);
|
||||
if (library_.is_dart_scheme() && library_.IsPrivate(accessor_name)) {
|
||||
func.set_is_visible(false);
|
||||
}
|
||||
}
|
||||
AddFormalParamsToFunction(¶ms, func);
|
||||
top_level->functions.Add(func);
|
||||
|
|
|
@ -5128,6 +5128,7 @@ static void CreateSpecializedFunction(Isolate* isolate,
|
|||
|
||||
fn.set_regexp(regexp);
|
||||
fn.set_regexp_cid(specialization_cid);
|
||||
fn.set_is_debuggable(false);
|
||||
|
||||
// The function is compiled lazily during the first call.
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ static RawFunction* CreateMethodExtractor(const String& getter_name,
|
|||
extractor.set_result_type(Type::Handle(Type::DynamicType()));
|
||||
|
||||
extractor.set_extracted_method_closure(closure_function);
|
||||
extractor.set_is_debuggable(false);
|
||||
|
||||
owner.AddFunction(extractor);
|
||||
|
||||
|
|
Loading…
Reference in a new issue