Commit c64b47f5 authored by yangguo's avatar yangguo Committed by Commit bot

When optimizing deserialized code, make sure IC state is preserved.

R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/737373003

Cr-Commit-Position: refs/heads/master@{#25444}
parent be782ea7
...@@ -938,16 +938,23 @@ bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) { ...@@ -938,16 +938,23 @@ bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
DCHECK(info->function() != NULL); DCHECK(info->function() != NULL);
DCHECK(info->scope() != NULL); DCHECK(info->scope() != NULL);
if (!info->shared_info()->has_deoptimization_support()) { if (!info->shared_info()->has_deoptimization_support()) {
CompilationInfoWithZone unoptimized(info->shared_info()); Handle<SharedFunctionInfo> shared = info->shared_info();
CompilationInfoWithZone unoptimized(shared);
// Note that we use the same AST that we will use for generating the // Note that we use the same AST that we will use for generating the
// optimized code. // optimized code.
unoptimized.SetFunction(info->function()); unoptimized.SetFunction(info->function());
unoptimized.PrepareForCompilation(info->scope()); unoptimized.PrepareForCompilation(info->scope());
unoptimized.SetContext(info->context()); unoptimized.SetContext(info->context());
unoptimized.EnableDeoptimizationSupport(); unoptimized.EnableDeoptimizationSupport();
// If the current code has reloc info for serialization, also include
// reloc info for serialization for the new code, so that deopt support
// can be added without losing IC state.
if (shared->code()->kind() == Code::FUNCTION &&
shared->code()->has_reloc_info_for_serialization()) {
unoptimized.PrepareForSerializing();
}
if (!FullCodeGenerator::MakeCode(&unoptimized)) return false; if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
Handle<SharedFunctionInfo> shared = info->shared_info();
shared->EnableDeoptimizationSupport(*unoptimized.code()); shared->EnableDeoptimizationSupport(*unoptimized.code());
shared->set_feedback_vector(*unoptimized.feedback_vector()); shared->set_feedback_vector(*unoptimized.feedback_vector());
...@@ -1313,10 +1320,10 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo( ...@@ -1313,10 +1320,10 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(
bool allow_lazy = literal->AllowsLazyCompilation() && bool allow_lazy = literal->AllowsLazyCompilation() &&
!DebuggerWantsEagerCompilation(&info, allow_lazy_without_ctx); !DebuggerWantsEagerCompilation(&info, allow_lazy_without_ctx);
if (outer_info->is_toplevel() && outer_info->will_serialize()) { if (outer_info->is_toplevel() && outer_info->will_serialize()) {
// Make sure that if the toplevel code (possibly to be serialized), // Make sure that if the toplevel code (possibly to be serialized),
// the inner function must be allowed to be compiled lazily. // the inner function must be allowed to be compiled lazily.
// This is necessary to serialize toplevel code without inner functions.
DCHECK(allow_lazy); DCHECK(allow_lazy);
} }
......
...@@ -477,6 +477,7 @@ DEFINE_BOOL(trace_stub_failures, false, ...@@ -477,6 +477,7 @@ DEFINE_BOOL(trace_stub_failures, false,
"trace deoptimization of generated code stubs") "trace deoptimization of generated code stubs")
DEFINE_BOOL(serialize_toplevel, true, "enable caching of toplevel scripts") DEFINE_BOOL(serialize_toplevel, true, "enable caching of toplevel scripts")
DEFINE_BOOL(serialize_inner, false, "enable caching of inner functions")
DEFINE_BOOL(trace_code_serializer, false, "print code serializer trace") DEFINE_BOOL(trace_code_serializer, false, "print code serializer trace")
// compiler.cc // compiler.cc
......
...@@ -338,6 +338,7 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) { ...@@ -338,6 +338,7 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
cgen.PopulateDeoptimizationData(code); cgen.PopulateDeoptimizationData(code);
cgen.PopulateTypeFeedbackInfo(code); cgen.PopulateTypeFeedbackInfo(code);
code->set_has_deoptimization_support(info->HasDeoptimizationSupport()); code->set_has_deoptimization_support(info->HasDeoptimizationSupport());
code->set_has_reloc_info_for_serialization(info->will_serialize());
code->set_handler_table(*cgen.handler_table()); code->set_handler_table(*cgen.handler_table());
code->set_compiled_optimizable(info->IsOptimizable()); code->set_compiled_optimizable(info->IsOptimizable());
code->set_allow_osr_at_loop_nesting_level(0); code->set_allow_osr_at_loop_nesting_level(0);
......
...@@ -4858,6 +4858,21 @@ void Code::set_compiled_optimizable(bool value) { ...@@ -4858,6 +4858,21 @@ void Code::set_compiled_optimizable(bool value) {
} }
bool Code::has_reloc_info_for_serialization() {
DCHECK_EQ(FUNCTION, kind());
byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
return FullCodeFlagsHasRelocInfoForSerialization::decode(flags);
}
void Code::set_has_reloc_info_for_serialization(bool value) {
DCHECK_EQ(FUNCTION, kind());
byte flags = READ_BYTE_FIELD(this, kFullCodeFlags);
flags = FullCodeFlagsHasRelocInfoForSerialization::update(flags, value);
WRITE_BYTE_FIELD(this, kFullCodeFlags, flags);
}
int Code::allow_osr_at_loop_nesting_level() { int Code::allow_osr_at_loop_nesting_level() {
DCHECK_EQ(FUNCTION, kind()); DCHECK_EQ(FUNCTION, kind());
int fields = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset); int fields = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
......
...@@ -5103,6 +5103,12 @@ class Code: public HeapObject { ...@@ -5103,6 +5103,12 @@ class Code: public HeapObject {
inline bool is_compiled_optimizable(); inline bool is_compiled_optimizable();
inline void set_compiled_optimizable(bool value); inline void set_compiled_optimizable(bool value);
// [has_reloc_info_for_serialization]: For FUNCTION kind, tells if its
// reloc info includes runtime and external references to support
// serialization/deserialization.
inline bool has_reloc_info_for_serialization();
inline void set_has_reloc_info_for_serialization(bool value);
// [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for // [allow_osr_at_loop_nesting_level]: For FUNCTION kind, tells for
// how long the function has been marked for OSR and therefore which // how long the function has been marked for OSR and therefore which
// level of loop nesting we are willing to do on-stack replacement // level of loop nesting we are willing to do on-stack replacement
...@@ -5387,6 +5393,8 @@ class Code: public HeapObject { ...@@ -5387,6 +5393,8 @@ class Code: public HeapObject {
public BitField<bool, 0, 1> {}; // NOLINT public BitField<bool, 0, 1> {}; // NOLINT
class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {}; class FullCodeFlagsHasDebugBreakSlotsField: public BitField<bool, 1, 1> {};
class FullCodeFlagsIsCompiledOptimizable: public BitField<bool, 2, 1> {}; class FullCodeFlagsIsCompiledOptimizable: public BitField<bool, 2, 1> {};
class FullCodeFlagsHasRelocInfoForSerialization
: public BitField<bool, 3, 1> {};
static const int kProfilerTicksOffset = kFullCodeFlags + 1; static const int kProfilerTicksOffset = kFullCodeFlags + 1;
......
...@@ -2042,10 +2042,11 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, ...@@ -2042,10 +2042,11 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
SerializeIC(code_object, how_to_code, where_to_point); SerializeIC(code_object, how_to_code, where_to_point);
return; return;
case Code::FUNCTION: case Code::FUNCTION:
// Only serialize the code for the toplevel function. Replace code DCHECK(code_object->has_reloc_info_for_serialization());
// of included function literals by the lazy compile builtin. // Only serialize the code for the toplevel function unless specified
// by flag. Replace code of inner functions by the lazy compile builtin.
// This is safe, as checked in Compiler::BuildFunctionInfo. // This is safe, as checked in Compiler::BuildFunctionInfo.
if (code_object != main_code_) { if (code_object != main_code_ && !FLAG_serialize_inner) {
SerializeBuiltin(Builtins::kCompileLazy, how_to_code, where_to_point); SerializeBuiltin(Builtins::kCompileLazy, how_to_code, where_to_point);
} else { } else {
code_object->MakeYoung(); code_object->MakeYoung();
...@@ -2062,6 +2063,8 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, ...@@ -2062,6 +2063,8 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
CHECK(!obj->IsJSGlobalProxy() && !obj->IsGlobalObject()); CHECK(!obj->IsJSGlobalProxy() && !obj->IsGlobalObject());
// There should be no hash table embedded. They would require rehashing. // There should be no hash table embedded. They would require rehashing.
CHECK(!obj->IsHashTable()); CHECK(!obj->IsHashTable());
// We expect no instantiated function objects or contexts.
CHECK(!obj->IsJSFunction() && !obj->IsContext());
SerializeGeneric(obj, how_to_code, where_to_point); SerializeGeneric(obj, how_to_code, where_to_point);
} }
......
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax --cache=code --no-lazy --serialize-inner
function f(x, y) { return x + y; }
assertEquals(1, f(0, 1));
assertEquals(5, f(2, 3));
%OptimizeFunctionOnNextCall(f);
assertEquals(9, f(4, 5));
assertOptimized(f);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment