Commit b167ae33 authored by epertoso's avatar epertoso Committed by Commit bot

[interpreter] Collect type feedback from bitwise binary ops handlers.

Also, re-enables the use of the type feedback in BytecodeGraphBuilder.

BUG=v8:5273
LOG=N

Review-Url: https://codereview.chromium.org/2235133003
Cr-Commit-Position: refs/heads/master@{#38618}
parent 68868c73
......@@ -1186,8 +1186,7 @@ BinaryOperationHint BytecodeGraphBuilder::GetBinaryOperationHint() {
}
void BytecodeGraphBuilder::VisitAdd() {
BinaryOperationHint hint = BinaryOperationHint::kAny;
BuildBinaryOp(javascript()->Add(hint));
BuildBinaryOp(javascript()->Add(GetBinaryOperationHint()));
}
void BytecodeGraphBuilder::VisitSub() {
......@@ -1195,48 +1194,39 @@ void BytecodeGraphBuilder::VisitSub() {
}
void BytecodeGraphBuilder::VisitMul() {
BinaryOperationHint hint = BinaryOperationHint::kAny;
BuildBinaryOp(javascript()->Multiply(hint));
BuildBinaryOp(javascript()->Multiply(GetBinaryOperationHint()));
}
void BytecodeGraphBuilder::VisitDiv() {
BinaryOperationHint hint = BinaryOperationHint::kAny;
BuildBinaryOp(javascript()->Divide(hint));
BuildBinaryOp(javascript()->Divide(GetBinaryOperationHint()));
}
void BytecodeGraphBuilder::VisitMod() {
BinaryOperationHint hint = BinaryOperationHint::kAny;
BuildBinaryOp(javascript()->Modulus(hint));
BuildBinaryOp(javascript()->Modulus(GetBinaryOperationHint()));
}
void BytecodeGraphBuilder::VisitBitwiseOr() {
BinaryOperationHint hint = BinaryOperationHint::kAny;
BuildBinaryOp(javascript()->BitwiseOr(hint));
BuildBinaryOp(javascript()->BitwiseOr(GetBinaryOperationHint()));
}
void BytecodeGraphBuilder::VisitBitwiseXor() {
BinaryOperationHint hint = BinaryOperationHint::kAny;
BuildBinaryOp(javascript()->BitwiseXor(hint));
BuildBinaryOp(javascript()->BitwiseXor(GetBinaryOperationHint()));
}
void BytecodeGraphBuilder::VisitBitwiseAnd() {
BinaryOperationHint hint = BinaryOperationHint::kAny;
BuildBinaryOp(javascript()->BitwiseAnd(hint));
BuildBinaryOp(javascript()->BitwiseAnd(GetBinaryOperationHint()));
}
void BytecodeGraphBuilder::VisitShiftLeft() {
BinaryOperationHint hint = BinaryOperationHint::kAny;
BuildBinaryOp(javascript()->ShiftLeft(hint));
BuildBinaryOp(javascript()->ShiftLeft(GetBinaryOperationHint()));
}
void BytecodeGraphBuilder::VisitShiftRight() {
BinaryOperationHint hint = BinaryOperationHint::kAny;
BuildBinaryOp(javascript()->ShiftRight(hint));
BuildBinaryOp(javascript()->ShiftRight(GetBinaryOperationHint()));
}
void BytecodeGraphBuilder::VisitShiftRightLogical() {
BinaryOperationHint hint = BinaryOperationHint::kAny;
BuildBinaryOp(javascript()->ShiftRightLogical(hint));
BuildBinaryOp(javascript()->ShiftRightLogical(GetBinaryOperationHint()));
}
void BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* js_op) {
......
......@@ -136,7 +136,7 @@ TypeHintAnalysis* TypeHintAnalyzer::Analyze(Handle<Code> code) {
BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
switch (type_feedback) {
case BinaryOperationFeedback::kSignedSmall:
return BinaryOperationHint::kSigned32;
return BinaryOperationHint::kSignedSmall;
case BinaryOperationFeedback::kNumber:
return BinaryOperationHint::kNumberOrOddball;
case BinaryOperationFeedback::kAny:
......
......@@ -845,6 +845,67 @@ void InterpreterAssembler::DispatchWide(OperandScale operand_scale) {
DispatchToBytecodeHandlerEntry(target_code_entry, next_bytecode_offset);
}
Node* InterpreterAssembler::TruncateTaggedToWord32WithFeedback(
Node* context, Node* value, Variable* var_type_feedback) {
// We might need to loop once due to ToNumber conversion.
Variable var_value(this, MachineRepresentation::kTagged),
var_result(this, MachineRepresentation::kWord32);
Variable* loop_vars[] = {&var_value, var_type_feedback};
Label loop(this, 2, loop_vars), done_loop(this, &var_result);
var_value.Bind(value);
var_type_feedback->Bind(Int32Constant(BinaryOperationFeedback::kNone));
Goto(&loop);
Bind(&loop);
{
// Load the current {value}.
value = var_value.value();
// Check if the {value} is a Smi or a HeapObject.
Label if_valueissmi(this), if_valueisnotsmi(this);
Branch(WordIsSmi(value), &if_valueissmi, &if_valueisnotsmi);
Bind(&if_valueissmi);
{
// Convert the Smi {value}.
var_result.Bind(SmiToWord32(value));
var_type_feedback->Bind(
Word32And(var_type_feedback->value(),
Int32Constant(BinaryOperationFeedback::kSignedSmall)));
Goto(&done_loop);
}
Bind(&if_valueisnotsmi);
{
// Check if {value} is a HeapNumber.
Label if_valueisheapnumber(this),
if_valueisnotheapnumber(this, Label::kDeferred);
Branch(WordEqual(LoadMap(value), HeapNumberMapConstant()),
&if_valueisheapnumber, &if_valueisnotheapnumber);
Bind(&if_valueisheapnumber);
{
// Truncate the floating point value.
var_result.Bind(TruncateHeapNumberValueToWord32(value));
var_type_feedback->Bind(
Word32Or(var_type_feedback->value(),
Int32Constant(BinaryOperationFeedback::kNumber)));
Goto(&done_loop);
}
Bind(&if_valueisnotheapnumber);
{
// Convert the {value} to a Number first.
Callable callable = CodeFactory::NonNumberToNumber(isolate());
var_value.Bind(CallStub(callable, context, value));
var_type_feedback->Bind(Int32Constant(BinaryOperationFeedback::kAny));
Goto(&loop);
}
}
}
Bind(&done_loop);
return var_result.value();
}
void InterpreterAssembler::UpdateInterruptBudgetOnReturn() {
// TODO(rmcilroy): Investigate whether it is worth supporting self
// optimization of primitive functions like FullCodegen.
......
......@@ -162,6 +162,12 @@ class InterpreterAssembler : public CodeStubAssembler {
// Dispatch bytecode as wide operand variant.
void DispatchWide(OperandScale operand_scale);
// Truncate tagged |value| to word32 and store the type feedback in
// |var_type_feedback|.
compiler::Node* TruncateTaggedToWord32WithFeedback(
compiler::Node* context, compiler::Node* value,
Variable* var_type_feedback);
// Abort with the given bailout reason.
void Abort(BailoutReason bailout_reason);
void AbortIfWordNotEqual(compiler::Node* lhs, compiler::Node* rhs,
......
......@@ -811,25 +811,97 @@ void Interpreter::DoMod(InterpreterAssembler* assembler) {
DoBinaryOpWithFeedback<ModulusWithFeedbackStub>(assembler);
}
void Interpreter::DoBitwiseBinaryOp(Token::Value bitwise_op,
InterpreterAssembler* assembler) {
Node* reg_index = __ BytecodeOperandReg(0);
Node* lhs = __ LoadRegister(reg_index);
Node* rhs = __ GetAccumulator();
Node* context = __ GetContext();
Node* slot_index = __ BytecodeOperandIdx(1);
Node* type_feedback_vector = __ LoadTypeFeedbackVector();
Variable var_lhs_type_feedback(assembler, MachineRepresentation::kWord32),
var_rhs_type_feedback(assembler, MachineRepresentation::kWord32);
Node* lhs_value = __ TruncateTaggedToWord32WithFeedback(
context, lhs, &var_lhs_type_feedback);
Node* rhs_value = __ TruncateTaggedToWord32WithFeedback(
context, rhs, &var_rhs_type_feedback);
Node* result = nullptr;
switch (bitwise_op) {
case Token::BIT_OR: {
Node* value = __ Word32Or(lhs_value, rhs_value);
result = __ ChangeInt32ToTagged(value);
} break;
case Token::BIT_AND: {
Node* value = __ Word32And(lhs_value, rhs_value);
result = __ ChangeInt32ToTagged(value);
} break;
case Token::BIT_XOR: {
Node* value = __ Word32Xor(lhs_value, rhs_value);
result = __ ChangeInt32ToTagged(value);
} break;
case Token::SHL: {
Node* value = __ Word32Shl(
lhs_value, __ Word32And(rhs_value, __ Int32Constant(0x1f)));
result = __ ChangeInt32ToTagged(value);
} break;
case Token::SHR: {
Node* value = __ Word32Shr(
lhs_value, __ Word32And(rhs_value, __ Int32Constant(0x1f)));
result = __ ChangeUint32ToTagged(value);
} break;
case Token::SAR: {
Node* value = __ Word32Sar(
lhs_value, __ Word32And(rhs_value, __ Int32Constant(0x1f)));
result = __ ChangeInt32ToTagged(value);
} break;
default:
UNREACHABLE();
}
Node* result_type =
__ Select(__ WordIsSmi(result),
__ Int32Constant(BinaryOperationFeedback::kSignedSmall),
__ Int32Constant(BinaryOperationFeedback::kNumber));
if (FLAG_debug_code) {
Label ok(assembler);
__ GotoIf(__ WordIsSmi(result), &ok);
Node* result_map = __ LoadMap(result);
__ AbortIfWordNotEqual(result_map, __ HeapNumberMapConstant(),
kExpectedHeapNumber);
__ Goto(&ok);
__ Bind(&ok);
}
Node* input_feedback =
__ Word32Or(var_lhs_type_feedback.value(), var_rhs_type_feedback.value());
__ UpdateFeedback(__ Word32Or(result_type, input_feedback),
type_feedback_vector, slot_index);
__ SetAccumulator(result);
__ Dispatch();
}
// BitwiseOr <src>
//
// BitwiseOr register <src> to accumulator.
void Interpreter::DoBitwiseOr(InterpreterAssembler* assembler) {
DoBinaryOp<BitwiseOrStub>(assembler);
DoBitwiseBinaryOp(Token::BIT_OR, assembler);
}
// BitwiseXor <src>
//
// BitwiseXor register <src> to accumulator.
void Interpreter::DoBitwiseXor(InterpreterAssembler* assembler) {
DoBinaryOp<BitwiseXorStub>(assembler);
DoBitwiseBinaryOp(Token::BIT_XOR, assembler);
}
// BitwiseAnd <src>
//
// BitwiseAnd register <src> to accumulator.
void Interpreter::DoBitwiseAnd(InterpreterAssembler* assembler) {
DoBinaryOp<BitwiseAndStub>(assembler);
DoBitwiseBinaryOp(Token::BIT_AND, assembler);
}
// ShiftLeft <src>
......@@ -839,7 +911,7 @@ void Interpreter::DoBitwiseAnd(InterpreterAssembler* assembler) {
// before the operation. 5 lsb bits from the accumulator are used as count
// i.e. <src> << (accumulator & 0x1F).
void Interpreter::DoShiftLeft(InterpreterAssembler* assembler) {
DoBinaryOp<ShiftLeftStub>(assembler);
DoBitwiseBinaryOp(Token::SHL, assembler);
}
// ShiftRight <src>
......@@ -849,7 +921,7 @@ void Interpreter::DoShiftLeft(InterpreterAssembler* assembler) {
// accumulator to uint32 before the operation. 5 lsb bits from the accumulator
// are used as count i.e. <src> >> (accumulator & 0x1F).
void Interpreter::DoShiftRight(InterpreterAssembler* assembler) {
DoBinaryOp<ShiftRightStub>(assembler);
DoBitwiseBinaryOp(Token::SAR, assembler);
}
// ShiftRightLogical <src>
......@@ -859,7 +931,7 @@ void Interpreter::DoShiftRight(InterpreterAssembler* assembler) {
// uint32 before the operation 5 lsb bits from the accumulator are used as
// count i.e. <src> << (accumulator & 0x1F).
void Interpreter::DoShiftRightLogical(InterpreterAssembler* assembler) {
DoBinaryOp<ShiftRightLogicalStub>(assembler);
DoBitwiseBinaryOp(Token::SHR, assembler);
}
// AddSmi <imm> <reg>
......
......@@ -83,6 +83,11 @@ class Interpreter {
template <class Generator>
void DoBinaryOpWithFeedback(InterpreterAssembler* assembler);
// Generates code to perform the bitwise binary operation corresponding to
// |bitwise_op| while gathering type feedback.
void DoBitwiseBinaryOp(Token::Value bitwise_op,
InterpreterAssembler* assembler);
// Generates code to perform the binary operation via |Generator| using
// an immediate value rather the accumulator as the rhs operand.
template <class Generator>
......
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