[compiler] Sanitize IC counts for vector based ICs.

All vector ICs use the TypeFeedbackVector::ComputeCounts method now,
while the remaining patching ICs still use the traditional way of
counting on the TypeFeedbackInfo hanging off the fullcodegen code
object. This fixes the problem that counts were sometimes off.

Drive-by-fix: Move FullCodeGenerator::CallIC to fullcodegen.cc.

R=yangguo@chromium.org

Review-Url: https://codereview.chromium.org/2472653002
Cr-Commit-Position: refs/heads/master@{#40690}
This commit is contained in:
bmeurer 2016-11-01 23:00:24 -07:00 committed by Commit bot
parent 3902043324
commit 5ef1bddf80
14 changed files with 75 additions and 136 deletions

View File

@ -2226,17 +2226,6 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
context()->Plug(r0);
}
void FullCodeGenerator::CallIC(Handle<Code> code,
TypeFeedbackId ast_id) {
ic_total_count_++;
// All calls must have a predictable size in full-codegen code to ensure that
// the debugger can patch them correctly.
__ Call(code, RelocInfo::CODE_TARGET, ast_id, al,
NEVER_INLINE_TARGET_ADDRESS);
}
// Code common for calls using the IC.
void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
Expression* callee = expr->expression();

View File

@ -2120,16 +2120,6 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
context()->Plug(x0);
}
void FullCodeGenerator::CallIC(Handle<Code> code,
TypeFeedbackId ast_id) {
ic_total_count_++;
// All calls must have a predictable size in full-codegen code to ensure that
// the debugger can patch them correctly.
__ Call(code, RelocInfo::CODE_TARGET, ast_id);
}
// Code common for calls using the IC.
void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
ASM_LOCATION("FullCodeGenerator::EmitCallWithLoadIC");

View File

@ -223,20 +223,25 @@ void FullCodeGenerator::PrepareForBailout(Expression* node,
PrepareForBailoutForId(node->id(), state);
}
void FullCodeGenerator::CallLoadIC(FeedbackVectorSlot slot, Handle<Object> name,
TypeFeedbackId id) {
void FullCodeGenerator::CallIC(Handle<Code> code, TypeFeedbackId ast_id) {
ic_total_count_++;
__ Call(code, RelocInfo::CODE_TARGET, ast_id);
}
void FullCodeGenerator::CallLoadIC(FeedbackVectorSlot slot,
Handle<Object> name) {
DCHECK(name->IsName());
__ Move(LoadDescriptor::NameRegister(), name);
EmitLoadSlot(LoadDescriptor::SlotRegister(), slot);
Handle<Code> ic = CodeFactory::LoadIC(isolate()).code();
CallIC(ic, id);
Handle<Code> code = CodeFactory::LoadIC(isolate()).code();
__ Call(code, RelocInfo::CODE_TARGET);
if (FLAG_tf_load_ic_stub) RestoreContext();
}
void FullCodeGenerator::CallStoreIC(FeedbackVectorSlot slot,
Handle<Object> name, TypeFeedbackId id) {
Handle<Object> name) {
DCHECK(name->IsName());
__ Move(StoreDescriptor::NameRegister(), name);
@ -249,8 +254,8 @@ void FullCodeGenerator::CallStoreIC(FeedbackVectorSlot slot,
EmitLoadSlot(StoreDescriptor::SlotRegister(), slot);
}
Handle<Code> ic = CodeFactory::StoreIC(isolate(), language_mode()).code();
CallIC(ic, id);
Handle<Code> code = CodeFactory::StoreIC(isolate(), language_mode()).code();
__ Call(code, RelocInfo::CODE_TARGET);
RestoreContext();
}
@ -264,9 +269,9 @@ void FullCodeGenerator::CallKeyedStoreIC(FeedbackVectorSlot slot) {
EmitLoadSlot(StoreDescriptor::SlotRegister(), slot);
}
Handle<Code> ic =
Handle<Code> code =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
__ Call(code, RelocInfo::CODE_TARGET);
RestoreContext();
}
@ -503,8 +508,8 @@ void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
#endif
EmitLoadSlot(LoadGlobalDescriptor::SlotRegister(),
proxy->VariableFeedbackSlot());
Handle<Code> ic = CodeFactory::LoadGlobalIC(isolate(), typeof_mode).code();
CallIC(ic);
Handle<Code> code = CodeFactory::LoadGlobalIC(isolate(), typeof_mode).code();
__ Call(code, RelocInfo::CODE_TARGET);
}
void FullCodeGenerator::VisitSloppyBlockFunctionStatement(
@ -1122,8 +1127,8 @@ void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
EmitLoadSlot(LoadDescriptor::SlotRegister(), prop->PropertyFeedbackSlot());
Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
CallIC(ic);
Handle<Code> code = CodeFactory::KeyedLoadIC(isolate()).code();
__ Call(code, RelocInfo::CODE_TARGET);
RestoreContext();
}

View File

@ -616,10 +616,8 @@ class FullCodeGenerator final : public AstVisitor<FullCodeGenerator> {
void CallIC(Handle<Code> code,
TypeFeedbackId id = TypeFeedbackId::None());
void CallLoadIC(FeedbackVectorSlot slot, Handle<Object> name,
TypeFeedbackId id = TypeFeedbackId::None());
void CallStoreIC(FeedbackVectorSlot slot, Handle<Object> name,
TypeFeedbackId id = TypeFeedbackId::None());
void CallLoadIC(FeedbackVectorSlot slot, Handle<Object> name);
void CallStoreIC(FeedbackVectorSlot slot, Handle<Object> name);
void CallKeyedStoreIC(FeedbackVectorSlot slot);
void SetFunctionPosition(FunctionLiteral* fun);

View File

@ -2136,14 +2136,6 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
context()->Plug(eax);
}
void FullCodeGenerator::CallIC(Handle<Code> code,
TypeFeedbackId ast_id) {
ic_total_count_++;
__ call(code, RelocInfo::CODE_TARGET, ast_id);
}
// Code common for calls using the IC.
void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
Expression* callee = expr->expression();

View File

@ -2242,14 +2242,6 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
context()->Plug(v0);
}
void FullCodeGenerator::CallIC(Handle<Code> code,
TypeFeedbackId id) {
ic_total_count_++;
__ Call(code, RelocInfo::CODE_TARGET, id);
}
// Code common for calls using the IC.
void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
Expression* callee = expr->expression();

View File

@ -2241,14 +2241,6 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
context()->Plug(v0);
}
void FullCodeGenerator::CallIC(Handle<Code> code,
TypeFeedbackId id) {
ic_total_count_++;
__ Call(code, RelocInfo::CODE_TARGET, id);
}
// Code common for calls using the IC.
void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
Expression* callee = expr->expression();

View File

@ -2238,13 +2238,6 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
context()->Plug(r3);
}
void FullCodeGenerator::CallIC(Handle<Code> code, TypeFeedbackId ast_id) {
ic_total_count_++;
__ Call(code, RelocInfo::CODE_TARGET, ast_id);
}
// Code common for calls using the IC.
void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
Expression* callee = expr->expression();

View File

@ -2190,11 +2190,6 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
context()->Plug(r2);
}
void FullCodeGenerator::CallIC(Handle<Code> code, TypeFeedbackId ast_id) {
ic_total_count_++;
__ Call(code, RelocInfo::CODE_TARGET, ast_id);
}
// Code common for calls using the IC.
void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
Expression* callee = expr->expression();

View File

@ -2123,14 +2123,6 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
context()->Plug(rax);
}
void FullCodeGenerator::CallIC(Handle<Code> code,
TypeFeedbackId ast_id) {
ic_total_count_++;
__ call(code, RelocInfo::CODE_TARGET, ast_id);
}
// Code common for calls using the IC.
void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
Expression* callee = expr->expression();

View File

@ -2128,14 +2128,6 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
context()->Plug(eax);
}
void FullCodeGenerator::CallIC(Handle<Code> code,
TypeFeedbackId ast_id) {
ic_total_count_++;
__ call(code, RelocInfo::CODE_TARGET, ast_id);
}
// Code common for calls using the IC.
void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
Expression* callee = expr->expression();

View File

@ -794,7 +794,10 @@ class MacroAssembler: public Assembler {
void Drop(int element_count);
void Call(Label* target) { call(target); }
void Call(Handle<Code> target, RelocInfo::Mode rmode) { call(target, rmode); }
void Call(Handle<Code> target, RelocInfo::Mode rmode,
TypeFeedbackId id = TypeFeedbackId::None()) {
call(target, rmode, id);
}
void Jump(Handle<Code> target, RelocInfo::Mode rmode) { jmp(target, rmode); }
void Push(Register src) { push(src); }
void Push(const Operand& src) { push(src); }

View File

@ -118,10 +118,7 @@ static void GetICCounts(JSFunction* function, int* ic_with_type_info_count,
function->shared()->code()->is_interpreter_trampoline_builtin();
vector->ComputeCounts(&with, &gen, &type_vector_ic_count, is_interpreted);
if (is_interpreted) {
DCHECK_EQ(*ic_total_count, 0);
*ic_total_count = type_vector_ic_count;
}
*ic_total_count += type_vector_ic_count;
*ic_with_type_info_count += with;
*ic_generic_count += gen;

View File

@ -159,8 +159,6 @@ CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
void TypeFeedbackVector::ComputeCounts(int* with_type_info, int* generic,
int* vector_ic_count,
bool code_is_interpreted) {
Object* uninitialized_sentinel =
TypeFeedbackVector::RawUninitializedSentinel(GetIsolate());
Object* megamorphic_sentinel =
*TypeFeedbackVector::MegamorphicSentinel(GetIsolate());
int with = 0;
@ -171,47 +169,58 @@ void TypeFeedbackVector::ComputeCounts(int* with_type_info, int* generic,
FeedbackVectorSlot slot = iter.Next();
FeedbackVectorSlotKind kind = iter.kind();
Object* obj = Get(slot);
if (kind == FeedbackVectorSlotKind::GENERAL) {
continue;
}
total++;
if (obj != uninitialized_sentinel) {
if (kind == FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC ||
kind == FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC) {
// If we are not running interpreted code, we need to ignore
// the special ic slots for binaryop/compare used by the
// interpreter.
// TODO(mvstanton): Remove code_is_interpreted when full code
// is retired from service.
if (!code_is_interpreted) continue;
DCHECK(obj->IsSmi());
int op_feedback = static_cast<int>(Smi::cast(obj)->value());
if (kind == FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC) {
CompareOperationHint hint =
CompareOperationHintFromFeedback(op_feedback);
if (hint == CompareOperationHint::kAny) {
gen++;
} else if (hint != CompareOperationHint::kNone) {
with++;
}
} else {
DCHECK(kind == FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC);
BinaryOperationHint hint =
BinaryOperationHintFromFeedback(op_feedback);
if (hint == BinaryOperationHint::kAny) {
gen++;
} else if (hint != BinaryOperationHint::kNone) {
with++;
}
Object* const obj = Get(slot);
switch (kind) {
case FeedbackVectorSlotKind::CALL_IC:
case FeedbackVectorSlotKind::LOAD_IC:
case FeedbackVectorSlotKind::LOAD_GLOBAL_IC:
case FeedbackVectorSlotKind::KEYED_LOAD_IC:
case FeedbackVectorSlotKind::STORE_IC:
case FeedbackVectorSlotKind::KEYED_STORE_IC: {
if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) {
with++;
} else if (obj == megamorphic_sentinel) {
gen++;
}
} else if (obj->IsWeakCell() || obj->IsFixedArray() || obj->IsString()) {
with++;
} else if (obj == megamorphic_sentinel) {
gen++;
total++;
break;
}
case FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC:
case FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC: {
// If we are not running interpreted code, we need to ignore the special
// IC slots for binaryop/compare used by the interpreter.
// TODO(mvstanton): Remove code_is_interpreted when full code is retired
// from service.
if (code_is_interpreted) {
int const feedback = Smi::cast(obj)->value();
if (kind == FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC) {
CompareOperationHint hint =
CompareOperationHintFromFeedback(feedback);
if (hint == CompareOperationHint::kAny) {
gen++;
} else if (hint != CompareOperationHint::kNone) {
with++;
}
} else {
DCHECK_EQ(FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC, kind);
BinaryOperationHint hint =
BinaryOperationHintFromFeedback(feedback);
if (hint == BinaryOperationHint::kAny) {
gen++;
} else if (hint != BinaryOperationHint::kNone) {
with++;
}
}
total++;
}
break;
}
case FeedbackVectorSlotKind::GENERAL:
break;
case FeedbackVectorSlotKind::INVALID:
case FeedbackVectorSlotKind::KINDS_NUMBER:
UNREACHABLE();
break;
}
}