Insert explicit deoptimization for named loads that have "uninitialized" type feedback.
We already do this for binary-ops, unary-ops and comparisons. Typefeedback for named loads can now also be in "uninitialized" state which means that the corresponding load IC was never executed. Review URL: https://chromiumcodereview.appspot.com/9722041 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11087 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
56c75c387a
commit
e081a3bfba
@ -399,6 +399,9 @@ bool FunctionDeclaration::IsInlineable() const {
|
|||||||
|
|
||||||
void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
|
void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
|
||||||
// Record type feedback from the oracle in the AST.
|
// Record type feedback from the oracle in the AST.
|
||||||
|
is_uninitialized_ = oracle->LoadIsUninitialized(this);
|
||||||
|
if (is_uninitialized_) return;
|
||||||
|
|
||||||
is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
|
is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
|
||||||
receiver_types_.Clear();
|
receiver_types_.Clear();
|
||||||
if (key()->IsPropertyName()) {
|
if (key()->IsPropertyName()) {
|
||||||
|
@ -1527,6 +1527,7 @@ class Property: public Expression {
|
|||||||
virtual bool IsMonomorphic() { return is_monomorphic_; }
|
virtual bool IsMonomorphic() { return is_monomorphic_; }
|
||||||
virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
|
virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
|
||||||
bool IsArrayLength() { return is_array_length_; }
|
bool IsArrayLength() { return is_array_length_; }
|
||||||
|
bool IsUninitialized() { return is_uninitialized_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template<class> friend class AstNodeFactory;
|
template<class> friend class AstNodeFactory;
|
||||||
@ -1540,6 +1541,7 @@ class Property: public Expression {
|
|||||||
key_(key),
|
key_(key),
|
||||||
pos_(pos),
|
pos_(pos),
|
||||||
is_monomorphic_(false),
|
is_monomorphic_(false),
|
||||||
|
is_uninitialized_(false),
|
||||||
is_array_length_(false),
|
is_array_length_(false),
|
||||||
is_string_length_(false),
|
is_string_length_(false),
|
||||||
is_string_access_(false),
|
is_string_access_(false),
|
||||||
@ -1552,6 +1554,7 @@ class Property: public Expression {
|
|||||||
|
|
||||||
SmallMapList receiver_types_;
|
SmallMapList receiver_types_;
|
||||||
bool is_monomorphic_ : 1;
|
bool is_monomorphic_ : 1;
|
||||||
|
bool is_uninitialized_ : 1;
|
||||||
bool is_array_length_ : 1;
|
bool is_array_length_ : 1;
|
||||||
bool is_string_length_ : 1;
|
bool is_string_length_ : 1;
|
||||||
bool is_string_access_ : 1;
|
bool is_string_access_ : 1;
|
||||||
|
@ -4523,6 +4523,10 @@ HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
|
|||||||
|
|
||||||
HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj,
|
HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj,
|
||||||
Property* expr) {
|
Property* expr) {
|
||||||
|
if (expr->IsUninitialized()) {
|
||||||
|
AddInstruction(new(zone()) HSoftDeoptimize);
|
||||||
|
current_block()->MarkAsDeoptimizing();
|
||||||
|
}
|
||||||
ASSERT(expr->key()->IsPropertyName());
|
ASSERT(expr->key()->IsPropertyName());
|
||||||
Handle<Object> name = expr->key()->AsLiteral()->handle();
|
Handle<Object> name = expr->key()->AsLiteral()->handle();
|
||||||
HValue* context = environment()->LookupContext();
|
HValue* context = environment()->LookupContext();
|
||||||
|
@ -77,6 +77,17 @@ Handle<Object> TypeFeedbackOracle::GetInfo(unsigned ast_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TypeFeedbackOracle::LoadIsUninitialized(Property* expr) {
|
||||||
|
Handle<Object> map_or_code = GetInfo(expr->id());
|
||||||
|
if (map_or_code->IsMap()) return false;
|
||||||
|
if (map_or_code->IsCode()) {
|
||||||
|
Handle<Code> code = Handle<Code>::cast(map_or_code);
|
||||||
|
return code->is_inline_cache_stub() && code->ic_state() == UNINITIALIZED;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TypeFeedbackOracle::LoadIsMonomorphicNormal(Property* expr) {
|
bool TypeFeedbackOracle::LoadIsMonomorphicNormal(Property* expr) {
|
||||||
Handle<Object> map_or_code = GetInfo(expr->id());
|
Handle<Object> map_or_code = GetInfo(expr->id());
|
||||||
if (map_or_code->IsMap()) return true;
|
if (map_or_code->IsMap()) return true;
|
||||||
@ -649,7 +660,7 @@ void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) {
|
|||||||
SetInfo(ast_id, map);
|
SetInfo(ast_id, map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (target->ic_state() == MEGAMORPHIC) {
|
} else {
|
||||||
SetInfo(ast_id, target);
|
SetInfo(ast_id, target);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -239,6 +239,7 @@ class TypeFeedbackOracle BASE_EMBEDDED {
|
|||||||
Isolate* isolate);
|
Isolate* isolate);
|
||||||
|
|
||||||
bool LoadIsMonomorphicNormal(Property* expr);
|
bool LoadIsMonomorphicNormal(Property* expr);
|
||||||
|
bool LoadIsUninitialized(Property* expr);
|
||||||
bool LoadIsMegamorphicWithTypeInfo(Property* expr);
|
bool LoadIsMegamorphicWithTypeInfo(Property* expr);
|
||||||
bool StoreIsMonomorphicNormal(Expression* expr);
|
bool StoreIsMonomorphicNormal(Expression* expr);
|
||||||
bool StoreIsMegamorphicWithTypeInfo(Expression* expr);
|
bool StoreIsMegamorphicWithTypeInfo(Expression* expr);
|
||||||
|
@ -277,7 +277,9 @@ static void CreateTraceCallerFunction(const char* func_name,
|
|||||||
TEST(CFromJSStackTrace) {
|
TEST(CFromJSStackTrace) {
|
||||||
// BUG(1303) Inlining of JSFuncDoTrace() in JSTrace below breaks this test.
|
// BUG(1303) Inlining of JSFuncDoTrace() in JSTrace below breaks this test.
|
||||||
i::FLAG_use_inlining = false;
|
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;
|
TickSample sample;
|
||||||
InitTraceEnv(&sample);
|
InitTraceEnv(&sample);
|
||||||
|
|
||||||
@ -307,6 +309,7 @@ TEST(CFromJSStackTrace) {
|
|||||||
// Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace"
|
// Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace"
|
||||||
int base = 0;
|
int base = 0;
|
||||||
CHECK_GT(sample.frames_count, base + 1);
|
CHECK_GT(sample.frames_count, base + 1);
|
||||||
|
|
||||||
CHECK(IsAddressWithinFuncCode("JSFuncDoTrace", sample.stack[base + 0]));
|
CHECK(IsAddressWithinFuncCode("JSFuncDoTrace", sample.stack[base + 0]));
|
||||||
CHECK(IsAddressWithinFuncCode("JSTrace", sample.stack[base + 1]));
|
CHECK(IsAddressWithinFuncCode("JSTrace", sample.stack[base + 1]));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user