Commit 63ea19ba authored by klaasb's avatar klaasb Committed by Commit bot

[interpreter] Add output register to ToName

ToName was always generated with a subsequent Star, fuse them.
Requires a few changes in the peephole optimizer as ToName cannot be
elided as easily, but must be replaced by Star.

BUG=v8:4280
LOG=n

Review-Url: https://codereview.chromium.org/2169813002
Cr-Commit-Position: refs/heads/master@{#38019}
parent 5c8cb168
......@@ -1304,18 +1304,19 @@ void BytecodeGraphBuilder::VisitTestInstanceOf() {
BuildCompareOp(javascript()->InstanceOf());
}
void BytecodeGraphBuilder::BuildCastOperator(const Operator* js_op) {
FrameStateBeforeAndAfter states(this);
Node* node = NewNode(js_op, environment()->LookupAccumulator());
environment()->BindAccumulator(node, &states);
}
void BytecodeGraphBuilder::VisitToName() {
BuildCastOperator(javascript()->ToName());
FrameStateBeforeAndAfter states(this);
Node* value =
NewNode(javascript()->ToName(), environment()->LookupAccumulator());
environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value,
&states);
}
void BytecodeGraphBuilder::VisitToObject() {
BuildCastOperator(javascript()->ToObject());
FrameStateBeforeAndAfter states(this);
Node* node =
NewNode(javascript()->ToObject(), environment()->LookupAccumulator());
environment()->BindAccumulator(node, &states);
}
void BytecodeGraphBuilder::VisitToNumber() {
......
......@@ -128,7 +128,6 @@ class BytecodeGraphBuilder {
void BuildBinaryOpWithImmediate(const Operator* op);
void BuildCompareOp(const Operator* op);
void BuildDelete(LanguageMode language_mode);
void BuildCastOperator(const Operator* op);
void BuildForInPrepare();
void BuildForInNext();
void BuildInvokeIntrinsic();
......
......@@ -388,8 +388,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToJSObject() {
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() {
Output(Bytecode::kToName);
BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName(
Register out) {
Output(Bytecode::kToName, RegisterOperand(out));
return *this;
}
......
......@@ -212,11 +212,12 @@ class BytecodeArrayBuilder final : public ZoneObject {
// Tests.
BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg);
// Casts.
// Casts accumulator and stores result in accumulator.
BytecodeArrayBuilder& CastAccumulatorToBoolean();
BytecodeArrayBuilder& CastAccumulatorToJSObject();
BytecodeArrayBuilder& CastAccumulatorToName();
// Does not update the accumulator but stores to |out| instead.
// Casts accumulator and stores result in register |out|.
BytecodeArrayBuilder& CastAccumulatorToName(Register out);
BytecodeArrayBuilder& CastAccumulatorToNumber(Register out);
// Flow Control.
......
......@@ -1448,7 +1448,7 @@ void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
}
VisitForAccumulatorValue(property->key());
builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
builder()->CastAccumulatorToName(key);
// The static prototype property is read only. We handle the non computed
// property name case in the parser. Since this is the only case where we
// need to check for an own read only property we special case this so we do
......@@ -1734,7 +1734,7 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
builder()->MoveRegister(literal, literal_argument);
VisitForAccumulatorValue(property->key());
builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
builder()->CastAccumulatorToName(key);
VisitForAccumulatorValue(property->value());
builder()->StoreAccumulatorInRegister(value);
VisitSetHomeObject(value, literal, property);
......
......@@ -221,18 +221,6 @@ void BytecodePeepholeOptimizer::ElideCurrentIfOperand0MatchesAction(
}
}
void BytecodePeepholeOptimizer::ElideCurrentIfLoadingNameConstantAction(
BytecodeNode* const node, const PeepholeActionAndData* action_data) {
DCHECK_EQ(last()->bytecode(), Bytecode::kLdaConstant);
DCHECK(!Bytecodes::IsJump(node->bytecode()));
if (GetConstantForIndexOperand(last(), 0)->IsName()) {
ElideCurrentAction(node);
} else {
DefaultAction(node);
}
}
void BytecodePeepholeOptimizer::ElideLastAction(
BytecodeNode* const node, const PeepholeActionAndData* action_data) {
DCHECK(LastIsValid());
......@@ -256,7 +244,7 @@ void BytecodePeepholeOptimizer::ChangeBytecodeAction(
DCHECK(LastIsValid());
DCHECK(!Bytecodes::IsJump(node->bytecode()));
node->set_bytecode(action_data->bytecode);
node->replace_bytecode(action_data->bytecode);
DefaultAction(node);
}
......@@ -301,6 +289,17 @@ void BytecodePeepholeOptimizer::
}
}
void BytecodePeepholeOptimizer::TransformToStarIfLoadingNameConstantAction(
BytecodeNode* const node, const PeepholeActionAndData* action_data) {
DCHECK_EQ(last()->bytecode(), Bytecode::kLdaConstant);
DCHECK(!Bytecodes::IsJump(node->bytecode()));
if (GetConstantForIndexOperand(last(), 0)->IsName()) {
node->replace_bytecode(Bytecode::kStar);
}
DefaultAction(node);
}
void BytecodePeepholeOptimizer::DefaultJumpAction(
BytecodeNode* const node, const PeepholeActionAndData* action_data) {
DCHECK(LastIsValid());
......
......@@ -11,18 +11,18 @@ namespace v8 {
namespace internal {
namespace interpreter {
#define PEEPHOLE_NON_JUMP_ACTION_LIST(V) \
V(DefaultAction) \
V(UpdateLastAction) \
V(UpdateLastIfSourceInfoPresentAction) \
V(ElideCurrentAction) \
V(ElideCurrentIfOperand0MatchesAction) \
V(ElideCurrentIfLoadingNameConstantAction) \
V(ElideLastAction) \
V(ChangeBytecodeAction) \
V(TransformLdaStarToLdrLdarAction) \
V(TransformLdaSmiBinaryOpToBinaryOpWithSmiAction) \
V(TransformLdaZeroBinaryOpToBinaryOpWithZeroAction)
#define PEEPHOLE_NON_JUMP_ACTION_LIST(V) \
V(DefaultAction) \
V(UpdateLastAction) \
V(UpdateLastIfSourceInfoPresentAction) \
V(ElideCurrentAction) \
V(ElideCurrentIfOperand0MatchesAction) \
V(ElideLastAction) \
V(ChangeBytecodeAction) \
V(TransformLdaStarToLdrLdarAction) \
V(TransformLdaSmiBinaryOpToBinaryOpWithSmiAction) \
V(TransformLdaZeroBinaryOpToBinaryOpWithZeroAction) \
V(TransformToStarIfLoadingNameConstantAction)
#define PEEPHOLE_JUMP_ACTION_LIST(V) \
V(DefaultJumpAction) \
......
......@@ -153,6 +153,12 @@ class BytecodeNode final : ZoneObject {
BytecodeNode(const BytecodeNode& other);
BytecodeNode& operator=(const BytecodeNode& other);
// Replace the bytecode of this node with |bytecode| and keep the operands.
void replace_bytecode(Bytecode bytecode) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode_),
Bytecodes::NumberOfOperands(bytecode));
bytecode_ = bytecode;
}
void set_bytecode(Bytecode bytecode) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0);
bytecode_ = bytecode;
......
......@@ -505,7 +505,7 @@ bool Bytecodes::IsPrefixScalingBytecode(Bytecode bytecode) {
// static
bool Bytecodes::PutsNameInAccumulator(Bytecode bytecode) {
return bytecode == Bytecode::kToName || bytecode == Bytecode::kTypeOf;
return bytecode == Bytecode::kTypeOf;
}
// static
......
......@@ -211,7 +211,7 @@ namespace interpreter {
V(TestIn, AccumulatorUse::kReadWrite, OperandType::kReg) \
\
/* Cast operators */ \
V(ToName, AccumulatorUse::kReadWrite) \
V(ToName, AccumulatorUse::kRead, OperandType::kRegOut) \
V(ToNumber, AccumulatorUse::kRead, OperandType::kRegOut) \
V(ToObject, AccumulatorUse::kReadWrite) \
\
......
......@@ -1026,7 +1026,9 @@ void Interpreter::DoUnaryOp(InterpreterAssembler* assembler) {
//
// Cast the object referenced by the accumulator to a name.
void Interpreter::DoToName(InterpreterAssembler* assembler) {
DoUnaryOp(CodeFactory::ToName(isolate_), assembler);
Node* result = BuildUnaryOp(CodeFactory::ToName(isolate_), assembler);
__ StoreRegister(result, __ BytecodeOperandReg(0));
__ Dispatch();
}
// ToNumber
......
......@@ -106,13 +106,14 @@ PeepholeActionAndData PeepholeActionTableWriter::LookupActionAndData(
}
}
// ToName optimizations: remove unnecessary ToName bytecodes.
// ToName bytecodes can be replaced by Star with the same output register if
// the value in the accumulator is already a name.
if (current == Bytecode::kToName) {
if (last == Bytecode::kLdaConstant) {
return {PeepholeAction::kElideCurrentIfLoadingNameConstantAction,
return {PeepholeAction::kTransformToStarIfLoadingNameConstantAction,
Bytecode::kIllegal};
} else if (Bytecodes::PutsNameInAccumulator(last)) {
return {PeepholeAction::kElideCurrentAction, Bytecode::kIllegal};
return {PeepholeAction::kChangeBytecodeAction, Bytecode::kStar};
}
}
......
......@@ -122,7 +122,7 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 126
bytecode array length: 124
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(2),
......@@ -147,8 +147,7 @@ bytecodes: [
B(Star), R(3),
B(LdrNamedProperty), R(3), U8(3), U8(1), R(4),
/* 75 E> */ B(LdaContextSlot), R(context), U8(4),
B(ToName),
B(Star), R(6),
B(ToName), R(6),
B(CreateClosure), U8(4), U8(2),
B(Star), R(7),
B(LdaSmi), U8(2),
......@@ -158,8 +157,7 @@ bytecodes: [
B(Mov), R(4), R(5),
B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5),
/* 106 E> */ B(LdaContextSlot), R(context), U8(5),
B(ToName),
B(Star), R(6),
B(ToName), R(6),
B(LdaConstant), U8(3),
B(TestEqualStrict), R(6),
B(Mov), R(3), R(5),
......
......@@ -299,7 +299,7 @@ snippet: "
"
frame size: 7
parameter count: 1
bytecode array length: 37
bytecode array length: 36
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaConstant), U8(0),
......@@ -307,8 +307,7 @@ bytecodes: [
/* 50 S> */ B(CreateObjectLiteral), U8(1), U8(0), U8(35),
B(Star), R(1),
B(Ldar), R(0),
/* 60 E> */ B(ToName),
B(Star), R(3),
/* 60 E> */ B(ToName), R(3),
B(LdaSmi), U8(1),
B(Star), R(4),
B(LdaZero),
......@@ -333,7 +332,7 @@ snippet: "
"
frame size: 7
parameter count: 1
bytecode array length: 41
bytecode array length: 40
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaConstant), U8(0),
......@@ -342,8 +341,7 @@ bytecodes: [
B(Star), R(1),
B(Ldar), R(0),
/* 64 E> */ B(StaNamedPropertySloppy), R(1), U8(2), U8(1),
/* 68 E> */ B(ToName),
B(Star), R(3),
/* 68 E> */ B(ToName), R(3),
B(LdaSmi), U8(1),
B(Star), R(4),
B(LdaZero),
......@@ -369,7 +367,7 @@ snippet: "
"
frame size: 7
parameter count: 1
bytecode array length: 54
bytecode array length: 53
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaConstant), U8(0),
......@@ -377,8 +375,7 @@ bytecodes: [
/* 50 S> */ B(CreateObjectLiteral), U8(1), U8(1), U8(35),
B(Star), R(1),
B(Ldar), R(0),
/* 60 E> */ B(ToName),
B(Star), R(3),
/* 60 E> */ B(ToName), R(3),
B(LdaSmi), U8(1),
B(Star), R(4),
B(LdaZero),
......@@ -408,7 +405,7 @@ snippet: "
"
frame size: 7
parameter count: 1
bytecode array length: 77
bytecode array length: 76
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaConstant), U8(0),
......@@ -416,8 +413,7 @@ bytecodes: [
/* 50 S> */ B(CreateObjectLiteral), U8(1), U8(0), U8(35),
B(Star), R(1),
B(Ldar), R(0),
/* 60 E> */ B(ToName),
B(Star), R(3),
/* 60 E> */ B(ToName), R(3),
B(LdaConstant), U8(2),
B(Star), R(4),
B(LdaZero),
......
......@@ -182,7 +182,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
// Emit cast operator invocations.
builder.CastAccumulatorToNumber(reg)
.CastAccumulatorToJSObject()
.CastAccumulatorToName();
.CastAccumulatorToName(reg);
// Emit control flow. Return must be the last instruction.
BytecodeLabel start;
......
......@@ -241,7 +241,7 @@ TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatementStarRy) {
TEST_F(BytecodePeepholeOptimizerTest, LdarToName) {
BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand());
BytecodeNode second(Bytecode::kToName);
BytecodeNode second(Bytecode::kToName, Register(0).ToOperand());
optimizer()->Write(&first);
CHECK_EQ(write_count(), 0);
optimizer()->Write(&second);
......@@ -252,26 +252,18 @@ TEST_F(BytecodePeepholeOptimizerTest, LdarToName) {
CHECK_EQ(last_written(), second);
}
TEST_F(BytecodePeepholeOptimizerTest, ToNameToName) {
BytecodeNode first(Bytecode::kToName);
BytecodeNode second(Bytecode::kToName);
optimizer()->Write(&first);
optimizer()->Write(&second);
CHECK_EQ(write_count(), 0);
Flush();
CHECK_EQ(last_written(), first);
CHECK_EQ(write_count(), 1);
}
TEST_F(BytecodePeepholeOptimizerTest, TypeOfToName) {
BytecodeNode first(Bytecode::kTypeOf);
BytecodeNode second(Bytecode::kToName);
BytecodeNode second(Bytecode::kToName, Register(0).ToOperand());
optimizer()->Write(&first);
optimizer()->Write(&second);
CHECK_EQ(write_count(), 0);
Flush();
optimizer()->Write(&second);
CHECK_EQ(write_count(), 1);
CHECK_EQ(last_written(), first);
Flush();
CHECK_EQ(write_count(), 2);
CHECK_EQ(last_written(), second);
CHECK_EQ(last_written().bytecode(), Bytecode::kStar);
}
TEST_F(BytecodePeepholeOptimizerTest, LdaConstantStringToName) {
......@@ -279,20 +271,23 @@ TEST_F(BytecodePeepholeOptimizerTest, LdaConstantStringToName) {
isolate()->factory()->NewStringFromStaticChars("optimizing");
size_t index = constant_array()->Insert(word);
BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index));
BytecodeNode second(Bytecode::kToName);
BytecodeNode second(Bytecode::kToName, Register(0).ToOperand());
optimizer()->Write(&first);
optimizer()->Write(&second);
CHECK_EQ(write_count(), 0);
Flush();
optimizer()->Write(&second);
CHECK_EQ(write_count(), 1);
CHECK_EQ(last_written(), first);
Flush();
CHECK_EQ(write_count(), 2);
CHECK_EQ(last_written(), second);
CHECK_EQ(last_written().bytecode(), Bytecode::kStar);
}
TEST_F(BytecodePeepholeOptimizerTest, LdaConstantNumberToName) {
Handle<Object> word = isolate()->factory()->NewNumber(0.380);
size_t index = constant_array()->Insert(word);
BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index));
BytecodeNode second(Bytecode::kToName);
BytecodeNode second(Bytecode::kToName, Register(0).ToOperand());
optimizer()->Write(&first);
CHECK_EQ(write_count(), 0);
optimizer()->Write(&second);
......
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