Index: src/interpreter/bytecode-array-builder.cc |
diff --git a/src/interpreter/bytecode-array-builder.cc b/src/interpreter/bytecode-array-builder.cc |
index c0de7c0bb1303f76f4cbb893d55efdd497a4b2df..d54b3bb00a0d46bb84a48258f32fa362e53263e4 100644 |
--- a/src/interpreter/bytecode-array-builder.cc |
+++ b/src/interpreter/bytecode-array-builder.cc |
@@ -8,6 +8,53 @@ namespace v8 { |
namespace internal { |
namespace interpreter { |
+class BytecodeArrayBuilder::PreviousBytecodeHelper { |
+ public: |
+ explicit PreviousBytecodeHelper(BytecodeArrayBuilder& array_builder) |
oth
2015/11/24 13:49:26
The array_builder argument and member should be co
mythria
2015/11/24 14:33:06
Done.
|
+ : array_builder(array_builder) {} |
+ |
+ Bytecode GetBytecode() const { |
+ // Returns the previous bytecode in the same basicblock. If there is none it |
+ // returns Bytecode::kLast. |
+ if (!array_builder.LastBytecodeInSameBlock()) { |
+ return Bytecode::kLast; |
+ } |
+ return Bytecodes::FromByte( |
+ array_builder.bytecodes()->at(array_builder.last_bytecode_start_)); |
+ } |
+ |
+ uint32_t GetOperand(int operand_index) const { |
+ Bytecode bytecode = GetBytecode(); |
+ DCHECK_GE(operand_index, 0); |
+ DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode)); |
+ size_t operand_offset = |
+ array_builder.last_bytecode_start_ + |
+ Bytecodes::GetOperandOffset(bytecode, operand_index); |
+ OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index); |
+ switch (size) { |
+ default: |
+ case OperandSize::kNone: |
+ UNREACHABLE(); |
+ case OperandSize::kByte: |
+ return static_cast<uint32_t>( |
+ array_builder.bytecodes()->at(operand_offset)); |
+ case OperandSize::kShort: |
+ uint16_t operand = |
+ (array_builder.bytecodes()->at(operand_offset) << 8) + |
+ array_builder.bytecodes()->at(operand_offset + 1); |
+ return static_cast<uint32_t>(operand); |
+ } |
+ } |
+ |
+ Handle<Object> GetConstantForIndexOperand(int operand_index) const { |
+ return array_builder.constants_.at(GetOperand(operand_index)); |
+ } |
+ |
+ private: |
+ BytecodeArrayBuilder& array_builder; |
oth
2015/11/24 13:49:26
Coding style is for members of a class to end with
mythria
2015/11/24 14:33:06
Done.
|
+}; |
+ |
+ |
BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone) |
: isolate_(isolate), |
zone_(zone), |
@@ -277,6 +324,16 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() { |
} |
+BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBooleanConstant(bool value) { |
+ if (value) { |
+ LoadTrue(); |
+ } else { |
+ LoadFalse(); |
+ } |
+ return *this; |
+} |
+ |
+ |
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( |
Register reg) { |
if (!IsRegisterInAccumulator(reg)) { |
@@ -513,15 +570,11 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { |
bool BytecodeArrayBuilder::NeedToBooleanCast() { |
- if (!LastBytecodeInSameBlock()) { |
- // If the previous bytecode was from a different block return false. |
- return true; |
- } |
- |
- // If the previous bytecode puts a boolean in the accumulator return true. |
- switch (Bytecodes::FromByte(bytecodes()->at(last_bytecode_start_))) { |
+ PreviousBytecodeHelper previous_bytecode(*this); |
+ switch (previous_bytecode.GetBytecode()) { |
case Bytecode::kToBoolean: |
UNREACHABLE(); |
+ // If the previous bytecode puts a boolean in the accumulator return true. |
case Bytecode::kLdaTrue: |
case Bytecode::kLdaFalse: |
case Bytecode::kLogicalNot: |
@@ -537,6 +590,8 @@ bool BytecodeArrayBuilder::NeedToBooleanCast() { |
case Bytecode::kTestIn: |
case Bytecode::kForInDone: |
return false; |
+ // Also handles the case where the previous bytecode was in a different |
+ // block. |
default: |
return true; |
} |
@@ -544,10 +599,28 @@ bool BytecodeArrayBuilder::NeedToBooleanCast() { |
BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToBoolean() { |
+ PreviousBytecodeHelper previous_bytecode(*this); |
// If the previous bytecode puts a boolean in the accumulator |
// there is no need to emit an instruction. |
if (NeedToBooleanCast()) { |
- Output(Bytecode::kToBoolean); |
+ switch (previous_bytecode.GetBytecode()) { |
+ // If the previous bytecode is a constant evaluate it and return false. |
+ case Bytecode::kLdaZero: { |
+ LoadFalse(); |
+ break; |
+ } |
+ case Bytecode::kLdaSmi8: { |
+ LoadBooleanConstant(previous_bytecode.GetOperand(0) != 0); |
+ break; |
+ } |
+ case Bytecode::kLdaConstant: { |
+ Handle<Object> object = previous_bytecode.GetConstantForIndexOperand(0); |
+ LoadBooleanConstant(object->BooleanValue()); |
+ break; |
+ } |
+ default: |
+ Output(Bytecode::kToBoolean); |
+ } |
} |
return *this; |
} |
@@ -560,6 +633,20 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToJSObject() { |
BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() { |
+ PreviousBytecodeHelper previous_bytecode(*this); |
+ switch (previous_bytecode.GetBytecode()) { |
+ case Bytecode::kLdaConstantWide: |
+ case Bytecode::kLdaConstant: { |
+ Handle<Object> object = previous_bytecode.GetConstantForIndexOperand(0); |
+ if (object->IsName()) return *this; |
+ break; |
+ } |
+ case Bytecode::kToName: |
+ case Bytecode::kTypeOf: |
+ return *this; |
+ default: |
+ break; |
+ } |
Output(Bytecode::kToName); |
return *this; |
} |
@@ -991,14 +1078,10 @@ bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const { |
bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) { |
- if (!LastBytecodeInSameBlock()) return false; |
- Bytecode previous_bytecode = |
- Bytecodes::FromByte(bytecodes()->at(last_bytecode_start_)); |
- if (previous_bytecode == Bytecode::kLdar || |
- previous_bytecode == Bytecode::kStar) { |
- size_t operand_offset = last_bytecode_start_ + |
- Bytecodes::GetOperandOffset(previous_bytecode, 0); |
- if (reg == Register::FromOperand(bytecodes()->at(operand_offset))) { |
+ PreviousBytecodeHelper previous_bytecode(*this); |
+ if (previous_bytecode.GetBytecode() == Bytecode::kLdar || |
+ previous_bytecode.GetBytecode() == Bytecode::kStar) { |
+ if (reg == Register::FromOperand(previous_bytecode.GetOperand(0))) { |
return true; |
} |
} |