Chromium Code Reviews| Index: src/interpreter/bytecode-array-builder.cc |
| diff --git a/src/interpreter/bytecode-array-builder.cc b/src/interpreter/bytecode-array-builder.cc |
| index dfa395095abaf72da5407a415b7af5edb58b1410..4c483ee36b8953569d9762b7a44fddeba1f92524 100644 |
| --- a/src/interpreter/bytecode-array-builder.cc |
| +++ b/src/interpreter/bytecode-array-builder.cc |
| @@ -31,7 +31,8 @@ BytecodeArrayBuilder::BytecodeArrayBuilder( |
| register_allocator_(fixed_register_count()), |
| bytecode_array_writer_(zone, &constant_array_builder_, |
| source_position_mode), |
| - pipeline_(&bytecode_array_writer_) { |
| + pipeline_(&bytecode_array_writer_), |
| + register_optimizer_(nullptr) { |
| DCHECK_GE(parameter_count_, 0); |
| DCHECK_GE(context_register_count_, 0); |
| DCHECK_GE(local_register_count_, 0); |
| @@ -45,7 +46,7 @@ BytecodeArrayBuilder::BytecodeArrayBuilder( |
| } |
| if (FLAG_ignition_reo) { |
| - pipeline_ = new (zone) BytecodeRegisterOptimizer( |
| + register_optimizer_ = new (zone) BytecodeRegisterOptimizer( |
| zone, ®ister_allocator_, fixed_register_count(), parameter_count, |
| pipeline_); |
|
Leszek Swirski
2016/10/07 08:34:10
I don't love that both this class and the register
rmcilroy
2016/10/24 16:27:55
As discussed offline, this isn't super easy. Let's
|
| } |
| @@ -75,108 +76,214 @@ Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray(Isolate* isolate) { |
| DCHECK(!bytecode_generated_); |
| bytecode_generated_ = true; |
| + int register_count = total_register_count(); |
| + |
| + if (register_optimizer_) { |
| + register_optimizer_->Flush(); |
| + register_count = register_optimizer_->maxiumum_register_index() + 1; |
| + } |
| + |
| Handle<FixedArray> handler_table = |
| handler_table_builder()->ToHandlerTable(isolate); |
| - return pipeline_->ToBytecodeArray(isolate, total_register_count(), |
| - parameter_count(), handler_table); |
| -} |
| - |
| -void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
| - uint32_t operand1, uint32_t operand2, |
| - uint32_t operand3) { |
| - DCHECK(OperandsAreValid(bytecode, 4, operand0, operand1, operand2, operand3)); |
| - BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, |
| - &latest_source_info_); |
| - pipeline()->Write(&node); |
| + return pipeline_->ToBytecodeArray(isolate, register_count, parameter_count(), |
| + handler_table); |
| +} |
| + |
| +BytecodeSourceInfo BytecodeArrayBuilder::CurrentSourcePosition( |
| + Bytecode bytecode) { |
| + BytecodeSourceInfo source_position; |
| + if (latest_source_info_.is_valid()) { |
| + // Statement positions need to be emitted immediately. Expression |
| + // positions can be pushed back until a bytecode is found that can |
| + // throw (if expression position filtering is turned on). We only |
| + // invalidate the existing source position information if it is used. |
| + if (latest_source_info_.is_statement() || |
| + !FLAG_ignition_filter_expression_positions || |
| + !Bytecodes::IsWithoutExternalSideEffects(bytecode)) { |
|
Leszek Swirski
2016/10/06 10:35:17
not sure what effect this would have on execution
rmcilroy
2016/10/06 17:14:43
Yeah, I made IsWithoutExternalSideEffects a conste
Leszek Swirski
2016/10/07 08:34:10
Oh yeah, inlining, stupid me. Did you check if it
rmcilroy
2016/10/24 16:27:55
Yeah it is, at least for the functions which appea
|
| + source_position.Clone(latest_source_info_); |
| + latest_source_info_.set_invalid(); |
|
Leszek Swirski
2016/10/06 10:35:17
maybe not for this CL, but this could be done a bi
rmcilroy
2016/10/06 17:14:43
This caused a bunch of issues elsewhere with the d
Leszek Swirski
2016/10/07 08:34:10
Fair enough, I might put that refactor on my backl
|
| + } |
| + } |
| + return source_position; |
| } |
| -void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
| - uint32_t operand1, uint32_t operand2) { |
| - DCHECK(OperandsAreValid(bytecode, 3, operand0, operand1, operand2)); |
| - BytecodeNode node(bytecode, operand0, operand1, operand2, |
| - &latest_source_info_); |
| - pipeline()->Write(&node); |
| -} |
| +namespace { |
| -void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0, |
| - uint32_t operand1) { |
| - DCHECK(OperandsAreValid(bytecode, 2, operand0, operand1)); |
| - BytecodeNode node(bytecode, operand0, operand1, &latest_source_info_); |
| - pipeline()->Write(&node); |
| -} |
| +template <OperandTypeInfo type_info> |
| +class UnsignedOperandHelper { |
| + public: |
| + INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, size_t value)) { |
| + DCHECK(IsValid(value)); |
| + return static_cast<uint32_t>(value); |
| + } |
| -void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) { |
| - DCHECK(OperandsAreValid(bytecode, 1, operand0)); |
| - BytecodeNode node(bytecode, operand0, &latest_source_info_); |
| - pipeline()->Write(&node); |
| -} |
| + static uint32_t Convert(BytecodeArrayBuilder* builder, int value) { |
|
Leszek Swirski
2016/10/06 10:35:17
why not INLINE?
rmcilroy
2016/10/06 17:14:43
Done.
|
| + DCHECK_GE(value, 0); |
| + return Convert(builder, static_cast<size_t>(value)); |
| + } |
| -void BytecodeArrayBuilder::Output(Bytecode bytecode) { |
| - DCHECK(OperandsAreValid(bytecode, 0)); |
| - BytecodeNode node(bytecode, &latest_source_info_); |
| - pipeline()->Write(&node); |
| -} |
| + static bool IsValid(size_t value) { |
|
Leszek Swirski
2016/10/06 10:35:17
maybe private?
rmcilroy
2016/10/06 17:14:43
Done.
|
| + switch (type_info) { |
| + case OperandTypeInfo::kFixedUnsignedByte: |
| + return value <= kMaxUInt8; |
| + case OperandTypeInfo::kFixedUnsignedShort: |
| + return value <= kMaxUInt16; |
| + case OperandTypeInfo::kScalableUnsignedByte: |
| + return value <= kMaxUInt32; |
| + default: |
| + UNREACHABLE(); |
| + return false; |
| + } |
| + } |
| +}; |
| + |
| +template <OperandType> |
| +class OperandHelper {}; |
| + |
| +#define DEFINE_UNSIGNED_OPERAND_HELPER(Name, Type) \ |
| + template <> \ |
| + class OperandHelper<OperandType::k##Name> \ |
| + : public UnsignedOperandHelper<Type> {}; |
| +UNSIGNED_SCALAR_OPERAND_TYPE_LIST(DEFINE_UNSIGNED_OPERAND_HELPER) |
| +#undef DEFINE_UNSIGNED_OPERAND_HELPER |
| + |
| +template <> |
| +class OperandHelper<OperandType::kImm> { |
| + public: |
| + INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) { |
| + return static_cast<uint32_t>(value); |
| + } |
| +}; |
| -void BytecodeArrayBuilder::OutputJump(Bytecode bytecode, BytecodeLabel* label) { |
| - BytecodeNode node(bytecode, 0, &latest_source_info_); |
| - pipeline_->WriteJump(&node, label); |
| - LeaveBasicBlock(); |
| -} |
| +template <> |
| +class OperandHelper<OperandType::kReg> { |
| + public: |
| + INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) { |
| + return builder->GetInputRegisterOperand(reg); |
| + } |
| +}; |
| + |
| +template <> |
| +class OperandHelper<OperandType::kRegList> { |
| + public: |
| + INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, |
| + RegisterList reg_list)) { |
| + return builder->GetInputRegisterListOperand(reg_list); |
| + } |
| +}; |
| + |
| +template <> |
| +class OperandHelper<OperandType::kRegPair> { |
| + public: |
| + INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, |
| + RegisterList reg_list)) { |
| + DCHECK_EQ(reg_list.register_count(), 2); |
| + return builder->GetInputRegisterListOperand(reg_list); |
| + } |
| +}; |
| -void BytecodeArrayBuilder::OutputJump(Bytecode bytecode, uint32_t operand0, |
| - BytecodeLabel* label) { |
| - BytecodeNode node(bytecode, 0, operand0, &latest_source_info_); |
| - pipeline_->WriteJump(&node, label); |
| - LeaveBasicBlock(); |
| -} |
| +template <> |
| +class OperandHelper<OperandType::kRegOut> { |
| + public: |
| + INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, Register reg)) { |
| + return builder->GetOutputRegisterOperand(reg); |
| + } |
| +}; |
| + |
| +template <> |
| +class OperandHelper<OperandType::kRegOutPair> { |
| + public: |
| + INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, |
| + RegisterList reg_list)) { |
| + DCHECK_EQ(2, reg_list.register_count()); |
| + return builder->GetOutputRegisterListOperand(reg_list); |
| + } |
| +}; |
| + |
| +template <> |
| +class OperandHelper<OperandType::kRegOutTriple> { |
| + public: |
| + INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, |
| + RegisterList reg_list)) { |
| + DCHECK_EQ(3, reg_list.register_count()); |
| + return builder->GetOutputRegisterListOperand(reg_list); |
| + } |
| +}; |
| + |
| +template <OperandType... operand_types> |
| +class BytecodeNodeBuilder { |
| + public: |
| + template <typename... Operands> |
| + INLINE(static BytecodeNode Make(Bytecode bytecode, Operands... operands, |
| + BytecodeSourceInfo source_info, |
| + BytecodeArrayBuilder* builder)) { |
| + builder->PrepareToOutputBytecode(bytecode); |
| + return BytecodeNode( |
| + bytecode, OperandHelper<operand_types>::Convert(builder, operands)..., |
|
Leszek Swirski
2016/10/06 10:35:17
It might be helpful for future readers of this cod
rmcilroy
2016/10/06 17:14:43
Done.
|
| + source_info); |
| + } |
| +}; |
| + |
| +} // namespace |
| + |
| +#define DEFINE_BYTECODE_OUTPUT(name, accumulator_use, ...) \ |
| + template <typename... Operands> \ |
| + void BytecodeArrayBuilder::Output##name(Operands... operands) { \ |
| + BytecodeNode node(BytecodeNodeBuilder<__VA_ARGS__>::Make<Operands...>( \ |
| + Bytecode::k##name, operands..., \ |
| + CurrentSourcePosition(Bytecode::k##name), this)); \ |
| + pipeline()->Write(&node); \ |
| + } \ |
| + \ |
| + template <typename... Operands> \ |
| + void BytecodeArrayBuilder::Output##name(BytecodeLabel* label, \ |
| + Operands... operands) { \ |
| + DCHECK(Bytecodes::IsJump(Bytecode::k##name)); \ |
| + BytecodeNode node(BytecodeNodeBuilder<__VA_ARGS__>::Make<Operands...>( \ |
| + Bytecode::k##name, operands..., \ |
| + CurrentSourcePosition(Bytecode::k##name), this)); \ |
| + pipeline()->WriteJump(&node, label); \ |
| + LeaveBasicBlock(); \ |
| + } |
| +BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT) |
| +#undef DEFINE_BYTECODE_OUTPUT |
| BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, |
| Register reg, |
| int feedback_slot) { |
| switch (op) { |
| case Token::Value::ADD: |
| - Output(Bytecode::kAdd, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputAdd(reg, feedback_slot); |
| break; |
| case Token::Value::SUB: |
| - Output(Bytecode::kSub, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputSub(reg, feedback_slot); |
| break; |
| case Token::Value::MUL: |
| - Output(Bytecode::kMul, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputMul(reg, feedback_slot); |
| break; |
| case Token::Value::DIV: |
| - Output(Bytecode::kDiv, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputDiv(reg, feedback_slot); |
| break; |
| case Token::Value::MOD: |
| - Output(Bytecode::kMod, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputMod(reg, feedback_slot); |
| break; |
| case Token::Value::BIT_OR: |
| - Output(Bytecode::kBitwiseOr, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputBitwiseOr(reg, feedback_slot); |
| break; |
| case Token::Value::BIT_XOR: |
| - Output(Bytecode::kBitwiseXor, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputBitwiseXor(reg, feedback_slot); |
| break; |
| case Token::Value::BIT_AND: |
| - Output(Bytecode::kBitwiseAnd, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputBitwiseAnd(reg, feedback_slot); |
| break; |
| case Token::Value::SHL: |
| - Output(Bytecode::kShiftLeft, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputShiftLeft(reg, feedback_slot); |
| break; |
| case Token::Value::SAR: |
| - Output(Bytecode::kShiftRight, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputShiftRight(reg, feedback_slot); |
| break; |
| case Token::Value::SHR: |
| - Output(Bytecode::kShiftRightLogical, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputShiftRightLogical(reg, feedback_slot); |
| break; |
| default: |
| UNREACHABLE(); |
| @@ -187,21 +294,21 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op, |
| BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, |
| int feedback_slot) { |
| if (op == Token::Value::ADD) { |
| - Output(Bytecode::kInc, UnsignedOperand(feedback_slot)); |
| + OutputInc(feedback_slot); |
| } else { |
| DCHECK_EQ(op, Token::Value::SUB); |
| - Output(Bytecode::kDec, UnsignedOperand(feedback_slot)); |
| + OutputDec(feedback_slot); |
| } |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { |
| - Output(Bytecode::kToBooleanLogicalNot); |
| + OutputToBooleanLogicalNot(); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() { |
| - Output(Bytecode::kTypeOf); |
| + OutputTypeOf(); |
| return *this; |
| } |
| @@ -209,38 +316,31 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( |
| Token::Value op, Register reg, int feedback_slot) { |
| switch (op) { |
| case Token::Value::EQ: |
| - Output(Bytecode::kTestEqual, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputTestEqual(reg, feedback_slot); |
| break; |
| case Token::Value::NE: |
| - Output(Bytecode::kTestNotEqual, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputTestNotEqual(reg, feedback_slot); |
| break; |
| case Token::Value::EQ_STRICT: |
| - Output(Bytecode::kTestEqualStrict, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputTestEqualStrict(reg, feedback_slot); |
| break; |
| case Token::Value::LT: |
| - Output(Bytecode::kTestLessThan, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputTestLessThan(reg, feedback_slot); |
| break; |
| case Token::Value::GT: |
| - Output(Bytecode::kTestGreaterThan, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputTestGreaterThan(reg, feedback_slot); |
| break; |
| case Token::Value::LTE: |
| - Output(Bytecode::kTestLessThanOrEqual, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputTestLessThanOrEqual(reg, feedback_slot); |
| break; |
| case Token::Value::GTE: |
| - Output(Bytecode::kTestGreaterThanOrEqual, RegisterOperand(reg), |
| - UnsignedOperand(feedback_slot)); |
| + OutputTestGreaterThanOrEqual(reg, feedback_slot); |
| break; |
| case Token::Value::INSTANCEOF: |
| - Output(Bytecode::kTestInstanceOf, RegisterOperand(reg)); |
| + OutputTestInstanceOf(reg); |
| break; |
| case Token::Value::IN: |
| - Output(Bytecode::kTestIn, RegisterOperand(reg)); |
| + OutputTestIn(reg); |
| break; |
| default: |
| UNREACHABLE(); |
| @@ -250,7 +350,7 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry( |
| size_t entry) { |
| - Output(Bytecode::kLdaConstant, UnsignedOperand(entry)); |
| + OutputLdaConstant(entry); |
| return *this; |
| } |
| @@ -258,70 +358,82 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral( |
| v8::internal::Smi* smi) { |
| int32_t raw_smi = smi->value(); |
| if (raw_smi == 0) { |
| - Output(Bytecode::kLdaZero); |
| + OutputLdaZero(); |
| } else { |
| - Output(Bytecode::kLdaSmi, SignedOperand(raw_smi)); |
| + OutputLdaSmi(raw_smi); |
| } |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) { |
| size_t entry = GetConstantPoolEntry(object); |
| - Output(Bytecode::kLdaConstant, UnsignedOperand(entry)); |
| + OutputLdaConstant(entry); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() { |
| - Output(Bytecode::kLdaUndefined); |
| + OutputLdaUndefined(); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() { |
| - Output(Bytecode::kLdaNull); |
| + OutputLdaNull(); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() { |
| - Output(Bytecode::kLdaTheHole); |
| + OutputLdaTheHole(); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() { |
| - Output(Bytecode::kLdaTrue); |
| + OutputLdaTrue(); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() { |
| - Output(Bytecode::kLdaFalse); |
| + OutputLdaFalse(); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( |
| Register reg) { |
| - Output(Bytecode::kLdar, RegisterOperand(reg)); |
| + if (register_optimizer_) { |
| + register_optimizer_->DoLdar(reg, CurrentSourcePosition(Bytecode::kLdar)); |
| + } else { |
| + OutputLdar(reg); |
| + } |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( |
| Register reg) { |
| - Output(Bytecode::kStar, RegisterOperand(reg)); |
| + if (register_optimizer_) { |
| + register_optimizer_->DoStar(reg, CurrentSourcePosition(Bytecode::kStar)); |
| + } else { |
| + OutputStar(reg); |
| + } |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from, |
| Register to) { |
| DCHECK(from != to); |
| - Output(Bytecode::kMov, RegisterOperand(from), RegisterOperand(to)); |
| + if (register_optimizer_) { |
| + register_optimizer_->DoMov(from, to, CurrentSourcePosition(Bytecode::kMov)); |
| + } else { |
| + OutputMov(from, to); |
| + } |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(int feedback_slot, |
| TypeofMode typeof_mode) { |
| if (typeof_mode == INSIDE_TYPEOF) { |
| - Output(Bytecode::kLdaGlobalInsideTypeof, feedback_slot); |
| + OutputLdaGlobalInsideTypeof(feedback_slot); |
| } else { |
| DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); |
| - Output(Bytecode::kLdaGlobal, UnsignedOperand(feedback_slot)); |
| + OutputLdaGlobal(feedback_slot); |
| } |
| return *this; |
| } |
| @@ -330,12 +442,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( |
| const Handle<String> name, int feedback_slot, LanguageMode language_mode) { |
| size_t name_index = GetConstantPoolEntry(name); |
| if (language_mode == SLOPPY) { |
| - Output(Bytecode::kStaGlobalSloppy, UnsignedOperand(name_index), |
| - UnsignedOperand(feedback_slot)); |
| + OutputStaGlobalSloppy(name_index, feedback_slot); |
| } else { |
| DCHECK_EQ(language_mode, STRICT); |
| - Output(Bytecode::kStaGlobalStrict, UnsignedOperand(name_index), |
| - UnsignedOperand(feedback_slot)); |
| + OutputStaGlobalStrict(name_index, feedback_slot); |
| } |
| return *this; |
| } |
| @@ -343,16 +453,14 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, |
| int slot_index, |
| int depth) { |
| - Output(Bytecode::kLdaContextSlot, RegisterOperand(context), |
| - UnsignedOperand(slot_index), UnsignedOperand(depth)); |
| + OutputLdaContextSlot(context, slot_index, depth); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context, |
| int slot_index, |
| int depth) { |
| - Output(Bytecode::kStaContextSlot, RegisterOperand(context), |
| - UnsignedOperand(slot_index), UnsignedOperand(depth)); |
| + OutputStaContextSlot(context, slot_index, depth); |
| return *this; |
| } |
| @@ -360,10 +468,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( |
| const Handle<String> name, TypeofMode typeof_mode) { |
| size_t name_index = GetConstantPoolEntry(name); |
| if (typeof_mode == INSIDE_TYPEOF) { |
| - Output(Bytecode::kLdaLookupSlotInsideTypeof, UnsignedOperand(name_index)); |
| + OutputLdaLookupSlotInsideTypeof(name_index); |
| } else { |
| DCHECK_EQ(typeof_mode, NOT_INSIDE_TYPEOF); |
| - Output(Bytecode::kLdaLookupSlot, UnsignedOperand(name_index)); |
| + OutputLdaLookupSlot(name_index); |
| } |
| return *this; |
| } |
| @@ -371,24 +479,26 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot( |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupContextSlot( |
| const Handle<String> name, TypeofMode typeof_mode, int slot_index, |
| int depth) { |
| - Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) |
| - ? Bytecode::kLdaLookupContextSlotInsideTypeof |
| - : Bytecode::kLdaLookupContextSlot; |
| size_t name_index = GetConstantPoolEntry(name); |
| - Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(slot_index), |
| - UnsignedOperand(depth)); |
| + if (typeof_mode == INSIDE_TYPEOF) { |
| + OutputLdaLookupContextSlotInsideTypeof(name_index, slot_index, depth); |
| + } else { |
| + DCHECK(typeof_mode == NOT_INSIDE_TYPEOF); |
| + OutputLdaLookupContextSlot(name_index, slot_index, depth); |
| + } |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupGlobalSlot( |
| const Handle<String> name, TypeofMode typeof_mode, int feedback_slot, |
| int depth) { |
| - Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF) |
| - ? Bytecode::kLdaLookupGlobalSlotInsideTypeof |
| - : Bytecode::kLdaLookupGlobalSlot; |
| size_t name_index = GetConstantPoolEntry(name); |
| - Output(bytecode, UnsignedOperand(name_index), UnsignedOperand(feedback_slot), |
| - UnsignedOperand(depth)); |
| + if (typeof_mode == INSIDE_TYPEOF) { |
| + OutputLdaLookupGlobalSlotInsideTypeof(name_index, feedback_slot, depth); |
| + } else { |
| + DCHECK(typeof_mode == NOT_INSIDE_TYPEOF); |
| + OutputLdaLookupGlobalSlot(name_index, feedback_slot, depth); |
| + } |
| return *this; |
| } |
| @@ -396,10 +506,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( |
| const Handle<String> name, LanguageMode language_mode) { |
| size_t name_index = GetConstantPoolEntry(name); |
| if (language_mode == SLOPPY) { |
| - Output(Bytecode::kStaLookupSlotSloppy, UnsignedOperand(name_index)); |
| + OutputStaLookupSlotSloppy(name_index); |
| } else { |
| DCHECK_EQ(language_mode, STRICT); |
| - Output(Bytecode::kStaLookupSlotStrict, UnsignedOperand(name_index)); |
| + OutputStaLookupSlotStrict(name_index); |
| } |
| return *this; |
| } |
| @@ -407,15 +517,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot( |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty( |
| Register object, const Handle<Name> name, int feedback_slot) { |
| size_t name_index = GetConstantPoolEntry(name); |
| - Output(Bytecode::kLdaNamedProperty, RegisterOperand(object), |
| - UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); |
| + OutputLdaNamedProperty(object, name_index, feedback_slot); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty( |
| Register object, int feedback_slot) { |
| - Output(Bytecode::kLdaKeyedProperty, RegisterOperand(object), |
| - UnsignedOperand(feedback_slot)); |
| + OutputLdaKeyedProperty(object, feedback_slot); |
| return *this; |
| } |
| @@ -424,12 +532,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty( |
| LanguageMode language_mode) { |
| size_t name_index = GetConstantPoolEntry(name); |
| if (language_mode == SLOPPY) { |
| - Output(Bytecode::kStaNamedPropertySloppy, RegisterOperand(object), |
| - UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); |
| + OutputStaNamedPropertySloppy(object, name_index, feedback_slot); |
| } else { |
| DCHECK_EQ(language_mode, STRICT); |
| - Output(Bytecode::kStaNamedPropertyStrict, RegisterOperand(object), |
| - UnsignedOperand(name_index), UnsignedOperand(feedback_slot)); |
| + OutputStaNamedPropertyStrict(object, name_index, feedback_slot); |
| } |
| return *this; |
| } |
| @@ -438,27 +544,24 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty( |
| Register object, Register key, int feedback_slot, |
| LanguageMode language_mode) { |
| if (language_mode == SLOPPY) { |
| - Output(Bytecode::kStaKeyedPropertySloppy, RegisterOperand(object), |
| - RegisterOperand(key), UnsignedOperand(feedback_slot)); |
| + OutputStaKeyedPropertySloppy(object, key, feedback_slot); |
| } else { |
| DCHECK_EQ(language_mode, STRICT); |
| - Output(Bytecode::kStaKeyedPropertyStrict, RegisterOperand(object), |
| - RegisterOperand(key), UnsignedOperand(feedback_slot)); |
| + OutputStaKeyedPropertyStrict(object, key, feedback_slot); |
| } |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(size_t entry, |
| int flags) { |
| - Output(Bytecode::kCreateClosure, UnsignedOperand(entry), |
| - UnsignedOperand(flags)); |
| + OutputCreateClosure(entry, flags); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::CreateBlockContext( |
| Handle<ScopeInfo> scope_info) { |
| size_t entry = GetConstantPoolEntry(scope_info); |
| - Output(Bytecode::kCreateBlockContext, UnsignedOperand(entry)); |
| + OutputCreateBlockContext(entry); |
| return *this; |
| } |
| @@ -466,21 +569,19 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateCatchContext( |
| Register exception, Handle<String> name, Handle<ScopeInfo> scope_info) { |
| size_t name_index = GetConstantPoolEntry(name); |
| size_t scope_info_index = GetConstantPoolEntry(scope_info); |
| - Output(Bytecode::kCreateCatchContext, RegisterOperand(exception), |
| - UnsignedOperand(name_index), UnsignedOperand(scope_info_index)); |
| + OutputCreateCatchContext(exception, name_index, scope_info_index); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::CreateFunctionContext(int slots) { |
| - Output(Bytecode::kCreateFunctionContext, UnsignedOperand(slots)); |
| + OutputCreateFunctionContext(slots); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::CreateWithContext( |
| Register object, Handle<ScopeInfo> scope_info) { |
| size_t scope_info_index = GetConstantPoolEntry(scope_info); |
| - Output(Bytecode::kCreateWithContext, RegisterOperand(object), |
| - UnsignedOperand(scope_info_index)); |
| + OutputCreateWithContext(object, scope_info_index); |
| return *this; |
| } |
| @@ -488,13 +589,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( |
| CreateArgumentsType type) { |
| switch (type) { |
| case CreateArgumentsType::kMappedArguments: |
| - Output(Bytecode::kCreateMappedArguments); |
| + OutputCreateMappedArguments(); |
| break; |
| case CreateArgumentsType::kUnmappedArguments: |
| - Output(Bytecode::kCreateUnmappedArguments); |
| + OutputCreateUnmappedArguments(); |
| break; |
| case CreateArgumentsType::kRestParameter: |
| - Output(Bytecode::kCreateRestParameter); |
| + OutputCreateRestParameter(); |
| break; |
| default: |
| UNREACHABLE(); |
| @@ -505,17 +606,14 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments( |
| BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral( |
| Handle<String> pattern, int literal_index, int flags) { |
| size_t pattern_entry = GetConstantPoolEntry(pattern); |
| - Output(Bytecode::kCreateRegExpLiteral, UnsignedOperand(pattern_entry), |
| - UnsignedOperand(literal_index), UnsignedOperand(flags)); |
| + OutputCreateRegExpLiteral(pattern_entry, literal_index, flags); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral( |
| Handle<FixedArray> constant_elements, int literal_index, int flags) { |
| size_t constant_elements_entry = GetConstantPoolEntry(constant_elements); |
| - Output(Bytecode::kCreateArrayLiteral, |
| - UnsignedOperand(constant_elements_entry), |
| - UnsignedOperand(literal_index), UnsignedOperand(flags)); |
| + OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags); |
| return *this; |
| } |
| @@ -523,42 +621,43 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral( |
| Handle<FixedArray> constant_properties, int literal_index, int flags, |
| Register output) { |
| size_t constant_properties_entry = GetConstantPoolEntry(constant_properties); |
| - Output(Bytecode::kCreateObjectLiteral, |
| - UnsignedOperand(constant_properties_entry), |
| - UnsignedOperand(literal_index), UnsignedOperand(flags), |
| - RegisterOperand(output)); |
| + OutputCreateObjectLiteral(constant_properties_entry, literal_index, flags, |
| + output); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) { |
| - Output(Bytecode::kPushContext, RegisterOperand(context)); |
| + OutputPushContext(context); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) { |
| - Output(Bytecode::kPopContext, RegisterOperand(context)); |
| + OutputPopContext(context); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToObject( |
| Register out) { |
| - Output(Bytecode::kToObject, RegisterOperand(out)); |
| + OutputToObject(out); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToName( |
| Register out) { |
| - Output(Bytecode::kToName, RegisterOperand(out)); |
| + OutputToName(out); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::ConvertAccumulatorToNumber( |
| Register out) { |
| - Output(Bytecode::kToNumber, RegisterOperand(out)); |
| + OutputToNumber(out); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) { |
| + // Flush the register optimizer when binding a label to ensure all |
| + // expected registers are valid when jumping to this label. |
| + if (register_optimizer_) register_optimizer_->Flush(); |
| pipeline_->BindLabel(label); |
| LeaveBasicBlock(); |
| return *this; |
| @@ -572,42 +671,42 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { |
| - OutputJump(Bytecode::kJump, label); |
| + OutputJump(label, 0); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { |
| // The peephole optimizer attempts to simplify JumpIfToBooleanTrue |
| // to JumpIfTrue. |
| - OutputJump(Bytecode::kJumpIfToBooleanTrue, label); |
| + OutputJumpIfToBooleanTrue(label, 0); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { |
| - OutputJump(Bytecode::kJumpIfToBooleanFalse, label); |
| + OutputJumpIfToBooleanFalse(label, 0); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) { |
| - OutputJump(Bytecode::kJumpIfNull, label); |
| + OutputJumpIfNull(label, 0); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined( |
| BytecodeLabel* label) { |
| - OutputJump(Bytecode::kJumpIfUndefined, label); |
| + OutputJumpIfUndefined(label, 0); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( |
| BytecodeLabel* label) { |
| - OutputJump(Bytecode::kJumpIfNotHole, label); |
| + OutputJumpIfNotHole(label, 0); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label, |
| int loop_depth) { |
| - OutputJump(Bytecode::kJumpLoop, UnsignedOperand(loop_depth), label); |
| + OutputJumpLoop(label, 0, loop_depth); |
| return *this; |
| } |
| @@ -625,44 +724,42 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StackCheck(int position) { |
| // statement's position. |
| latest_source_info_.ForceExpressionPosition(position); |
| } |
| - Output(Bytecode::kStackCheck); |
| + OutputStackCheck(); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() { |
| - Output(Bytecode::kThrow); |
| + OutputThrow(); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() { |
| - Output(Bytecode::kReThrow); |
| + OutputReThrow(); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { |
| SetReturnPosition(); |
| - Output(Bytecode::kReturn); |
| + OutputReturn(); |
| return_seen_in_block_ = true; |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::Debugger() { |
| - Output(Bytecode::kDebugger); |
| + OutputDebugger(); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare( |
| Register receiver, RegisterList cache_info_triple) { |
| DCHECK_EQ(3, cache_info_triple.register_count()); |
| - Output(Bytecode::kForInPrepare, RegisterOperand(receiver), |
| - RegisterOperand(cache_info_triple.first_register())); |
| + OutputForInPrepare(receiver, cache_info_triple); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::ForInContinue( |
| Register index, Register cache_length) { |
| - Output(Bytecode::kForInContinue, RegisterOperand(index), |
| - RegisterOperand(cache_length)); |
| + OutputForInContinue(index, cache_length); |
| return *this; |
| } |
| @@ -670,27 +767,24 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext( |
| Register receiver, Register index, RegisterList cache_type_array_pair, |
| int feedback_slot) { |
| DCHECK_EQ(2, cache_type_array_pair.register_count()); |
| - Output(Bytecode::kForInNext, RegisterOperand(receiver), |
| - RegisterOperand(index), |
| - RegisterOperand(cache_type_array_pair.first_register()), |
| - UnsignedOperand(feedback_slot)); |
| + OutputForInNext(receiver, index, cache_type_array_pair, feedback_slot); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) { |
| - Output(Bytecode::kForInStep, RegisterOperand(index)); |
| + OutputForInStep(index); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::SuspendGenerator( |
| Register generator) { |
| - Output(Bytecode::kSuspendGenerator, RegisterOperand(generator)); |
| + OutputSuspendGenerator(generator); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator( |
| Register generator) { |
| - Output(Bytecode::kResumeGenerator, RegisterOperand(generator)); |
| + OutputResumeGenerator(generator); |
| return *this; |
| } |
| @@ -724,16 +818,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
| int feedback_slot, |
| TailCallMode tail_call_mode) { |
| if (tail_call_mode == TailCallMode::kDisallow) { |
| - Output(Bytecode::kCall, RegisterOperand(callable), |
| - RegisterOperand(args.first_register()), |
| - UnsignedOperand(args.register_count()), |
| - UnsignedOperand(feedback_slot)); |
| + OutputCall(callable, args, args.register_count(), feedback_slot); |
| } else { |
| DCHECK(tail_call_mode == TailCallMode::kAllow); |
| - Output(Bytecode::kTailCall, RegisterOperand(callable), |
| - RegisterOperand(args.first_register()), |
| - UnsignedOperand(args.register_count()), |
| - UnsignedOperand(feedback_slot)); |
| + OutputTailCall(callable, args, args.register_count(), feedback_slot); |
| } |
| return *this; |
| } |
| @@ -741,10 +829,7 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, |
| BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor, |
| RegisterList args, |
| int feedback_slot_id) { |
| - Output(Bytecode::kNew, RegisterOperand(constructor), |
| - RegisterOperand(args.first_register()), |
| - UnsignedOperand(args.register_count()), |
| - UnsignedOperand(feedback_slot_id)); |
| + OutputNew(constructor, args, args.register_count(), feedback_slot_id); |
| return *this; |
| } |
| @@ -752,17 +837,15 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime( |
| Runtime::FunctionId function_id, RegisterList args) { |
| DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size); |
| DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort); |
| - Bytecode bytecode; |
| - uint32_t id; |
| if (IntrinsicsHelper::IsSupported(function_id)) { |
| - bytecode = Bytecode::kInvokeIntrinsic; |
| - id = static_cast<uint32_t>(IntrinsicsHelper::FromRuntimeId(function_id)); |
| + IntrinsicsHelper::IntrinsicId intrinsic_id = |
| + IntrinsicsHelper::FromRuntimeId(function_id); |
| + OutputInvokeIntrinsic(static_cast<int>(intrinsic_id), args, |
| + args.register_count()); |
| } else { |
| - bytecode = Bytecode::kCallRuntime; |
| - id = static_cast<uint32_t>(function_id); |
| + OutputCallRuntime(static_cast<int>(function_id), args, |
| + args.register_count()); |
| } |
| - Output(bytecode, id, RegisterOperand(args.first_register()), |
| - UnsignedOperand(args.register_count())); |
| return *this; |
| } |
| @@ -782,10 +865,8 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( |
| DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size); |
| DCHECK(Bytecodes::SizeForUnsignedOperand(function_id) <= OperandSize::kShort); |
| DCHECK_EQ(2, return_pair.register_count()); |
| - Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id), |
| - RegisterOperand(args.first_register()), |
| - UnsignedOperand(args.register_count()), |
| - RegisterOperand(return_pair.first_register())); |
| + OutputCallRuntimeForPair(static_cast<uint16_t>(function_id), args, |
| + args.register_count(), return_pair); |
| return *this; |
| } |
| @@ -797,19 +878,17 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair( |
| BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index, |
| RegisterList args) { |
| - Output(Bytecode::kCallJSRuntime, UnsignedOperand(context_index), |
| - RegisterOperand(args.first_register()), |
| - UnsignedOperand(args.register_count())); |
| + OutputCallJSRuntime(context_index, args, args.register_count()); |
| return *this; |
| } |
| BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object, |
| LanguageMode language_mode) { |
| if (language_mode == SLOPPY) { |
| - Output(Bytecode::kDeletePropertySloppy, RegisterOperand(object)); |
| + OutputDeletePropertySloppy(object); |
| } else { |
| DCHECK_EQ(language_mode, STRICT); |
| - Output(Bytecode::kDeletePropertyStrict, RegisterOperand(object)); |
| + OutputDeletePropertyStrict(object); |
| } |
| return *this; |
| } |
| @@ -850,88 +929,50 @@ bool BytecodeArrayBuilder::RegisterIsValid(Register reg) const { |
| } |
| } |
| -bool BytecodeArrayBuilder::OperandsAreValid( |
| - Bytecode bytecode, int operand_count, uint32_t operand0, uint32_t operand1, |
| - uint32_t operand2, uint32_t operand3) const { |
| - if (Bytecodes::NumberOfOperands(bytecode) != operand_count) { |
| - return false; |
| - } |
| - |
| - uint32_t operands[] = {operand0, operand1, operand2, operand3}; |
| - const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode); |
| - for (int i = 0; i < operand_count; ++i) { |
| - switch (operand_types[i]) { |
| - case OperandType::kNone: |
| +bool BytecodeArrayBuilder::RegisterListIsValid(RegisterList reg_list) const { |
| + if (reg_list.register_count() == 0) { |
| + return reg_list.first_register() == Register(0); |
| + } else { |
| + int first_reg_index = reg_list.first_register().index(); |
| + for (int i = 0; i < reg_list.register_count(); i++) { |
| + if (!RegisterIsValid(Register(first_reg_index + i))) { |
| return false; |
| - case OperandType::kFlag8: |
| - case OperandType::kIntrinsicId: |
| - if (Bytecodes::SizeForUnsignedOperand(operands[i]) > |
| - OperandSize::kByte) { |
| - return false; |
| - } |
| - break; |
| - case OperandType::kRuntimeId: |
| - if (Bytecodes::SizeForUnsignedOperand(operands[i]) > |
| - OperandSize::kShort) { |
| - return false; |
| - } |
| - break; |
| - case OperandType::kIdx: |
| - // TODO(leszeks): Possibly split this up into constant pool indices and |
| - // other indices, for checking. |
| - break; |
| - case OperandType::kUImm: |
| - case OperandType::kImm: |
| - break; |
| - case OperandType::kRegList: { |
| - CHECK_LT(i, operand_count - 1); |
| - CHECK(operand_types[i + 1] == OperandType::kRegCount); |
| - int reg_count = static_cast<int>(operands[i + 1]); |
| - if (reg_count == 0) { |
| - return Register::FromOperand(operands[i]) == Register(0); |
| - } else { |
| - Register start = Register::FromOperand(operands[i]); |
| - Register end(start.index() + reg_count - 1); |
| - if (!RegisterIsValid(start) || !RegisterIsValid(end) || start > end) { |
| - return false; |
| - } |
| - } |
| - i++; // Skip past kRegCount operand. |
| - break; |
| - } |
| - case OperandType::kReg: |
| - case OperandType::kRegOut: { |
| - Register reg = Register::FromOperand(operands[i]); |
| - if (!RegisterIsValid(reg)) { |
| - return false; |
| - } |
| - break; |
| - } |
| - case OperandType::kRegOutPair: |
| - case OperandType::kRegPair: { |
| - Register reg0 = Register::FromOperand(operands[i]); |
| - Register reg1 = Register(reg0.index() + 1); |
| - if (!RegisterIsValid(reg0) || !RegisterIsValid(reg1)) { |
| - return false; |
| - } |
| - break; |
| - } |
| - case OperandType::kRegOutTriple: { |
| - Register reg0 = Register::FromOperand(operands[i]); |
| - Register reg1 = Register(reg0.index() + 1); |
| - Register reg2 = Register(reg0.index() + 2); |
| - if (!RegisterIsValid(reg0) || !RegisterIsValid(reg1) || |
| - !RegisterIsValid(reg2)) { |
| - return false; |
| - } |
| - break; |
| } |
| - case OperandType::kRegCount: |
| - UNREACHABLE(); // Dealt with in kRegList above. |
| } |
| + return true; |
| } |
| +} |
| + |
| +void BytecodeArrayBuilder::PrepareToOutputBytecode(Bytecode bytecode) { |
| + if (register_optimizer_) register_optimizer_->PrepareForBytecode(bytecode); |
| +} |
| + |
| +uint32_t BytecodeArrayBuilder::GetInputRegisterOperand(Register reg) { |
| + DCHECK(RegisterIsValid(reg)); |
| + if (register_optimizer_) reg = register_optimizer_->GetInputRegister(reg); |
| + return static_cast<uint32_t>(reg.ToOperand()); |
| +} |
| + |
| +uint32_t BytecodeArrayBuilder::GetOutputRegisterOperand(Register reg) { |
| + DCHECK(RegisterIsValid(reg)); |
| + if (register_optimizer_) register_optimizer_->PrepareOutputRegister(reg); |
| + return static_cast<uint32_t>(reg.ToOperand()); |
| +} |
| + |
| +uint32_t BytecodeArrayBuilder::GetInputRegisterListOperand( |
| + RegisterList reg_list) { |
| + DCHECK(RegisterListIsValid(reg_list)); |
| + if (register_optimizer_) |
| + reg_list = register_optimizer_->GetInputRegisterList(reg_list); |
| + return static_cast<uint32_t>(reg_list.first_register().ToOperand()); |
| +} |
| - return true; |
| +uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand( |
| + RegisterList reg_list) { |
| + DCHECK(RegisterListIsValid(reg_list)); |
| + if (register_optimizer_) |
| + register_optimizer_->PrepareOutputRegisterList(reg_list); |
| + return static_cast<uint32_t>(reg_list.first_register().ToOperand()); |
| } |
| } // namespace interpreter |