From 80b98da2cda6d0225798cec4213d842811d20df3 Mon Sep 17 00:00:00 2001 From: mstarzinger Date: Wed, 8 Jun 2016 00:07:20 -0700 Subject: [PATCH] [compiler] Improve contract for Compiler::CompileDebugCode. This changes the contract for the aforementioned API function to be more permissive and allow callers to call it with less restrictions. The new contract is: a) For so far un-compiled functions, the compiler is free to choose the backend according to other decision criteria. Debug code can hence be provided by either Ignition or FullCodegen. b) For compiled functions, the compiler will provide debug code within the same tier as existing code. For Ignition the generated code will be equivalent to the old one. For FullCodegen the code will contain debug information and debug break slots. Concretely this fixes an issue where generator or async functions might have been compiled with an unexpected backend, due to the fact that the API method in question was always providing FullCodegen code. R=yangguo@chromium.org Review-Url: https://codereview.chromium.org/2044063002 Cr-Commit-Position: refs/heads/master@{#36808} --- src/compiler.cc | 16 +++++++++++++++- src/debug/liveedit.cc | 26 ++++++++++++-------------- src/debug/liveedit.h | 4 ++-- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/compiler.cc b/src/compiler.cc index 9ed86dd382..445c46e2e0 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -433,7 +433,15 @@ void EnsureFeedbackMetadata(CompilationInfo* info) { } bool UseIgnition(CompilationInfo* info) { - if (info->is_debug()) return false; + DCHECK(info->has_shared_info()); + + // When requesting debug code as a replacement for existing code, we provide + // the same kind as the existing code (to prevent implicit tier-change). + if (info->is_debug() && info->shared_info()->is_compiled()) { + return info->shared_info()->HasBytecodeArray(); + } + + // For generator or async functions we might avoid Ignition wholesale. if (info->shared_info()->is_resumable() && !FLAG_ignition_generators) { return false; } @@ -509,6 +517,12 @@ void InstallSharedScopeInfo(CompilationInfo* info, void InstallSharedCompilationResult(CompilationInfo* info, Handle shared) { + // TODO(mstarzinger): Compiling for debug code might be used to reveal inner + // functions via {FindSharedFunctionInfoInScript}, in which case we end up + // regenerating existing bytecode. Fix this! + if (info->is_debug() && info->has_bytecode_array()) { + shared->ClearBytecodeArray(); + } // Assert that we are not overwriting (possibly patched) debug code. DCHECK(!shared->HasDebugInfo()); DCHECK(!info->code().is_null()); diff --git a/src/debug/liveedit.cc b/src/debug/liveedit.cc index e9c373e95b..39db3dbcca 100644 --- a/src/debug/liveedit.cc +++ b/src/debug/liveedit.cc @@ -621,11 +621,9 @@ void FunctionInfoWrapper::SetInitialProperties(Handle name, this->SetSmiValueField(kParentIndexOffset_, parent_index); } - -void FunctionInfoWrapper::SetFunctionCode(Handle function_code, +void FunctionInfoWrapper::SetFunctionCode(Handle function_code, Handle code_scope_info) { // CompileForLiveEdit must deliver full-codegen code. - DCHECK(function_code->kind() == Code::FUNCTION); Handle code_wrapper = WrapInJSValue(function_code); this->SetField(kCodeOffset_, code_wrapper); @@ -640,13 +638,12 @@ void FunctionInfoWrapper::SetSharedFunctionInfo( this->SetField(kSharedFunctionInfoOffset_, info_holder); } - -Handle FunctionInfoWrapper::GetFunctionCode() { +Handle FunctionInfoWrapper::GetFunctionCode() { Handle element = this->GetField(kCodeOffset_); Handle value_wrapper = Handle::cast(element); Handle raw_result = UnwrapJSValue(value_wrapper); - CHECK(raw_result->IsCode()); - return Handle::cast(raw_result); + CHECK(raw_result->IsAbstractCode()); + return Handle::cast(raw_result); } MaybeHandle FunctionInfoWrapper::GetFeedbackMetadata() { @@ -1012,16 +1009,17 @@ void LiveEdit::ReplaceFunctionCode( bool feedback_metadata_changed = false; if (shared_info->is_compiled()) { - Handle new_code = compile_info_wrapper.GetFunctionCode(); - Handle old_code(shared_info->code()); + Handle new_code = compile_info_wrapper.GetFunctionCode(); if (shared_info->HasBytecodeArray()) { - // The old code is interpreted. If we clear the bytecode array, the - // interpreter entry trampoline will self-heal and go to compiled code. + DCHECK(new_code->IsBytecodeArray()); + // The old code is interpreted, the new code must be interpreted as well. shared_info->ClearBytecodeArray(); - shared_info->ReplaceCode(*new_code); + shared_info->set_bytecode_array(BytecodeArray::cast(*new_code)); } else { + Handle old_code(shared_info->code()); DCHECK(old_code->kind() == Code::FUNCTION); - ReplaceCodeObject(old_code, new_code); + DCHECK(new_code->kind() == AbstractCode::FUNCTION); + ReplaceCodeObject(old_code, Handle::cast(new_code)); } if (shared_info->HasDebugInfo()) { // Existing break points will be re-applied. Reset the debug info here. @@ -2002,7 +2000,7 @@ void LiveEditFunctionTracker::FunctionDone(Handle shared, FunctionInfoWrapper info = FunctionInfoWrapper::cast( *JSReceiver::GetElement(isolate_, result_, current_parent_index_) .ToHandleChecked()); - info.SetFunctionCode(Handle(shared->code()), + info.SetFunctionCode(Handle(shared->abstract_code()), Handle(shared->scope_info())); info.SetSharedFunctionInfo(shared); diff --git a/src/debug/liveedit.h b/src/debug/liveedit.h index 7c483130ef..32328d9da7 100644 --- a/src/debug/liveedit.h +++ b/src/debug/liveedit.h @@ -292,7 +292,7 @@ class FunctionInfoWrapper : public JSArrayBasedStruct { int end_position, int param_num, int literal_count, int parent_index); - void SetFunctionCode(Handle function_code, + void SetFunctionCode(Handle function_code, Handle code_scope_info); void SetFunctionScopeInfo(Handle scope_info_array) { @@ -309,7 +309,7 @@ class FunctionInfoWrapper : public JSArrayBasedStruct { return this->GetSmiValueField(kParentIndexOffset_); } - Handle GetFunctionCode(); + Handle GetFunctionCode(); MaybeHandle GetFeedbackMetadata();