| 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..87324d4c4379dea9cc5bf74328008ead9451bb60 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(const BytecodeArrayBuilder& array_builder)
|
| + : 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:
|
| + const BytecodeArrayBuilder& array_builder_;
|
| +};
|
| +
|
| +
|
| 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;
|
| }
|
| }
|
|
|