Commit 245e5b32 authored by mythria's avatar mythria Committed by Commit bot

[Ignition] Use binary operation feedback from Ignition to Crankshaft.

Ignition collects type feedback for binary and compare operations in type
feedback vector and FCG uses Binary/CompareOpICs to collect type feedback.
The feedback collected by ignition is not used by crankshaft. This hits the
performance, when trying to optimize functions that did not tier upto FCG.
This cl merges the feedback collected by ignition and FCG when passing to
crankshaft.

BUG=v8:4280

Review-Url: https://codereview.chromium.org/2361043002
Cr-Commit-Position: refs/heads/master@{#39753}
parent 381aa94d
......@@ -211,7 +211,8 @@ void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
AstType* label_type;
AstType* combined_type;
oracle()->CompareType(clause->CompareId(),
&tag_type, &label_type, &combined_type);
clause->CompareOperationFeedbackSlot(), &tag_type,
&label_type, &combined_type);
NarrowLowerType(stmt->tag(), tag_type);
NarrowLowerType(label, label_type);
clause->set_compare_type(combined_type);
......@@ -614,7 +615,8 @@ void AstTyper::VisitCountOperation(CountOperation* expr) {
oracle()->CountReceiverTypes(slot, expr->GetReceiverTypes());
expr->set_store_mode(store_mode);
expr->set_key_type(key_type);
expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId()));
expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId(),
expr->CountBinaryOpFeedbackSlot()));
// TODO(rossberg): merge the count type with the generic expression type.
RECURSE(Visit(expr->expression()));
......@@ -627,7 +629,6 @@ void AstTyper::VisitCountOperation(CountOperation* expr) {
}
}
void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
// Collect type feedback.
AstType* type;
......@@ -636,8 +637,10 @@ void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
Maybe<int> fixed_right_arg = Nothing<int>();
Handle<AllocationSite> allocation_site;
oracle()->BinaryType(expr->BinaryOperationFeedbackId(),
&left_type, &right_type, &type, &fixed_right_arg,
&allocation_site, expr->op());
expr->BinaryOperationFeedbackSlot(), &left_type,
&right_type, &type, &fixed_right_arg, &allocation_site,
expr->op());
NarrowLowerType(expr, type);
NarrowLowerType(expr->left(), left_type);
NarrowLowerType(expr->right(), right_type);
......@@ -739,7 +742,8 @@ void AstTyper::VisitCompareOperation(CompareOperation* expr) {
AstType* right_type;
AstType* combined_type;
oracle()->CompareType(expr->CompareOperationFeedbackId(),
&left_type, &right_type, &combined_type);
expr->CompareOperationFeedbackSlot(), &left_type,
&right_type, &combined_type);
NarrowLowerType(expr->left(), left_type);
NarrowLowerType(expr->right(), right_type);
expr->set_combined_type(combined_type);
......
......@@ -123,6 +123,8 @@ void TypeFeedbackVector::Set(FeedbackVectorSlot slot, Object* value,
// Helper function to transform the feedback to BinaryOperationHint.
BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
switch (type_feedback) {
case BinaryOperationFeedback::kNone:
return BinaryOperationHint::kNone;
case BinaryOperationFeedback::kSignedSmall:
return BinaryOperationHint::kSignedSmall;
case BinaryOperationFeedback::kNumber:
......@@ -138,6 +140,8 @@ BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
// Helper function to transform the feedback to CompareOperationHint.
CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
switch (type_feedback) {
case CompareOperationFeedback::kNone:
return CompareOperationHint::kNone;
case CompareOperationFeedback::kSignedSmall:
return CompareOperationHint::kSignedSmall;
case CompareOperationFeedback::kNumber:
......@@ -145,6 +149,8 @@ CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
default:
return CompareOperationHint::kAny;
}
UNREACHABLE();
return CompareOperationHint::kNone;
}
void TypeFeedbackVector::ComputeCounts(int* with_type_info, int* generic,
......
......@@ -191,38 +191,100 @@ Handle<AllocationSite> TypeFeedbackOracle::GetCallNewAllocationSite(
return Handle<AllocationSite>::null();
}
void TypeFeedbackOracle::CompareType(TypeFeedbackId id, AstType** left_type,
AstType** right_type,
namespace {
AstType* CompareOpHintToType(CompareOperationHint hint) {
switch (hint) {
case CompareOperationHint::kNone:
return AstType::None();
case CompareOperationHint::kSignedSmall:
return AstType::SignedSmall();
case CompareOperationHint::kNumber:
return AstType::Number();
case CompareOperationHint::kNumberOrOddball:
return AstType::NumberOrOddball();
case CompareOperationHint::kAny:
return AstType::Any();
}
UNREACHABLE();
return AstType::None();
}
AstType* BinaryOpHintToType(BinaryOperationHint hint) {
switch (hint) {
case BinaryOperationHint::kNone:
return AstType::None();
case BinaryOperationHint::kSignedSmall:
return AstType::SignedSmall();
case BinaryOperationHint::kSigned32:
return AstType::Signed32();
case BinaryOperationHint::kNumberOrOddball:
return AstType::Number();
case BinaryOperationHint::kString:
return AstType::String();
case BinaryOperationHint::kAny:
return AstType::Any();
}
UNREACHABLE();
return AstType::None();
}
} // end anonymous namespace
void TypeFeedbackOracle::CompareType(TypeFeedbackId id, FeedbackVectorSlot slot,
AstType** left_type, AstType** right_type,
AstType** combined_type) {
Handle<Object> info = GetInfo(id);
// A check for a valid slot is not sufficient here. InstanceOf collects
// type feedback in a General slot.
if (!info->IsCode()) {
// For some comparisons we don't have ICs, e.g. LiteralCompareTypeof.
// For some comparisons we don't have type feedback, e.g.
// LiteralCompareTypeof.
*left_type = *right_type = *combined_type = AstType::None();
return;
}
Handle<Code> code = Handle<Code>::cast(info);
// Feedback from Ignition. The feedback slot will be allocated and initialized
// to AstType::None() even when ignition is not enabled. So it is safe to get
// feedback from the type feedback vector.
DCHECK(!slot.IsInvalid());
CompareICNexus nexus(feedback_vector_, slot);
*left_type = *right_type = *combined_type =
CompareOpHintToType(nexus.GetCompareOperationFeedback());
// Merge the feedback from full-codegen if available.
Handle<Code> code = Handle<Code>::cast(info);
Handle<Map> map;
Map* raw_map = code->FindFirstMap();
if (raw_map != NULL) Map::TryUpdate(handle(raw_map)).ToHandle(&map);
if (code->is_compare_ic_stub()) {
CompareICStub stub(code->stub_key(), isolate());
*left_type = CompareICState::StateToType(zone(), stub.left());
*right_type = CompareICState::StateToType(zone(), stub.right());
*combined_type = CompareICState::StateToType(zone(), stub.state(), map);
AstType* left_type_from_ic =
CompareICState::StateToType(zone(), stub.left());
*left_type = AstType::Union(*left_type, left_type_from_ic, zone());
AstType* right_type_from_ic =
CompareICState::StateToType(zone(), stub.right());
*right_type = AstType::Union(*right_type, right_type_from_ic, zone());
AstType* combined_type_from_ic =
CompareICState::StateToType(zone(), stub.state(), map);
*combined_type =
AstType::Union(*combined_type, combined_type_from_ic, zone());
}
}
void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, AstType** left,
AstType** right, AstType** result,
void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, FeedbackVectorSlot slot,
AstType** left, AstType** right,
AstType** result,
Maybe<int>* fixed_right_arg,
Handle<AllocationSite>* allocation_site,
Token::Value op) {
Handle<Object> object = GetInfo(id);
if (!object->IsCode()) {
// For some binary ops we don't have ICs, e.g. Token::COMMA, but for the
// operations covered by the BinaryOpIC we should always have them.
if (slot.IsInvalid()) {
// For some binary ops we don't have ICs or feedback slots,
// e.g. Token::COMMA, but for the operations covered by the BinaryOpIC we
// should always have them.
DCHECK(!object->IsCode());
DCHECK(op < BinaryOpICState::FIRST_TOKEN ||
op > BinaryOpICState::LAST_TOKEN);
*left = *right = *result = AstType::None();
......@@ -230,14 +292,28 @@ void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, AstType** left,
*allocation_site = Handle<AllocationSite>::null();
return;
}
// Feedback from Ignition. The feedback slot will be allocated and initialized
// to AstType::None() even when ignition is not enabled. So it is safe to get
// feedback from the type feedback vector.
DCHECK(!slot.IsInvalid());
BinaryOpICNexus nexus(feedback_vector_, slot);
*left = *right = *result =
BinaryOpHintToType(nexus.GetBinaryOperationFeedback());
*fixed_right_arg = Nothing<int>();
*allocation_site = Handle<AllocationSite>::null();
if (!object->IsCode()) return;
// Merge the feedback from full-codegen if available.
Handle<Code> code = Handle<Code>::cast(object);
DCHECK_EQ(Code::BINARY_OP_IC, code->kind());
BinaryOpICState state(isolate(), code->extra_ic_state());
DCHECK_EQ(op, state.op());
*left = state.GetLeftType();
*right = state.GetRightType();
*result = state.GetResultType();
*left = AstType::Union(*left, state.GetLeftType(), zone());
*right = AstType::Union(*right, state.GetRightType(), zone());
*result = AstType::Union(*result, state.GetResultType(), zone());
*fixed_right_arg = state.fixed_right_arg();
AllocationSite* first_allocation_site = code->FindFirstAllocationSite();
......@@ -248,13 +324,24 @@ void TypeFeedbackOracle::BinaryType(TypeFeedbackId id, AstType** left,
}
}
AstType* TypeFeedbackOracle::CountType(TypeFeedbackId id) {
AstType* TypeFeedbackOracle::CountType(TypeFeedbackId id,
FeedbackVectorSlot slot) {
Handle<Object> object = GetInfo(id);
if (!object->IsCode()) return AstType::None();
if (slot.IsInvalid()) {
DCHECK(!object->IsCode());
return AstType::None();
}
DCHECK(!slot.IsInvalid());
BinaryOpICNexus nexus(feedback_vector_, slot);
AstType* type = BinaryOpHintToType(nexus.GetBinaryOperationFeedback());
if (!object->IsCode()) return type;
Handle<Code> code = Handle<Code>::cast(object);
DCHECK_EQ(Code::BINARY_OP_IC, code->kind());
BinaryOpICState state(isolate(), code->extra_ic_state());
return state.GetLeftType();
return AstType::Union(type, state.GetLeftType(), zone());
}
......
......@@ -77,15 +77,16 @@ class TypeFeedbackOracle: public ZoneObject {
uint16_t ToBooleanTypes(TypeFeedbackId id);
// Get type information for arithmetic operations and compares.
void BinaryType(TypeFeedbackId id, AstType** left, AstType** right,
AstType** result, Maybe<int>* fixed_right_arg,
void BinaryType(TypeFeedbackId id, FeedbackVectorSlot slot, AstType** left,
AstType** right, AstType** result,
Maybe<int>* fixed_right_arg,
Handle<AllocationSite>* allocation_site,
Token::Value operation);
void CompareType(TypeFeedbackId id, AstType** left, AstType** right,
AstType** combined);
void CompareType(TypeFeedbackId id, FeedbackVectorSlot slot, AstType** left,
AstType** right, AstType** combined);
AstType* CountType(TypeFeedbackId id);
AstType* CountType(TypeFeedbackId id, FeedbackVectorSlot slot);
Zone* zone() const { return zone_; }
Isolate* isolate() const { return isolate_; }
......
......@@ -364,7 +364,6 @@
'test-heap/CompilationCacheCachingBehavior': [FAIL],
# BUG(4680): Missing type feedback makes optimistic optimizations fail.
'test-cpu-profiler/CollectDeoptEvents': [FAIL],
'test-cpu-profiler/DeoptUntrackedFunction': [SKIP],
# BUG(4751). Flaky with ignition.
......@@ -374,10 +373,6 @@
# with crankshaft.
'test-cpu-profiler/TickLinesOptimized': [SKIP],
# TurboFan cpu profiler result is different.
'test-cpu-profiler/DeoptAtFirstLevelInlinedSource': [FAIL],
'test-cpu-profiler/DeoptAtSecondLevelInlinedSource': [FAIL],
# BUG(5193): Flaky.
'test-cpu-profiler/FunctionApplySample': [PASS, ['system == windows', SKIP]],
}], # variant == ignition
......@@ -386,9 +381,6 @@
['variant == ignition_staging', {
'test-cpu-profiler/DeoptUntrackedFunction': [SKIP],
'test-cpu-profiler/TickLinesOptimized': [SKIP],
'test-cpu-profiler/CollectDeoptEvents': [FAIL],
'test-cpu-profiler/DeoptAtFirstLevelInlinedSource': [FAIL],
'test-cpu-profiler/DeoptAtSecondLevelInlinedSource': [FAIL],
'test-heap/CompilationCacheCachingBehavior': [FAIL],
'test-heap/Regress169209': [FAIL],
'test-heap/TestCodeFlushing': [FAIL],
......
......@@ -656,38 +656,11 @@
# TODO(4680): Test doesn't know about three tier compiler pipeline.
'assert-opt-and-deopt': [SKIP],
# BUG(rmcilroy,4989): Function is optimized without type feedback and so
# immediately deopts again, causing check failure in the test.
'compiler/deopt-inlined-from-call': [FAIL],
'compiler/increment-typefeedback': [FAIL],
# Fails because concurrent compilation is not triggered on bytecode.
# Check in Runtime_OptimizeFunctionOnNextCall.
'compiler/manual-concurrent-recompile': [FAIL],
'constant-folding-2': [FAIL],
'debug-is-active': [FAIL],
'deopt-with-fp-regs': [FAIL],
'deserialize-optimize-inner': [FAIL],
'div-mul-minus-one': [FAIL],
'double-intrinsics': [FAIL],
'elements-transition-hoisting': [FAIL],
'es6/block-let-crankshaft': [FAIL],
'es6/block-let-crankshaft-sloppy': [FAIL],
'getters-on-elements': [FAIL],
'harmony/do-expressions': [FAIL],
'math-floor-of-div-minus-zero': [FAIL],
'regress/regress-2132': [FAIL],
'regress/regress-2339': [FAIL],
'regress/regress-3176': [FAIL],
'regress/regress-3709': [FAIL],
'regress/regress-385565': [FAIL],
'regress/regress-crbug-594183': [FAIL],
'regress/regress-embedded-cons-string': [FAIL],
'regress/regress-map-invalidation-2': [FAIL],
'regress/regress-param-local-type': [FAIL],
'regress/regress-prepare-break-while-recompile': [FAIL],
'shift-for-integer-div': [FAIL],
'sin-cos': [FAIL],
'smi-mul-const': [FAIL],
'smi-mul': [FAIL],
'unary-minus-deopt': [FAIL],
# Modules for which execution must fail (e.g. because of unresolved imports).
# Eventually we should test for the precise error message, but for now we only
......@@ -731,37 +704,14 @@
##############################################################################
['variant == ignition_staging', {
'assert-opt-and-deopt': [SKIP],
'compiler/deopt-inlined-from-call': [FAIL],
'compiler/increment-typefeedback': [FAIL],
'compiler/manual-concurrent-recompile': [FAIL],
'constant-folding-2': [FAIL],
'debug-is-active': [FAIL],
'debug-liveedit-double-call': [FAIL],
'deopt-with-fp-regs': [FAIL],
'deserialize-optimize-inner': [FAIL],
'div-mul-minus-one': [FAIL],
'elements-transition-hoisting': [FAIL],
'es6/block-let-crankshaft': [FAIL],
'es6/block-let-crankshaft-sloppy': [FAIL],
'getters-on-elements': [FAIL],
'harmony/do-expressions': [FAIL],
'math-floor-of-div-minus-zero': [FAIL],
'regress/regress-2132': [FAIL],
'regress/regress-2339': [FAIL],
'regress/regress-3176': [FAIL],
'regress/regress-3709': [FAIL],
'regress/regress-385565': [FAIL],
'regress/regress-crbug-594183': [FAIL],
'regress-sync-optimized-lists': [FAIL],
# Fails because concurrent compilation is not triggered on bytecode.
# Check in Runtime_OptimizeFunctionOnNextCall.
'compiler/manual-concurrent-recompile': [FAIL],
'regress/regress-embedded-cons-string': [FAIL],
'regress/regress-map-invalidation-2': [FAIL],
'regress/regress-param-local-type': [FAIL],
'regress/regress-prepare-break-while-recompile': [FAIL],
'regress-sync-optimized-lists': [FAIL],
'shift-for-integer-div': [FAIL],
'sin-cos': [FAIL],
'smi-mul-const': [FAIL],
'smi-mul': [FAIL],
'unary-minus-deopt': [FAIL],
# Flaky.
'asm/int32div': [SKIP],
......
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