diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-03-08 10:28:10 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-03-20 13:40:30 +0000 |
commit | e733310db58160074f574c429d48f8308c0afe17 (patch) | |
tree | f8aef4b7e62a69928dbcf880620eece20f98c6df /chromium/v8/src/interpreter/bytecode-array-builder.cc | |
parent | 2f583e4aec1ae3a86fa047829c96b310dc12ecdf (diff) | |
download | qtwebengine-chromium-e733310db58160074f574c429d48f8308c0afe17.tar.gz |
BASELINE: Update Chromium to 56.0.2924.122
Change-Id: I4e04de8f47e47e501c46ed934c76a431c6337ced
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/v8/src/interpreter/bytecode-array-builder.cc')
-rw-r--r-- | chromium/v8/src/interpreter/bytecode-array-builder.cc | 661 |
1 files changed, 367 insertions, 294 deletions
diff --git a/chromium/v8/src/interpreter/bytecode-array-builder.cc b/chromium/v8/src/interpreter/bytecode-array-builder.cc index dfa395095ab..904a8e021d8 100644 --- a/chromium/v8/src/interpreter/bytecode-array-builder.cc +++ b/chromium/v8/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,14 +46,12 @@ BytecodeArrayBuilder::BytecodeArrayBuilder( } if (FLAG_ignition_reo) { - pipeline_ = new (zone) BytecodeRegisterOptimizer( + register_optimizer_ = new (zone) BytecodeRegisterOptimizer( zone, ®ister_allocator_, fixed_register_count(), parameter_count, pipeline_); } - return_position_ = - literal ? std::max(literal->start_position(), literal->end_position() - 1) - : kNoSourcePosition; + return_position_ = literal ? literal->return_position() : kNoSourcePosition; } Register BytecodeArrayBuilder::first_context_register() const { @@ -75,108 +74,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 +300,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 +322,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 +356,7 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation( BytecodeArrayBuilder& BytecodeArrayBuilder::LoadConstantPoolEntry( size_t entry) { - Output(Bytecode::kLdaConstant, UnsignedOperand(entry)); + OutputLdaConstant(entry); return *this; } @@ -258,70 +364,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 +448,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 +459,22 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal( BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context, int slot_index, int depth) { - Output(Bytecode::kLdaContextSlot, RegisterOperand(context), - UnsignedOperand(slot_index), UnsignedOperand(depth)); + if (context.is_current_context() && depth == 0) { + OutputLdaCurrentContextSlot(slot_index); + } else { + 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)); + if (context.is_current_context() && depth == 0) { + OutputStaCurrentContextSlot(slot_index); + } else { + OutputStaContextSlot(context, slot_index, depth); + } return *this; } @@ -360,10 +482,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 +493,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 +520,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 +531,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 +546,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 +558,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 +583,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 +603,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 +620,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 +635,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 +685,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 +738,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 +781,36 @@ 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::StoreModuleVariable(int cell_index, + int depth) { + OutputStaModuleVariable(cell_index, depth); + return *this; +} + +BytecodeArrayBuilder& BytecodeArrayBuilder::LoadModuleVariable(int cell_index, + int depth) { + OutputLdaModuleVariable(cell_index, depth); 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; } @@ -722,18 +842,18 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) { BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, RegisterList args, int feedback_slot, + Call::CallType call_type, 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)); + if (call_type == Call::NAMED_PROPERTY_CALL || + call_type == Call::KEYED_PROPERTY_CALL) { + OutputCallProperty(callable, args, args.register_count(), feedback_slot); + } else { + 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 +861,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 +869,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 +897,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 +910,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 +961,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 |