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