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) {
|
||||
// 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()) {
|
||||
|
@ -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<class> 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;
|
||||
|
@ -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<Object> name = expr->key()->AsLiteral()->handle();
|
||||
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) {
|
||||
Handle<Object> map_or_code = GetInfo(expr->id());
|
||||
if (map_or_code->IsMap()) return true;
|
||||
@ -649,7 +660,7 @@ void TypeFeedbackOracle::ProcessRelocInfos(ZoneList<RelocInfo>* infos) {
|
||||
SetInfo(ast_id, map);
|
||||
}
|
||||
}
|
||||
} else if (target->ic_state() == MEGAMORPHIC) {
|
||||
} else {
|
||||
SetInfo(ast_id, target);
|
||||
}
|
||||
break;
|
||||
|
@ -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);
|
||||
|
@ -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]));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user