[wasm][debug] Compile source only once for Debug-Evaluate.

We accidentally compiled the source for Debug-Evaluate on Wasm frames
twice, and used the first script result as outer function info for the
second, actual compile (which goes via the `eval` machinery).

Also unify DebugEvaluate::Local and DebugEvaluate::WebAssembly, since
they are essentially very similar, except for the context.

Bug: chromium:1127914
Change-Id: I8eb85c128c05ab1d4fcb73061de89b0942d1e5c8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2605198
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71890}
This commit is contained in:
Benedikt Meurer 2020-12-29 10:03:46 +01:00 committed by Commit Bot
parent cbed76b711
commit 6f6a540456
3 changed files with 36 additions and 71 deletions

View File

@ -78,58 +78,37 @@ MaybeHandle<Object> DebugEvaluate::Local(Isolate* isolate,
// Get the frame where the debugging is performed.
StackTraceFrameIterator it(isolate, frame_id);
if (!it.is_javascript()) return isolate->factory()->undefined_value();
JavaScriptFrame* frame = it.javascript_frame();
if (it.is_javascript()) {
JavaScriptFrame* frame = it.javascript_frame();
// This is not a lot different than DebugEvaluate::Global, except that
// variables accessible by the function we are evaluating from are
// materialized and included on top of the native context. Changes to
// the materialized object are written back afterwards.
// Note that the native context is taken from the original context chain,
// which may not be the current native context of the isolate.
ContextBuilder context_builder(isolate, frame, inlined_jsframe_index);
if (isolate->has_pending_exception()) return {};
// This is not a lot different than DebugEvaluate::Global, except that
// variables accessible by the function we are evaluating from are
// materialized and included on top of the native context. Changes to
// the materialized object are written back afterwards.
// Note that the native context is taken from the original context chain,
// which may not be the current native context of the isolate.
ContextBuilder context_builder(isolate, frame, inlined_jsframe_index);
if (isolate->has_pending_exception()) return MaybeHandle<Object>();
Handle<Context> context = context_builder.evaluation_context();
Handle<JSObject> receiver(context->global_proxy(), isolate);
MaybeHandle<Object> maybe_result =
Evaluate(isolate, context_builder.outer_info(), context, receiver, source,
throw_on_side_effect);
if (!maybe_result.is_null()) context_builder.UpdateValues();
return maybe_result;
}
V8_EXPORT MaybeHandle<Object> DebugEvaluate::WebAssembly(
Handle<WasmInstanceObject> instance, StackFrameId frame_id,
Handle<String> source, bool throw_on_side_effect) {
Isolate* isolate = instance->GetIsolate();
StackTraceFrameIterator it(isolate, frame_id);
if (!it.is_wasm()) return isolate->factory()->undefined_value();
WasmFrame* frame = WasmFrame::cast(it.frame());
Handle<JSProxy> context_extension = WasmJs::GetJSDebugProxy(frame);
DisableBreak disable_break_scope(isolate->debug(), /*disable=*/true);
Handle<SharedFunctionInfo> shared_info;
if (!GetFunctionInfo(isolate, source, REPLMode::kNo).ToHandle(&shared_info)) {
return {};
Handle<Context> context = context_builder.evaluation_context();
Handle<JSObject> receiver(context->global_proxy(), isolate);
MaybeHandle<Object> maybe_result =
Evaluate(isolate, context_builder.outer_info(), context, receiver,
source, throw_on_side_effect);
if (!maybe_result.is_null()) context_builder.UpdateValues();
return maybe_result;
} else {
CHECK(it.is_wasm());
WasmFrame* frame = WasmFrame::cast(it.frame());
Handle<SharedFunctionInfo> outer_info(
isolate->native_context()->empty_function().shared(), isolate);
Handle<JSProxy> context_extension = WasmJs::GetJSDebugProxy(frame);
Handle<ScopeInfo> scope_info =
ScopeInfo::CreateForWithScope(isolate, Handle<ScopeInfo>::null());
Handle<Context> context = isolate->factory()->NewWithContext(
isolate->native_context(), scope_info, context_extension);
return Evaluate(isolate, outer_info, context, context_extension, source,
throw_on_side_effect);
}
Handle<ScopeInfo> scope_info =
ScopeInfo::CreateForWithScope(isolate, Handle<ScopeInfo>::null());
Handle<Context> context = isolate->factory()->NewWithContext(
isolate->native_context(), scope_info, context_extension);
Handle<Object> result;
if (!DebugEvaluate::Evaluate(isolate, shared_info, context, context_extension,
source, throw_on_side_effect)
.ToHandle(&result)) {
return {};
}
return result;
}
MaybeHandle<Object> DebugEvaluate::WithTopmostArguments(Isolate* isolate,

View File

@ -32,15 +32,14 @@ class DebugEvaluate : public AllStatic {
// - Parameters and stack-allocated locals need to be materialized. Altered
// values need to be written back to the stack afterwards.
// - The arguments object needs to materialized.
// The stack frame can be either a JavaScript stack frame or a Wasm
// stack frame. In the latter case, a special Debug Proxy API is
// provided to peek into the Wasm state.
static MaybeHandle<Object> Local(Isolate* isolate, StackFrameId frame_id,
int inlined_jsframe_index,
Handle<String> source,
bool throw_on_side_effect);
static V8_EXPORT MaybeHandle<Object> WebAssembly(
Handle<WasmInstanceObject> instance, StackFrameId frame_id,
Handle<String> source, bool throw_on_side_effect);
// This is used for break-at-entry for builtins and API functions.
// Evaluate a piece of JavaScript in the native context, but with the
// materialized arguments object and receiver of the current call.

View File

@ -178,23 +178,10 @@ v8::MaybeLocal<v8::Value> DebugStackTraceIterator::Evaluate(
Handle<Object> value;
i::SafeForInterruptsScope safe_for_interrupt_scope(isolate_);
bool success = false;
if (iterator_.is_wasm()) {
FrameSummary summary = FrameSummary::Get(iterator_.frame(), 0);
const FrameSummary::WasmFrameSummary& wasmSummary = summary.AsWasm();
Handle<WasmInstanceObject> instance = wasmSummary.wasm_instance();
success = DebugEvaluate::WebAssembly(instance, iterator_.frame()->id(),
Utils::OpenHandle(*source),
throw_on_side_effect)
.ToHandle(&value);
} else {
success = DebugEvaluate::Local(
isolate_, iterator_.frame()->id(), inlined_frame_index_,
Utils::OpenHandle(*source), throw_on_side_effect)
.ToHandle(&value);
}
if (!success) {
if (!DebugEvaluate::Local(isolate_, iterator_.frame()->id(),
inlined_frame_index_, Utils::OpenHandle(*source),
throw_on_side_effect)
.ToHandle(&value)) {
isolate_->OptionalRescheduleException(false);
return v8::MaybeLocal<v8::Value>();
}