Chromium Code Reviews| Index: src/runtime/runtime-debug.cc |
| diff --git a/src/runtime/runtime-debug.cc b/src/runtime/runtime-debug.cc |
| index dcdffb748051a55f51d983823b21f8af7c34a9fc..c9137b317cf2b156271d6d23acac5b1373af8193 100644 |
| --- a/src/runtime/runtime-debug.cc |
| +++ b/src/runtime/runtime-debug.cc |
| @@ -14,6 +14,7 @@ |
| #include "src/interpreter/interpreter.h" |
| #include "src/isolate-inl.h" |
| #include "src/runtime/runtime.h" |
| +#include "src/wasm/wasm-module.h" |
| namespace v8 { |
| namespace internal { |
| @@ -453,12 +454,16 @@ RUNTIME_FUNCTION(Runtime_GetFrameCount) { |
| return Smi::FromInt(0); |
| } |
| - for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) { |
| + for (StackTraceFrameIterator it(isolate, id); !it.done(); it.Advance()) { |
| List<FrameSummary> frames(FLAG_max_inlining_levels + 1); |
| - it.frame()->Summarize(&frames); |
| - for (int i = frames.length() - 1; i >= 0; i--) { |
| - // Omit functions from native and extension scripts. |
| - if (frames[i].function()->shared()->IsSubjectToDebugging()) n++; |
| + if (it.is_wasm()) { |
| + n++; |
| + } else { |
| + it.javascript_frame()->Summarize(&frames); |
| + for (int i = frames.length() - 1; i >= 0; i--) { |
| + // Omit functions from native and extension scripts. |
| + if (frames[i].function()->shared()->IsSubjectToDebugging()) n++; |
| + } |
| } |
| } |
| return Smi::FromInt(n); |
| @@ -468,14 +473,14 @@ RUNTIME_FUNCTION(Runtime_GetFrameCount) { |
| static const int kFrameDetailsFrameIdIndex = 0; |
| static const int kFrameDetailsReceiverIndex = 1; |
| static const int kFrameDetailsFunctionIndex = 2; |
| -static const int kFrameDetailsArgumentCountIndex = 3; |
| -static const int kFrameDetailsLocalCountIndex = 4; |
| -static const int kFrameDetailsSourcePositionIndex = 5; |
| -static const int kFrameDetailsConstructCallIndex = 6; |
| -static const int kFrameDetailsAtReturnIndex = 7; |
| -static const int kFrameDetailsFlagsIndex = 8; |
| -static const int kFrameDetailsFirstDynamicIndex = 9; |
| - |
| +static const int kFrameDetailsScriptIndex = 3; |
| +static const int kFrameDetailsArgumentCountIndex = 4; |
| +static const int kFrameDetailsLocalCountIndex = 5; |
| +static const int kFrameDetailsSourcePositionIndex = 6; |
| +static const int kFrameDetailsConstructCallIndex = 7; |
| +static const int kFrameDetailsAtReturnIndex = 8; |
| +static const int kFrameDetailsFlagsIndex = 9; |
| +static const int kFrameDetailsFirstDynamicIndex = 10; |
| // Return an array with frame details |
| // args[0]: number: break id |
| @@ -485,12 +490,13 @@ static const int kFrameDetailsFirstDynamicIndex = 9; |
| // 0: Frame id |
| // 1: Receiver |
| // 2: Function |
| -// 3: Argument count |
| -// 4: Local count |
| -// 5: Source position |
| -// 6: Constructor call |
| -// 7: Is at return |
| -// 8: Flags |
| +// 3: Script |
| +// 4: Argument count |
| +// 5: Local count |
| +// 6: Source position |
| +// 7: Constructor call |
| +// 8: Is at return |
| +// 9: Flags |
| // Arguments name, value |
| // Locals name, value |
| // Return value if any |
| @@ -510,7 +516,7 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { |
| return heap->undefined_value(); |
| } |
| - JavaScriptFrameIterator it(isolate, id); |
| + StackTraceFrameIterator it(isolate, id); |
| // Inlined frame index in optimized frame, starting from outer function. |
| int inlined_jsframe_index = |
| DebugFrameHelper::FindIndexedNonNativeFrame(&it, index); |
| @@ -534,61 +540,67 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { |
| // Check for constructor frame. |
| bool constructor = frame_inspector.IsConstructor(); |
| - // Get scope info and read from it for local variable information. |
| - Handle<JSFunction> function = |
| - Handle<JSFunction>::cast(frame_inspector.GetFunction()); |
| - RUNTIME_ASSERT(function->shared()->IsSubjectToDebugging()); |
| - Handle<SharedFunctionInfo> shared(function->shared()); |
| - Handle<ScopeInfo> scope_info(shared->scope_info()); |
| - DCHECK(*scope_info != ScopeInfo::Empty(isolate)); |
| + Handle<ScopeInfo> scope_info; |
| // Get the locals names and values into a temporary array. |
| - int local_count = scope_info->LocalCount(); |
| - for (int slot = 0; slot < scope_info->LocalCount(); ++slot) { |
| - // Hide compiler-introduced temporary variables, whether on the stack or on |
| - // the context. |
| - if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(slot))) { |
| - local_count--; |
| + Handle<FixedArray> locals; |
|
Yang
2016/06/24 05:56:37
Can we re-organize this file like this?
if (it.is
Clemens Hammacher
2016/06/24 09:23:31
Done.
|
| + if (it.is_wasm()) { |
| + // TODO(clemensh): add names and values of local variables. |
| + locals = isolate->factory()->NewFixedArray(0); |
| + } else { |
| + // Get scope info and read from it for local variable information. |
| + SharedFunctionInfo* shared = frame_inspector.GetFunction()->shared(); |
| + RUNTIME_ASSERT(shared->IsSubjectToDebugging()); |
| + scope_info = handle(shared->scope_info(), isolate); |
| + DCHECK(*scope_info != ScopeInfo::Empty(isolate)); |
| + |
| + int local_count = scope_info->LocalCount(); |
| + for (int slot = 0; slot < scope_info->LocalCount(); ++slot) { |
| + // Hide compiler-introduced temporary variables, whether on the stack or |
| + // on the context. |
| + if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(slot))) { |
| + local_count--; |
| + } |
| } |
| - } |
| - Handle<FixedArray> locals = |
| - isolate->factory()->NewFixedArray(local_count * 2); |
| - |
| - // Fill in the values of the locals. |
| - int local = 0; |
| - int i = 0; |
| - for (; i < scope_info->StackLocalCount(); ++i) { |
| - // Use the value from the stack. |
| - if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(i))) continue; |
| - locals->set(local * 2, scope_info->LocalName(i)); |
| - Handle<Object> value = |
| - frame_inspector.GetExpression(scope_info->StackLocalIndex(i)); |
| - // TODO(yangguo): We convert optimized out values to {undefined} when they |
| - // are passed to the debugger. Eventually we should handle them somehow. |
| - if (value->IsOptimizedOut(isolate)) { |
| - value = isolate->factory()->undefined_value(); |
| - } |
| - locals->set(local * 2 + 1, *value); |
| - local++; |
| - } |
| - if (local < local_count) { |
| - // Get the context containing declarations. |
| - Handle<Context> context( |
| - Handle<Context>::cast(frame_inspector.GetContext())->closure_context()); |
| - for (; i < scope_info->LocalCount(); ++i) { |
| - Handle<String> name(scope_info->LocalName(i)); |
| - if (ScopeInfo::VariableIsSynthetic(*name)) continue; |
| - VariableMode mode; |
| - InitializationFlag init_flag; |
| - MaybeAssignedFlag maybe_assigned_flag; |
| - locals->set(local * 2, *name); |
| - int context_slot_index = ScopeInfo::ContextSlotIndex( |
| - scope_info, name, &mode, &init_flag, &maybe_assigned_flag); |
| - Object* value = context->get(context_slot_index); |
| - locals->set(local * 2 + 1, value); |
| + locals = isolate->factory()->NewFixedArray(local_count * 2); |
| + |
| + // Fill in the values of the locals. |
| + int local = 0; |
| + int i = 0; |
| + for (; i < scope_info->StackLocalCount(); ++i) { |
| + // Use the value from the stack. |
| + if (ScopeInfo::VariableIsSynthetic(scope_info->LocalName(i))) continue; |
| + locals->set(local * 2, scope_info->LocalName(i)); |
| + Handle<Object> value = |
| + frame_inspector.GetExpression(scope_info->StackLocalIndex(i)); |
| + // TODO(yangguo): We convert optimized out values to {undefined} when they |
| + // are passed to the debugger. Eventually we should handle them somehow. |
| + if (value->IsOptimizedOut(isolate)) { |
| + value = isolate->factory()->undefined_value(); |
| + } |
| + locals->set(local * 2 + 1, *value); |
| local++; |
| } |
| + if (local < local_count) { |
| + // Get the context containing declarations. |
| + Handle<Context> context( |
| + Handle<Context>::cast(frame_inspector.GetContext()) |
| + ->closure_context()); |
| + for (; i < scope_info->LocalCount(); ++i) { |
| + Handle<String> name(scope_info->LocalName(i)); |
| + if (ScopeInfo::VariableIsSynthetic(*name)) continue; |
| + VariableMode mode; |
| + InitializationFlag init_flag; |
| + MaybeAssignedFlag maybe_assigned_flag; |
| + locals->set(local * 2, *name); |
| + int context_slot_index = ScopeInfo::ContextSlotIndex( |
| + scope_info, name, &mode, &init_flag, &maybe_assigned_flag); |
| + Object* value = context->get(context_slot_index); |
| + locals->set(local * 2 + 1, value); |
| + local++; |
| + } |
| + } |
| } |
| // Check whether this frame is positioned at return. If not top |
| @@ -609,34 +621,50 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { |
| // the provided parameters whereas the function frame always have the number |
| // of arguments matching the functions parameters. The rest of the |
| // information (except for what is collected above) is the same. |
| - if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) { |
| + if ((inlined_jsframe_index == 0) && it.frame()->is_java_script() && |
| + it.javascript_frame()->has_adapted_arguments()) { |
| it.AdvanceToArgumentsFrame(); |
| frame_inspector.SetArgumentsFrame(it.frame()); |
| } |
| // Find the number of arguments to fill. At least fill the number of |
| // parameters for the function and fill more if more parameters are provided. |
| - int argument_count = scope_info->ParameterCount(); |
| - if (argument_count < frame_inspector.GetParametersCount()) { |
| - argument_count = frame_inspector.GetParametersCount(); |
| + int argument_count = frame_inspector.GetParametersCount(); |
| + if (!it.is_wasm()) { |
| + int scope_param_count = scope_info->ParameterCount(); |
| + if (scope_param_count > argument_count) argument_count = scope_param_count; |
| } |
| // Calculate the size of the result. |
| - int details_size = kFrameDetailsFirstDynamicIndex + |
| - 2 * (argument_count + local_count) + (at_return ? 1 : 0); |
| + int details_size = kFrameDetailsFirstDynamicIndex + 2 * argument_count + |
| + locals->length() + (at_return ? 1 : 0); |
| Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size); |
| // Add the frame id. |
| details->set(kFrameDetailsFrameIdIndex, *frame_id); |
| // Add the function (same as in function frame). |
| - details->set(kFrameDetailsFunctionIndex, *(frame_inspector.GetFunction())); |
| + if (it.is_wasm()) { |
| + Handle<Object> wasm_obj(it.wasm_frame()->wasm_obj(), isolate); |
| + int func_index = it.wasm_frame()->function_index(); |
| + Handle<String> func_name = |
| + wasm::GetWasmFunctionName(isolate, wasm_obj, func_index); |
| + details->set(kFrameDetailsFunctionIndex, *func_name); |
| + } else { |
| + details->set(kFrameDetailsFunctionIndex, *frame_inspector.GetFunction()); |
| + } |
| + |
| + // Add the script wrapper |
| + Handle<Object> script_wrapper = |
| + Script::GetWrapper(frame_inspector.GetScript()); |
| + details->set(kFrameDetailsScriptIndex, *script_wrapper); |
| // Add the arguments count. |
| details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count)); |
| // Add the locals count |
| - details->set(kFrameDetailsLocalCountIndex, Smi::FromInt(local_count)); |
| + details->set(kFrameDetailsLocalCountIndex, |
| + Smi::FromInt(locals->length() / 2)); |
| // Add the source position. |
| if (position != RelocInfo::kNoPosition) { |
| @@ -669,25 +697,21 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { |
| int details_index = kFrameDetailsFirstDynamicIndex; |
| // Add arguments name and value. |
| - for (int i = 0; i < argument_count; i++) { |
| + for (int i = 0; i < argument_count; i++, details_index += 2) { |
| // Name of the argument. |
| - if (i < scope_info->ParameterCount()) { |
| - details->set(details_index++, scope_info->ParameterName(i)); |
| - } else { |
| - details->set(details_index++, heap->undefined_value()); |
| + if (!scope_info.is_null() && i < scope_info->ParameterCount()) { |
| + details->set(details_index, scope_info->ParameterName(i)); |
| } |
| // Parameter value. |
| if (i < frame_inspector.GetParametersCount()) { |
| // Get the value from the stack. |
| - details->set(details_index++, *(frame_inspector.GetParameter(i))); |
| - } else { |
| - details->set(details_index++, heap->undefined_value()); |
| + details->set(details_index + 1, *frame_inspector.GetParameter(i)); |
| } |
| } |
| // Add locals name and value from the temporary copy from the function frame. |
| - for (int i = 0; i < local_count * 2; i++) { |
| + for (int i = 0, l = locals->length(); i < l; ++i) { |
| details->set(details_index++, locals->get(i)); |
| } |
| @@ -698,8 +722,11 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { |
| // Add the receiver (same as in function frame). |
| Handle<Object> receiver(it.frame()->receiver(), isolate); |
| - DCHECK(!function->shared()->IsBuiltin()); |
| - DCHECK_IMPLIES(is_sloppy(shared->language_mode()), receiver->IsJSReceiver()); |
| + DCHECK(it.is_wasm() || !frame_inspector.GetFunction()->shared()->IsBuiltin()); |
| + DCHECK_IMPLIES( |
| + !it.is_wasm() && |
| + is_sloppy(frame_inspector.GetFunction()->shared()->language_mode()), |
| + receiver->IsJSReceiver()); |
| details->set(kFrameDetailsReceiverIndex, *receiver); |
| DCHECK_EQ(details_size, details_index); |
| @@ -795,8 +822,8 @@ RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) { |
| // Get the frame where the debugging is performed. |
| StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); |
| - JavaScriptFrameIterator frame_it(isolate, id); |
| - JavaScriptFrame* frame = frame_it.frame(); |
| + StackTraceFrameIterator frame_it(isolate, id); |
| + StandardFrame* frame = frame_it.frame(); |
|
Yang
2016/06/24 05:56:37
We need to return an empty array if the frame is n
Clemens Hammacher
2016/06/24 09:23:31
This happens implicitely, as the ScopeIterator wil
Yang
2016/06/24 10:02:57
It will be empty because of the check in ScopeIter
Clemens Hammacher
2016/06/24 10:45:42
The check is in debug-scopes.cc:25:
if (!frame_ins
Yang
2016/06/24 10:52:25
I see. Can we at least add an assertion in ScopeIt
Clemens Hammacher
2016/06/24 15:11:58
Done.
|
| FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate); |
| List<Handle<JSObject> > result(4); |
| @@ -1555,8 +1582,10 @@ static Handle<Object> GetJSPositionInfo(Handle<Script> script, int position, |
| } |
| Handle<String> source = handle(String::cast(script->source()), isolate); |
| - Handle<String> sourceText = |
| - isolate->factory()->NewSubString(source, info.line_start, info.line_end); |
| + Handle<String> sourceText = info.line_end > source->length() |
|
Yang
2016/06/24 05:56:37
can we do a script->is_wasm check instead?
Clemens Hammacher
2016/06/24 09:23:31
Done.
|
| + ? isolate->factory()->empty_string() |
| + : isolate->factory()->NewSubString( |
| + source, info.line_start, info.line_end); |
| Handle<JSObject> jsinfo = |
| isolate->factory()->NewJSObject(isolate->object_function()); |