[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}
This commit is contained in:
mstarzinger 2016-06-08 00:07:20 -07:00 committed by Commit bot
parent 1e3a38d962
commit 80b98da2cd
3 changed files with 29 additions and 17 deletions

View File

@ -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<SharedFunctionInfo> 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());

View File

@ -621,11 +621,9 @@ void FunctionInfoWrapper::SetInitialProperties(Handle<String> name,
this->SetSmiValueField(kParentIndexOffset_, parent_index);
}
void FunctionInfoWrapper::SetFunctionCode(Handle<Code> function_code,
void FunctionInfoWrapper::SetFunctionCode(Handle<AbstractCode> function_code,
Handle<HeapObject> code_scope_info) {
// CompileForLiveEdit must deliver full-codegen code.
DCHECK(function_code->kind() == Code::FUNCTION);
Handle<JSValue> code_wrapper = WrapInJSValue(function_code);
this->SetField(kCodeOffset_, code_wrapper);
@ -640,13 +638,12 @@ void FunctionInfoWrapper::SetSharedFunctionInfo(
this->SetField(kSharedFunctionInfoOffset_, info_holder);
}
Handle<Code> FunctionInfoWrapper::GetFunctionCode() {
Handle<AbstractCode> FunctionInfoWrapper::GetFunctionCode() {
Handle<Object> element = this->GetField(kCodeOffset_);
Handle<JSValue> value_wrapper = Handle<JSValue>::cast(element);
Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
CHECK(raw_result->IsCode());
return Handle<Code>::cast(raw_result);
CHECK(raw_result->IsAbstractCode());
return Handle<AbstractCode>::cast(raw_result);
}
MaybeHandle<TypeFeedbackMetadata> FunctionInfoWrapper::GetFeedbackMetadata() {
@ -1012,16 +1009,17 @@ void LiveEdit::ReplaceFunctionCode(
bool feedback_metadata_changed = false;
if (shared_info->is_compiled()) {
Handle<Code> new_code = compile_info_wrapper.GetFunctionCode();
Handle<Code> old_code(shared_info->code());
Handle<AbstractCode> 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<Code> 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<Code>::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<SharedFunctionInfo> shared,
FunctionInfoWrapper info = FunctionInfoWrapper::cast(
*JSReceiver::GetElement(isolate_, result_, current_parent_index_)
.ToHandleChecked());
info.SetFunctionCode(Handle<Code>(shared->code()),
info.SetFunctionCode(Handle<AbstractCode>(shared->abstract_code()),
Handle<HeapObject>(shared->scope_info()));
info.SetSharedFunctionInfo(shared);

View File

@ -292,7 +292,7 @@ class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
int end_position, int param_num, int literal_count,
int parent_index);
void SetFunctionCode(Handle<Code> function_code,
void SetFunctionCode(Handle<AbstractCode> function_code,
Handle<HeapObject> code_scope_info);
void SetFunctionScopeInfo(Handle<Object> scope_info_array) {
@ -309,7 +309,7 @@ class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
return this->GetSmiValueField(kParentIndexOffset_);
}
Handle<Code> GetFunctionCode();
Handle<AbstractCode> GetFunctionCode();
MaybeHandle<TypeFeedbackMetadata> GetFeedbackMetadata();