| 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..7f22ccbb4b7eb00efcecdecc0b6e0f38c59bf9fc 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_);
|
| }
|
| @@ -75,108 +76,222 @@ 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)) {
|
| + source_position = latest_source_info_;
|
| + latest_source_info_.set_invalid();
|
| + }
|
| + }
|
| + 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);
|
| -}
|
| + INLINE(static uint32_t Convert(BytecodeArrayBuilder* builder, int value)) {
|
| + 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);
|
| -}
|
| + private:
|
| + static bool IsValid(size_t value) {
|
| + 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);
|
| + }
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +template <OperandType... operand_types>
|
| +class BytecodeNodeBuilder {
|
| + public:
|
| + template <typename... Operands>
|
| + INLINE(static BytecodeNode Make(BytecodeArrayBuilder* builder,
|
| + BytecodeSourceInfo source_info,
|
| + Bytecode bytecode, Operands... operands)) {
|
| + builder->PrepareToOutputBytecode(bytecode);
|
| + // The "OperandHelper<operand_types>::Convert(builder, operands)..." will
|
| + // expand both the OperandType... and Operands... parameter packs e.g. for:
|
| + // BytecodeNodeBuilder<OperandType::kReg, OperandType::kImm>::Make<
|
| + // Register, int>(..., Register reg, int immediate)
|
| + // the code will expand into:
|
| + // OperandHelper<OperandType::kReg>::Convert(builder, reg),
|
| + // OperandHelper<OperandType::kImm>::Convert(builder, immediate),
|
| + return BytecodeNode(
|
| + bytecode, OperandHelper<operand_types>::Convert(builder, operands)...,
|
| + source_info);
|
| + }
|
| +};
|
| +
|
| +#define DEFINE_BYTECODE_OUTPUT(name, accumulator_use, ...) \
|
| + template <typename... Operands> \
|
| + void BytecodeArrayBuilder::Output##name(Operands... operands) { \
|
| + BytecodeNode node(BytecodeNodeBuilder<__VA_ARGS__>::Make<Operands...>( \
|
| + this, CurrentSourcePosition(Bytecode::k##name), Bytecode::k##name, \
|
| + operands...)); \
|
| + 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...>( \
|
| + this, CurrentSourcePosition(Bytecode::k##name), Bytecode::k##name, \
|
| + operands...)); \
|
| + 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 +302,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 +324,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 +358,7 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
|
|
|
| BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry(
|
| size_t entry) {
|
| - Output(Bytecode::kLdaConstant, UnsignedOperand(entry));
|
| + OutputLdaConstant(entry);
|
| return *this;
|
| }
|
|
|
| @@ -258,70 +366,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 +450,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 +461,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 +476,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 +487,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 +514,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 +525,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 +540,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 +552,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 +577,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 +597,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 +614,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 +629,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 +679,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 +732,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 +775,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 +826,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 +837,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 +845,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 +873,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 +886,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 +937,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
|
|
|