diff --git a/src/ast.cc b/src/ast.cc index 629e4722b5..4b6ae680a4 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -399,6 +399,9 @@ bool FunctionDeclaration::IsInlineable() const { void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) { // Record type feedback from the oracle in the AST. + is_uninitialized_ = oracle->LoadIsUninitialized(this); + if (is_uninitialized_) return; + is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this); receiver_types_.Clear(); if (key()->IsPropertyName()) { diff --git a/src/ast.h b/src/ast.h index 0ca3f0c091..b827302ebd 100644 --- a/src/ast.h +++ b/src/ast.h @@ -1527,6 +1527,7 @@ class Property: public Expression { virtual bool IsMonomorphic() { return is_monomorphic_; } virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; } bool IsArrayLength() { return is_array_length_; } + bool IsUninitialized() { return is_uninitialized_; } protected: template friend class AstNodeFactory; @@ -1540,6 +1541,7 @@ class Property: public Expression { key_(key), pos_(pos), is_monomorphic_(false), + is_uninitialized_(false), is_array_length_(false), is_string_length_(false), is_string_access_(false), @@ -1552,6 +1554,7 @@ class Property: public Expression { SmallMapList receiver_types_; bool is_monomorphic_ : 1; + bool is_uninitialized_ : 1; bool is_array_length_ : 1; bool is_string_length_ : 1; bool is_string_access_ : 1; diff --git a/src/hydrogen.cc b/src/hydrogen.cc index c28730b17b..358256cbf2 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -4523,6 +4523,10 @@ HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, Property* expr) { + if (expr->IsUninitialized()) { + AddInstruction(new(zone()) HSoftDeoptimize); + current_block()->MarkAsDeoptimizing(); + } ASSERT(expr->key()->IsPropertyName()); Handle name = expr->key()->AsLiteral()->handle(); HValue* context = environment()->LookupContext(); diff --git a/src/type-info.cc b/src/type-info.cc index 78fb47a165..159be6a5a1 100644 --- a/src/type-info.cc +++ b/src/type-info.cc @@ -77,6 +77,17 @@ Handle TypeFeedbackOracle::GetInfo(unsigned ast_id) { } +bool TypeFeedbackOracle::LoadIsUninitialized(Property* expr) { + Handle map_or_code = GetInfo(expr->id()); + if (map_or_code->IsMap()) return false; + if (map_or_code->IsCode()) { + Handle code = Handle::cast(map_or_code); + return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED; + } + return false; +} + + bool TypeFeedbackOracle::LoadIsMonomorphicNormal(Property* expr) { Handle map_or_code = GetInfo(expr->id()); if (map_or_code->IsMap()) return true; @@ -649,7 +660,7 @@ void TypeFeedbackOracle::ProcessRelocInfos(ZoneList* infos) { SetInfo(ast_id, map); } } - } else if (target->ic_state() == MEGAMORPHIC) { + } else { SetInfo(ast_id, target); } break; diff --git a/src/type-info.h b/src/type-info.h index 2e2ce10f96..d461331bec 100644 --- a/src/type-info.h +++ b/src/type-info.h @@ -239,6 +239,7 @@ class TypeFeedbackOracle BASE_EMBEDDED { Isolate* isolate); bool LoadIsMonomorphicNormal(Property* expr); + bool LoadIsUninitialized(Property* expr); bool LoadIsMegamorphicWithTypeInfo(Property* expr); bool StoreIsMonomorphicNormal(Expression* expr); bool StoreIsMegamorphicWithTypeInfo(Expression* expr); diff --git a/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc index f536e6b193..8b2348cd5b 100644 --- a/test/cctest/test-log-stack-tracer.cc +++ b/test/cctest/test-log-stack-tracer.cc @@ -277,7 +277,9 @@ static void CreateTraceCallerFunction(const char* func_name, TEST(CFromJSStackTrace) { // BUG(1303) Inlining of JSFuncDoTrace() in JSTrace below breaks this test. i::FLAG_use_inlining = false; - + // This test does not work with --always-opt because we don't replace the code + // in the JSFunction at deoptimization in that case. + i::FLAG_always_opt = false; TickSample sample; InitTraceEnv(&sample); @@ -307,6 +309,7 @@ TEST(CFromJSStackTrace) { // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace" int base = 0; CHECK_GT(sample.frames_count, base + 1); + CHECK(IsAddressWithinFuncCode("JSFuncDoTrace", sample.stack[base + 0])); CHECK(IsAddressWithinFuncCode("JSTrace", sample.stack[base + 1])); }